初始化版本
This commit is contained in:
133
api/videos.php
Normal file
133
api/videos.php
Normal file
@@ -0,0 +1,133 @@
|
||||
<?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);
|
||||
Reference in New Issue
Block a user