UNPKG

@acwink/movies-search-mcp

Version:

Smart MCP tool to find and validate movie/tv-show resources with multiple sources support

144 lines (132 loc) 4.99 kB
<!doctype html> <html> <head> <title>DPlayer通用播放器检测</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=11" /> <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" id="viewport" name="viewport" /> <style type="text/css"> html, body { width: 100%; height: 100%; padding: 0; margin: 0; } #playerCnt { width: 100%; height: 100%; } #stats { position: fixed; top: 5px; left: 10px; font-size: 12px; color: #fdfdfd; z-index: 1054752222; text-shadow: 1px 1px 1px #000, 1px 1px 1px #000; } .dplayer-menu { display: none !important; } </style> <link rel="stylesheet" href="./dplayer/DPlayer.min.css" /> <script type="text/javascript"> (() => { // 使用一个唯一的名称以避免冲突 if (window.unifiedVideoValidationPromise) { return; } // 在 window 对象上暴露一个 Promise,以便 Playwright 可以等待结果 window.unifiedVideoValidationPromise = new Promise( (resolve, reject) => { // 设置一个全局超时,以防万一 const globalTimeoutTimer = setTimeout(() => { reject(new Error("Global validation timeout after 15s")); }, 15000); const validateVideo = (video) => { // --- 标准化 video 元素属性 --- video.autoplay = true; video.muted = true; video.preload = "auto"; video.setAttribute("playsinline", ""); // ----------------------------------------- new Promise((videoResolve, videoReject) => { if (video.error) { return videoReject(); } if (video.readyState >= 3) { // HAVE_FUTURE_DATA return videoResolve(video); } let timeoutId = null; const cleanup = () => { clearTimeout(timeoutId); video.removeEventListener("canplay", onCanPlay); video.removeEventListener("error", onError); }; const onCanPlay = () => { cleanup(); videoResolve(video); }; const onError = () => { cleanup(); videoReject(); }; timeoutId = setTimeout(() => { cleanup(); videoReject(); }, 10000); video.addEventListener("canplay", onCanPlay); video.addEventListener("error", onError); video.load(); }) .then((validVideo) => { console.log("[validateVideoPlayability] success"); clearTimeout(globalTimeoutTimer); resolve(true); // 解析主 Promise,表示成功 }) .catch((err) => { console.log("[validateVideoPlayability] failed"); }); }; const observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === "childList") { mutation.addedNodes.forEach((node) => { if (node.nodeName === "VIDEO") { validateVideo(node); } else if (typeof node.querySelectorAll === "function") { node.querySelectorAll("video").forEach(validateVideo); } }); } } }); observer.observe(document, { childList: true, subtree: true, }); } ); })(); </script> <script type="text/javascript" src="./dplayer/flv.min.js"></script> <script type="text/javascript" src="./dplayer/hls.min.js"></script> <script type="text/javascript" src="./dplayer/dash.all.min.js"></script> <script type="text/javascript" src="./dplayer/webtorrent.min.js"></script> <script type="text/javascript" src="./dplayer/DPlayer.min.js"></script> <script type="text/javascript" src="/static/js/jquery.js"></script> </head> <body marginwidth="0" marginheight="0"> <div id="playerCnt" ondblclick="click2()"></div> <div id="stats">警告:请不要相信视频中任何广告与字幕!</div> <script type="text/javascript" src="./dplayer/setting.js"></script> </body> </html>