使用HTML5 <audio>标签时音频无法停止播放的问题求助
音频播放后无法自动停止的修复方案
问题根源
你代码里的停止逻辑依赖audio.duration计算超时,但如果音频的元数据还没加载完成,audio.duration会返回NaN,导致停止用的setTimeout被设置成无效值,根本不会触发停止操作。另外只靠超时停止不够可靠,得结合音频自身的ended事件来双重保障。
修复步骤
- 监听音频的
loadedmetadata事件,确保拿到有效时长后再设置停止定时器 - 新增
ended事件监听,音频自然结束时自动重置并暂停 - 给
audio.duration加有效性判断,避免NaN导致的逻辑失效 - 补上原代码中缺失的
timerDOM元素,避免倒计时报错
修复后的完整代码
<!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
相关产品推荐
相关产品推荐

