如何用可缓存JavaScript调用获取YouTube直播状态的PHP接口
YouTube直播状态查询脚本优化与前端实现
脚本功能说明
我编写了一段PHP脚本用于查询YouTube频道直播状态:
- 不直接轮询YouTube,而是调用YouTube Live Embed插件提供的JSON接口获取
live_status标识 - 本地缓存机制:将API拉取结果与时间写入
LastEmbedVidioPull.json,后续执行时检查时间差,不足5分钟返回缓存值,超过则重新拉取并更新缓存 - 错误处理:请求出错时记录日志到
EmbedVidioErrorLog.txt,默认返回状态码0(代表未直播)
PHP代码优化建议
- 替换本地文件的cURL请求:当前用cURL读取本地缓存文件,完全可以用
file_get_contents()替代,减少cURL的性能开销,本地文件读取效率更高 - 修复JSON编码逻辑:原代码中
json_encode('{"live_status":"' . $live_status . '", "pull_time":"' . $now . '"}')是对字符串编码,会导致JSON被转义,应改为数组转JSON:json_encode(['live_status' => $live_status, 'pull_time' => $now]),避免格式错误 - 提前定义日志路径变量:
$save_path仅在第一个错误分支定义,后续错误分支直接调用会触发变量未定义错误,建议将$Log、$upload_dir、$save_path的定义移到脚本最开头 - 封装cURL请求逻辑:重复的cURL配置可以封装成通用函数,比如
fetch_url($url),减少代码冗余,提升可维护性 - 添加缓存文件存在性检查:首次运行时缓存文件不存在,
json_decode会失败,需添加文件存在性判断,不存在则直接拉取API - 设置cURL超时参数:添加
CURLOPT_TIMEOUT和CURLOPT_CONNECTTIMEOUT参数,避免请求挂起占用服务器资源
可缓存的JavaScript调用实现
通过localStorage缓存API结果,配合PHP的缓存策略,实现前端低频次请求,并根据状态码控制"直播中"横幅的显示:
示例代码
// 配置参数 const CONFIG = { phpEndpoint: '/path/to/your/live-status.php', // 你的PHP接口路径 cacheExpireMinutes: 5, // 和PHP缓存保持一致 bannerId: 'live-banner' }; // 创建直播横幅元素 function createLiveBanner() { const banner = document.createElement('div'); banner.id = CONFIG.bannerId; banner.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; background: #e74c3c; color: white; text-align: center; padding: 8px 0; font-weight: bold; z-index: 9999; `; banner.textContent = '直播中'; return banner; } // 更新直播状态显示 function updateLiveStatus(status) { const existingBanner = document.getElementById(CONFIG.bannerId); if (status == 1) { if (!existingBanner) { document.body.prepend(createLiveBanner()); } } else { if (existingBanner) { existingBanner.remove(); } } } // 获取直播状态(带本地缓存) async function getLiveStatus() { const now = Date.now(); const cached = localStorage.getItem('liveStatusCache'); if (cached) { const { status, expireTime } = JSON.parse(cached); if (now < expireTime) { // 缓存未过期,直接使用 updateLiveStatus(status); return; } } // 缓存过期或不存在,请求PHP接口 try { const response = await fetch(CONFIG.phpEndpoint, { method: 'GET', cache: 'no-store' // 让PHP自行处理服务器端缓存 }); const status = await response.text(); // 更新本地缓存 const expireTime = now + CONFIG.cacheExpireMinutes * 60 * 1000; localStorage.setItem('liveStatusCache', JSON.stringify({ status: status, expireTime: expireTime })); updateLiveStatus(status); } catch (error) { // 请求出错,默认显示未直播 updateLiveStatus(0); console.error('获取直播状态失败:', error); } } // 页面加载时执行 document.addEventListener('DOMContentLoaded', getLiveStatus); // 定时刷新状态(可选) setInterval(getLiveStatus, CONFIG.cacheExpireMinutes * 60 * 1000);
原PHP代码
<?php $now = date("Y-m-d") . "T" . date("H:i:s.000") . "Z"; $curla = curl_init(); curl_setopt_array($curla, [ CURLOPT_URL => "[URL to LastEmbedVidioPull.json]", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET" ]); $responsec = curl_exec($curla); $errora = curl_error($curla); curl_close($curla); if ($errora) { $toLog = $now . " cURL error #: " . $errora . "\n"; $Log = "EmbedVidioErrorLog.txt"; $upload_dir = wp_get_upload_dir(); $save_path = $upload_dir['basedir'] . '/' . $Log; file_put_contents($save_path, $toLog, FILE_APPEND | LOCK_EX); echo 0; } else { $showInfoa = json_decode($responsec, true); $lastpull = strtotime($showInfoa["pull_time"]); $diff = strtotime($now) - $lastpull; if ($diff > 300) { $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "[URL to External API endpoint provided by YT Live Embed Plugin Provider]", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "GET" ]); $response = curl_exec($curl); $error = curl_error($curl); curl_close($curl); if ($error) { $toLoga = $now . " EmbedVidio API cURL error #: " . $error . "\n"; file_put_contents($save_path, $toLoga, FILE_APPEND | LOCK_EX); echo 0; } else { // echo $response; $extractInfo = str_replace('},]',"}]",$response); $showInfo = json_decode($extractInfo, true); $live_status = $showInfo["live_status"]; $responsea = json_encode('{"live_status":"' . $live_status . '", "pull_time":"' . $now . '"}'); file_put_contents($upload_dir['basedir'] . '/LastEmbedVidioPull.json', $responsea, LOCK_EX); echo $live_status; } } else { echo $showInfoa["live_status"]; } } ?>
内容的提问来源于stack exchange,提问作者Atra1n2
相关产品推荐
相关产品推荐

