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

使用HTML5 <audio>标签时音频无法停止播放的问题求助

音频播放后无法自动停止的修复方案

问题根源

你代码里的停止逻辑依赖audio.duration计算超时,但如果音频的元数据还没加载完成,audio.duration会返回NaN,导致停止用的setTimeout被设置成无效值,根本不会触发停止操作。另外只靠超时停止不够可靠,得结合音频自身的ended事件来双重保障。

修复步骤

  • 监听音频的loadedmetadata事件,确保拿到有效时长后再设置停止定时器
  • 新增ended事件监听,音频自然结束时自动重置并暂停
  • 给audio.duration加有效性判断,避免NaN导致的逻辑失效
  • 补上原代码中缺失的timer DOM元素,避免倒计时报错

修复后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Do You Remember?</title>
</head>
<body>
    <!-- 补上原代码缺失的定时器显示元素 -->
    <div id="timer"></div>

    <audio id="delayedAudio" preload="auto">
        <source src="audio/eerie.mp3" type="audio/mpeg">
    </audio>

    <script>
        const audio = document.getElementById('delayedAudio');
        audio.loop = false;
        let started = false;
        let stopTimeout = null;

        // 监听音频自然结束事件,自动停止并重置
        audio.addEventListener('ended', () => {
            audio.pause();
            audio.currentTime = 0;
            if (stopTimeout) {
                clearTimeout(stopTimeout);
                stopTimeout = null;
            }
        });

        function allowAudioPlayback() {
            if (started) return;
            started = true;

            setTimeout(() => {
                audio.currentTime = 0;
                audio.play().then(() => {
                    // 封装停止定时器设置逻辑
                    const setupStopTimer = () => {
                        if (!isNaN(audio.duration)) {
                            stopTimeout = setTimeout(() => {
                                audio.pause();
                                audio.currentTime = 0;
                            }, audio.duration * 1000 + 500);
                        } else {
                            // 未拿到时长则延迟重试
                            setTimeout(setupStopTimer, 100);
                        }
                    };

                    // 检查音频是否已加载元数据
                    if (audio.readyState >= 2) { // HAVE_METADATA状态
                        setupStopTimer();
                    } else {
                        audio.addEventListener('loadedmetadata', setupStopTimer, { once: true });
                    }
                }).catch(err => {
                    console.log('Autoplay blocked:', err);
                });
            }, 60000);
        }

        window.addEventListener('click', allowAudioPlayback, { once: true });
        window.addEventListener('keydown', allowAudioPlayback, { once: true });

        // 倒计时逻辑
        let timeLeft = 60;
        const timer = document.getElementById("timer");
        const countdown = setInterval(() => {
            if (timeLeft > 0) {
                timer.textContent = `Time left: ${timeLeft--}s`;
            } else {
                timer.textContent = "???";
                clearInterval(countdown);
            }
        }, 1000);
    </script>
</body>
</html>

额外说明

  • 新增stopTimeout变量存储定时器ID,避免音频自然结束后冗余定时器仍触发
  • 用audio.readyState判断元数据加载状态,比单纯等待事件更严谨

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:33:17