134 lines
5.6 KiB
PHP
134 lines
5.6 KiB
PHP
<?php
|
||
// 代理获取视频地址的接口:从多个来源“随机/顺序”获取 1~N 条视频地址,并返回统一格式
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
// 指定来源功能已取消:统一按优先级尝试全部来源;如需随机请使用 ?random=1
|
||
// 支持的远程来源(按优先级尝试,默认启用全部并按优先级依次尝试)
|
||
$endpoints = [
|
||
'https://api.kuleu.com/api/MP4_xiaojiejie?type=json', // 新增来源(纯视频URL或JSON)
|
||
'https://v2.xxapi.cn/api/meinv', // 新来源(JSON: {code,data})
|
||
'https://api.iyuns.com/api/meinv', // 旧来源(JSON: {code,data})
|
||
'https://api.kuleu.com/api/xjj?type=json', // 新增来源(JSON: {code,data})
|
||
'https://api.dwo.cc/api/ksvideo?type=json', // 新增来源(JSON: {code,data})
|
||
'https://v2.api-m.com/api/meinv?type=json', // 新增来源(JSON: {code,data})
|
||
'https://api.mhimg.cn/api/Sj_girls_video?type=json', // 新增来源(JSON: {code,data})
|
||
];
|
||
// 随机获取:默认开启;如需关闭可用 ?random=0
|
||
$randomParam = $_GET['random'] ?? null;
|
||
$random = !isset($randomParam) ? true : (intval($randomParam) === 1);
|
||
$count = intval($_GET['count'] ?? 1);
|
||
if ($count < 1) $count = 1; if ($count > 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);
|