如何获取iframe嵌入视频与video标签视频的时长
同时获取iframe嵌入视频与原生video标签视频时长的实现方案
核心前提
浏览器同源策略会限制跨域iframe的DOM访问,第三方平台(比如YouTube)嵌入的iframe视频,无法直接通过DOM操作读取内部视频元素的属性,必须通过平台官方提供的JS SDK做交互才能拿到时长等数据;如果是同域名下的iframe,不存在跨域限制,可以直接读取内部video元素。
另外不管是哪种视频,都要等元数据加载完成后再读取时长,否则会拿到NaN无效值。
第一步:页面结构调整
保留原有video标签,给iframe元素加唯一id,嵌入第三方视频时记得开启平台要求的API支持参数:
<button onclick="getAllVideoDuration()" type="button">获取视频时长</button><br> <!-- 原有原生video标签 --> <video id="myVideo" width="320" height="176" controls> <source src="https://dev.theappkit.co.uk/stylco/public/images/hair_styles/0_427_serena_grant_1619797376.mp4" type="video/mp4"> 你的浏览器不支持HTML5 video标签 </video> <!-- 示例YouTube嵌入iframe,其他平台替换对应src即可,记得开启API参数 --> <iframe id="thirdPartyVideo" width="560" height="315" src="https://www.youtube.com/embed/对应视频ID?enablejsapi=1" frameborder="0" allowfullscreen> </iframe>
第二步:分场景实现时长获取逻辑
1. 原生video标签时长获取
优化原有逻辑,增加元数据加载判断,避免拿到无效值:
// 获取原生video标签时长 function getNativeVideoDuration(videoEl) { return new Promise((resolve, reject) => { // 元数据已加载直接返回 if (videoEl.readyState >= 1) { resolve(videoEl.duration) return } // 元数据加载完成后返回 videoEl.addEventListener('loadedmetadata', () => resolve(videoEl.duration), { once: true }) videoEl.addEventListener('error', reject, { once: true }) }) }
2. iframe嵌入视频时长获取
- 同域名iframe:直接通过
iframe.contentDocument.querySelector('video')拿到内部video元素,复用上面的原生video获取逻辑即可 - 第三方跨域iframe:加载对应平台的官方JS SDK,初始化播放器实例后,通过SDK提供的方法获取时长。以下以YouTube为例,其他平台(Vimeo、国内各视频平台)逻辑完全一致,替换对应SDK和API方法即可:
// 存储iframe播放器实例 const playerMap = {} // 初始化第三方iframe播放器 function initThirdPartyPlayer() { // 此处加载对应平台的JS SDK,以YouTube为例 window.YT.ready(() => { playerMap.thirdPartyVideo = new YT.Player('thirdPartyVideo', { events: { onReady: () => console.log('第三方播放器初始化完成') } }) }) } // 获取第三方iframe视频时长 function getIframeVideoDuration(iframeId) { return new Promise((resolve, reject) => { const player = playerMap[iframeId] if (!player) return reject('播放器未初始化') // YouTube对应获取时长的方法为getDuration(),其他平台替换为对应官方API方法 const getDuration = () => player.getDuration() let duration = getDuration() if (duration > 0) return resolve(duration) // 时长未加载完成时轮询等待 const timer = setInterval(() => { duration = getDuration() if (duration > 0) { clearInterval(timer) resolve(duration) } }, 200) }) }
第三步:统一调用入口
// 统一获取所有视频时长 async function getAllVideoDuration() { try { // 获取原生video时长 const nativeVideoEl = document.getElementById('myVideo') const nativeDuration = await getNativeVideoDuration(nativeVideoEl) alert(`原生视频时长:${nativeDuration}秒`) // 获取iframe视频时长 const iframeDuration = await getIframeVideoDuration('thirdPartyVideo') alert(`iframe嵌入视频时长:${iframeDuration}秒`) } catch (err) { console.error('获取视频时长失败:', err) } } // 保留原有视频播放结束监听 document.getElementById('myVideo').addEventListener('ended', () => { alert("视频播放结束") }, false) // 页面加载完成后初始化第三方播放器 window.addEventListener('load', initThirdPartyPlayer)
注意事项
- 不要尝试通过跨域漏洞、代理页面等非官方方式读取第三方iframe内容,这类方法稳定性极差,且可能违反对应平台的使用规则
- 不同第三方视频平台的SDK初始化、时长获取方法名有差异,直接参考对应平台官方文档的API说明替换即可,核心逻辑不变
- 如果页面有多个iframe视频,给每个iframe设唯一id,分别初始化播放器实例存入
playerMap即可批量获取时长
内容的提问来源于stack exchange,提问作者Avinash Kumar
相关产品推荐
相关产品推荐

