5) $count = 5; // 限制最多5条 // 是否包含本地视频的开关 $includeLocal = intval($_GET['include_local'] ?? 0) === 1; // 本地视频条数上限(当开启包含本地时生效,默认与远程条数相同) $localCount = intval($_GET['local_count'] ?? $count); if ($localCount < 0) $localCount = 0; if ($localCount > 10) $localCount = 10; // 限制一次最多10条本地视频 function fetch_remote_url($endpoint) { // 使用 curl 更稳妥地请求第三方接口 $ch = curl_init($endpoint); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 8, CURLOPT_TIMEOUT => 12, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_USERAGENT => 'VideoFetcher/1.0', ]); $body = curl_exec($ch); $err = curl_error($ch); curl_close($ch); if ($err) { return null; } $json = json_decode($body, true); $candidate = ''; if (is_array($json)) { // 某些接口包含 code 字段,若存在则需为 200 if (array_key_exists('code', $json) && intval($json['code']) !== 200) { return null; } // 兼容不同字段名:mp4_video、data、url、mp4、video foreach (['mp4_video','data','url','mp4','video','pic'] as $key) { if (!empty($json[$key]) && is_string($json[$key])) { $candidate = $json[$key]; break; } } } else { // 非JSON:可能直接返回URL $candidate = trim((string)$body); } // 清理反引号和空白 $candidate = preg_replace('/[`\s]/', '', (string)$candidate); // 简单校验:必须是 http/https,且 URL 中包含常见视频扩展(允许出现在路径或查询字符串中) if (!$candidate || !preg_match('/^https?:\/\//i', $candidate)) { return null; } if (!preg_match('/\.(mp4|webm|mov)(?![A-Za-z])/i', $candidate)) { return null; } return $candidate; } // 远程接口视频列表 $remote = []; for ($i = 0; $i < $count; $i++) { $u = null; // 依次尝试多个来源,取第一个成功的(随机模式下,每次尝试顺序打乱) $epOrder = $endpoints; if ($random && count($epOrder) > 1) { shuffle($epOrder); } foreach ($epOrder as $ep) { $u = fetch_remote_url($ep); if ($u) { break; } } if ($u) { $remote[] = [ 'url' => $u, 'title' => '接口视频 ' . ($i + 1), ]; } } // 随机模式下,对远程列表打乱顺序 if ($random && count($remote) > 1) { shuffle($remote); } // 同时把本地已保存的视频加入列表(可选) $videosRoot = __DIR__ . '/../videos'; $local = []; // 构建本地视频列表,用于开关合并或远程失败时的回退 if (is_dir($videosRoot)) { $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($videosRoot)); foreach ($rii as $file) { if ($file->isFile()) { $ext = strtolower(pathinfo($file->getFilename(), PATHINFO_EXTENSION)); if (in_array($ext, ['mp4','webm','mov'])) { // 构造相对URL供前端播放 $rel = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $file->getPathname())); $local[] = [ 'url' => $rel, 'title' => '本地:' . $file->getFilename() ]; } } } // 本地视频顺序随机并裁剪到指定数量 if (count($local) > 1) { shuffle($local); } if ($localCount > 0 && count($local) > $localCount) { $local = array_slice($local, 0, $localCount); } } // 合并/回退策略: // 1) 远程成功: // - 如果开启本地,则远程+本地合并并整体随机 // - 如果未开启本地,则仅远程 // 2) 远程失败: // - 若本地有内容,则仅返回本地随机列表(忽略开关) $list = []; if (!empty($remote)) { $list = $includeLocal ? array_merge($remote, $local) : $remote; if (count($list) > 1 && ($includeLocal || $random)) { shuffle($list); } } else if (!empty($local)) { $list = $local; // 远程不可用时,回退到全部本地随机 } // 如果仍为空,提供一个后备示例 if (empty($list)) { $list[] = [ 'url' => 'https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4', 'title' => '示例视频' ]; } echo json_encode(['list' => $list], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);