You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

关键细节说明:

  1. 跨域问题彻底解决:YouTube IFrame API是官方提供的合法途径,绕开了同源策略限制,能安全获取所有视频时间数据。
  2. Elementor兼容无压力:不管WordPress给iframe套多少层div,只要能定位到iframe元素,提取视频ID就能初始化播放器。
  3. 修复了时间格式化bug:原函数在有小时数时会出现重复拼接(比如1:02:0300:02:03),现在用数组拼接的方式更可靠。
  4. 计时器更新更稳定:用setInterval每秒更新一次,替代原来的timeupdate事件(API没有直接的timeupdate,但每秒轮询足够精准)。

如果你的Elementor视频是自动嵌入的,找不到iframe的话,可以用document.querySelector('.phone-video-1 .elementor-widget-video iframe')来定位,只要选择器能准确找到对应的iframe就行。

内容的提问来源于stack exchange,提问作者fbalu13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:15