WordPress中用JavaScript获取YouTube视频时长的问题
解决WordPress中嵌入YouTube视频无法获取时长的问题
我太懂这种憋屈了——WordPress(尤其是用Elementor这类编辑器时)总给YouTube iframe套一堆冗余的div和脚本,不仅定位元素麻烦,更关键是跨域限制让你根本拿不到视频的时间数据。原来的代码对本地视频有效,但YouTube iframe受同源策略保护,直接访问currentTime这类属性完全行不通。
下面是靠谱的解决方案,用YouTube官方的IFrame API来实现你的需求:
第一步:加载YouTube IFrame API
你可以在主题的functions.php里添加这段代码,或者直接在页面底部(比如footer模板)插入脚本,确保API能正常加载:
// 在WordPress中加载YouTube IFrame API function enqueue_youtube_api() { wp_enqueue_script( 'youtube-api', 'https://www.youtube.com/iframe_api', array(), null, true ); } add_action( 'wp_enqueue_scripts', 'enqueue_youtube_api' );
嫌麻烦的话直接在HTML里加也行:
<script src="https://www.youtube.com/iframe_api"></script>
第二步:给YouTube iframe加可识别标记
在Elementor编辑视频时,要么给每个视频的iframe设置唯一ID(比如youtube-video-1和youtube-video-2),要么确保你的自定义类(phone-video-1/phone-video-2)能精准定位到包含iframe的容器。
第三步:重写你的JavaScript代码
用YouTube API监听视频事件,安全获取时长和当前时间,替换你原来的代码:
// 修复时间格式化函数(原函数存在重复拼接的bug) function fancyTimeFormat(time) { const hrs = Math.floor(time / 3600); const mins = Math.floor((time % 3600) / 60); const secs = Math.floor(time % 60); let timeParts = []; if (hrs > 0) { timeParts.push(hrs.toString().padStart(2, '0')); } timeParts.push(mins.toString().padStart(2, '0')); timeParts.push(secs.toString().padStart(2, '0')); return timeParts.join(':'); } // 声明全局播放器实例 let player1, player2; // API加载完成后初始化播放器 function onYouTubeIframeAPIReady() { // 初始化第一个视频 const videoFrame1 = document.querySelector('.phone-video-1 iframe'); if (videoFrame1) { const videoId = getYouTubeVideoId(videoFrame1.src); player1 = new YT.Player(videoFrame1, { videoId: videoId, events: { 'onReady': handlePlayerReady, 'onStateChange': handlePlayerStateChange } }); } // 初始化第二个视频 const videoFrame2 = document.querySelector('.phone-video-2 iframe'); if (videoFrame2) { const videoId = getYouTubeVideoId(videoFrame2.src); player2 = new YT.Player(videoFrame2, { videoId: videoId, events: { 'onReady': handlePlayerReady, 'onStateChange': handlePlayerStateChange } }); } // 启动计时器更新循环 startTimerUpdates(); } // 从YouTube URL中提取视频ID function getYouTubeVideoId(url) { const regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; const matchResult = url.match(regex); return (matchResult && matchResult[2].length === 11) ? matchResult[2] : null; } // 播放器就绪时的回调(可在这里获取总时长) function handlePlayerReady(event) { const player = event.target; // 如需获取总时长:const totalDuration = player.getDuration(); } // 播放器状态变化时的回调 function handlePlayerStateChange(event) { // 状态码说明:-1=未开始,0=播放结束,1=正在播放,2=暂停,3=缓冲中,5=视频已加载 if (event.data === YT.PlayerState.PLAYING) { // 可在这里添加播放开始时的额外逻辑 } } // 每秒更新一次计时器 function startTimerUpdates() { setInterval(() => { // 更新第一个视频的计时器 if (player1 && player1.getPlayerState() === YT.PlayerState.PLAYING) { const currentTime = player1.getCurrentTime(); let displayTime = fancyTimeFormat(Math.round(currentTime)); // 实现你原来的时间偏移逻辑(3-5秒时减2秒) if (displayTime >= '00:00:03' && displayTime <= '00:00:05') { displayTime = fancyTimeFormat(Math.round(currentTime - 2)); } else if (displayTime === '00:00:00') { displayTime = fancyTimeFormat(0); } const firstTimer = document.getElementById('first-video-timer'); if (firstTimer) { const timerPara = firstTimer.querySelector('p') || firstTimer; timerPara.textContent = displayTime; } } // 更新第二个视频的计时器 if (player2 && player2.getPlayerState() === YT.PlayerState.PLAYING) { const currentTime = player2.getCurrentTime(); const displayTime = fancyTimeFormat(Math.round(currentTime)); const secondTimer = document.getElementById('second-video-timer'); if (secondTimer) { const timerPara = secondTimer.querySelector('p') || secondTimer; timerPara.textContent = displayTime; } } }, 1000); }
关键细节说明:
- 跨域问题彻底解决:YouTube IFrame API是官方提供的合法途径,绕开了同源策略限制,能安全获取所有视频时间数据。
- Elementor兼容无压力:不管WordPress给iframe套多少层div,只要能定位到iframe元素,提取视频ID就能初始化播放器。
- 修复了时间格式化bug:原函数在有小时数时会出现重复拼接(比如
1:02:0300:02:03),现在用数组拼接的方式更可靠。 - 计时器更新更稳定:用
setInterval每秒更新一次,替代原来的timeupdate事件(API没有直接的timeupdate,但每秒轮询足够精准)。
如果你的Elementor视频是自动嵌入的,找不到iframe的话,可以用document.querySelector('.phone-video-1 .elementor-widget-video iframe')来定位,只要选择器能准确找到对应的iframe就行。
内容的提问来源于stack exchange,提问作者fbalu13
相关产品推荐
相关产品推荐

