如何检测多iframe中的视频源并获取video.currentTime?
检测iframe里视频的播放进度和源的可行办法
先说说你原来代码的问题:
- 只盯着当前激活的iframe,其他没被选中的iframe根本检测不到
- 硬写死只找id是
mainly的iframe,多iframe场景下完全没用 - 最关键的是浏览器的同源安全限制:如果iframe是mega.nz、gdrive这种第三方网站,父页面根本没法直接访问iframe内部的元素(包括video和它的播放进度)
下面分情况给你解决思路:
一、自己能控制的iframe(比如直接嵌mp4、自己搭的JWPlayer)
这种情况可以直接改代码,覆盖所有iframe,实时检测:
改进后的代码
// 存一下每个iframe对应的视频对象 const videoMap = new Map(); function checkAllIframes() { // 遍历页面里所有的iframe document.querySelectorAll('iframe').forEach(iframe => { try { const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; if (!iframeDoc) return; // 找iframe里的video标签 const video = iframeDoc.querySelector('video'); if (video) { videoMap.set(iframe, video); // 监听播放进度变化,实时拿到currentTime video.addEventListener('timeupdate', () => { console.log(`来自${iframe.src}的视频进度:${video.currentTime}`); }); } else { // 视频元素没了就从map里删掉 videoMap.delete(iframe); } } catch (e) { // 报错就是跨域了,这个iframe是第三方的,没法直接访问 console.log(`没法访问这个跨域iframe:${iframe.src}`); } }); } // 每个iframe加载完后,等1秒再检测(确保视频元素已经渲染出来) document.querySelectorAll('iframe').forEach(iframe => { iframe.addEventListener('load', () => { setTimeout(checkAllIframes, 1000); }); }); // 每隔2秒全局扫一遍(应对动态新加的iframe) setInterval(checkAllIframes, 2000);
代码说明
- 不再死磕单个iframe,而是遍历所有iframe
- 用try-catch接住跨域错误,不会因为一个iframe搞崩整个脚本
- 监听iframe的load事件,每次切换视频源后自动重新检测
- 用video的
timeupdate事件实时拿进度,比定时轮询更高效
二、第三方跨域iframe(mega.nz、gdrive、别人的JWPlayer)
浏览器为了安全,不让不同网站的页面互相偷看内容,所以父页面没法直接碰这些iframe内部的东西,只能用间接办法:
1. 用第三方提供的API(如果有的话)
- Google Drive:可以用它的官方API,但要配置权限,而且只对你有权限的视频有用
- JWPlayer:如果是你自己部署的,可以用它的JS接口把进度传给父页面;如果是别人的JWPlayer,那就没戏了
- mega.nz:目前没公开的API支持外部拿播放进度
2. 用postMessage传消息
如果第三方网站支持主动给父页面发消息,那可以让它把进度传过来,但像mega.nz这种公共站点,一般不会给你这权限,除非你能自己套一层页面。
3. 自己做个代理页面(只适用于能拿到视频直链的情况)
把第三方视频的直链嵌到你自己域名下的一个页面里,这样这个代理页面和父页面是同个域名,就能直接访问视频进度,再把进度传给父页面。
比如代理页面(proxy-video.html):
<!DOCTYPE html> <html> <body> <video id="proxyVideo" controls></video> <script> const video = document.getElementById('proxyVideo'); // 接收父页面发来的视频地址 window.addEventListener('message', (e) => { if (e.data.type === 'LOAD_VIDEO') { video.src = e.data.url; } }); // 把播放进度发给父页面 video.addEventListener('timeupdate', () => { window.parent.postMessage({ type: 'VIDEO_PROGRESS', currentTime: video.currentTime }, 'https://你的父页面域名.com'); // 这里填父页面的域名,更安全 }); </script> </body> </html>
父页面里用这个代理iframe:
const proxyIframe = document.getElementById('proxyIframe'); // 给代理页面发消息,让它加载视频 proxyIframe.contentWindow.postMessage({ type: 'LOAD_VIDEO', url: '视频的直链地址' }, 'https://你的代理页面域名.com'); // 接收代理页面发来的进度 window.addEventListener('message', (e) => { if (e.data.type === 'VIDEO_PROGRESS') { console.log('当前视频进度:', e.data.currentTime); } });
最后总结下
- 自己能控制的iframe:直接用改进后的代码,遍历所有iframe就能拿到进度
- 第三方跨域iframe:要么找第三方的API,要么用代理页面中转(仅限能拿到直链的视频),否则基本没法直接获取进度
内容的提问来源于stack exchange,提问作者PHP NOOB
相关产品推荐
相关产品推荐

