HTML Audio播放器10秒前后跳转功能在Chrome/Opera失效求助
HTML Audio播放器10秒跳转功能在Chrome/Opera中异常重置问题修复
问题描述
为HTML Audio播放器实现了类似YouTube的10秒前后跳转功能,该功能在Firefox、Safari等浏览器中运行正常(点击前进跳10秒,点击后退倒回10秒),但在Chrome和Opera浏览器中,无论点击前进还是后退按钮,播放时间都会重置为0:00。希望在不改动现有核心逻辑的前提下修复该问题。
现有代码
HTML代码
<div class="audioVersionPost"> <audio id="audioPlayer" autoplay preload="metadata"> <source id="audioSource" type="audio/mpeg"> </audio> <button id="playPauseBtn"> <span id="playSpanIcon" class="material-symbols-rounded playerSymbols">play_circle</span> <span id="pauseSpanIcon" class="material-symbols-rounded playerSymbols">pause_circle</span> <span id="playText">Playing</span> <span id="pauseText">Paused</span> </button> <button id="replayBtn"> <span class="material-symbols-rounded playerSymbols">replay</span> <span>Replay</span> </button> <button id="skipBackwardBtn"> <span class="material-symbols-rounded playerSymbols">replay_10</span> </button> <button id="skipForwardBtn"> <span class="material-symbols-rounded playerSymbols">forward_10</span> </button> <span id="currentTime">0:00</span> <input type="range" id="seekSlider" min="0" max="100" value="0" disabled> <span id="totalTime">0:00</span> <select id="speedSelect"> <option value="0.5">0.5x</option> <option value="1" selected>1x</option> <option value="1.5">1.5x</option> <option value="2">2x</option> </select> </div>
JavaScript代码
const audioPlayer = document.getElementById('audioPlayer'); const playPauseBtn = document.getElementById('playPauseBtn'); const skipBackwardBtn = document.getElementById('skipBackwardBtn'); const skipForwardBtn = document.getElementById('skipForwardBtn'); const speedSelect = document.getElementById('speedSelect'); const currentTime = document.getElementById('currentTime'); const totalTime = document.getElementById('totalTime'); const seekSlider = document.getElementById('seekSlider'); // Play/pause button functionality playPauseBtn.addEventListener('click', function() { if (audioPlayer.paused) { audioPlayer.play(); } else { audioPlayer.pause(); } }); // Skip backward button functionality skipBackwardBtn.addEventListener('click', function() { audioPlayer.currentTime -= 10; }); // Skip forward button functionality skipForwardBtn.addEventListener('click', function() { audioPlayer.currentTime += 10; }); // Speed control functionality speedSelect.addEventListener('change', function() { audioPlayer.playbackRate = parseFloat(speedSelect.value); }); // Update current time and total time audioPlayer.addEventListener('timeupdate', function() { currentTime.textContent = formatTime(audioPlayer.currentTime); totalTime.textContent = formatTime(audioPlayer.duration); const value = (audioPlayer.currentTime / audioPlayer.duration) * 100; seekSlider.value = value; seekSlider.style.background = `linear-gradient(to right, #3557FF ${value}%, #EDF0FF ${value}%)`; }); // Format time function function formatTime(seconds) { const minutes = Math.floor(seconds / 60); const remainingSeconds = Math.floor(seconds % 60); const formattedMinutes = minutes === 0 ? '0' : minutes.toString(); const formattedSeconds = remainingSeconds < 10 ? '0' + remainingSeconds : remainingSeconds.toString(); return `${formattedMinutes}:${formattedSeconds}`; } // Seek functionality seekSlider.addEventListener('input', function() { const value = (seekSlider.value / 100) * audioPlayer.duration; audioPlayer.currentTime = value; seekSlider.style.background = `linear-gradient(to right, #3557FF ${seekSlider.value}%, #EDF0FF ${seekSlider.value}%)`; }); document.getElementById("playPauseBtn").addEventListener("click", function() { var playIcon = document.getElementById("playSpanIcon"); var pauseIcon = document.getElementById("pauseSpanIcon"); var playText = document.getElementById("pauseText"); var pauseText = document.getElementById("playText"); if (playIcon.style.display === "none") { playIcon.style.display = "block"; pauseIcon.style.display = "none"; playText.style.display = "block"; pauseText.style.display = "none"; } else { playIcon.style.display = "none"; pauseIcon.style.display = "block"; playText.style.display = "none"; pauseText.style.display = "block"; } }); const replayBtn = document.getElementById('replayBtn'); audioPlayer.addEventListener('ended', function() { // Show replay button and hide play/pause button replayBtn.style.display = 'flex'; playPauseBtn.style.display = 'none'; }); replayBtn.addEventListener('click', function() { // Reset audio playback audioPlayer.currentTime = 0; audioPlayer.play(); // Toggle display of play/pause buttons playPauseBtn.style.display = 'block'; replayBtn.style.display = 'none'; });
修复方案
核心修复:给跳转逻辑添加时间校验
Chrome和Opera对未加载完成元数据的音频currentTime处理更严格,直接加减会因duration为NaN导致计算异常,触发时间重置。只需修改两个跳转按钮的事件处理代码:
// Skip backward button functionality skipBackwardBtn.addEventListener('click', function() { // 确保音频元数据已加载,且计算后时间不小于0 if (audioPlayer.duration) { audioPlayer.currentTime = Math.max(0, audioPlayer.currentTime - 10); } }); // Skip forward button functionality skipForwardBtn.addEventListener('click', function() { // 确保音频元数据已加载,且计算后时间不超过总时长 if (audioPlayer.duration) { audioPlayer.currentTime = Math.min(audioPlayer.duration, audioPlayer.currentTime + 10); } });
可选增强:等待元数据加载后启用按钮
为了进一步提升稳定性,可以给音频添加loadedmetadata事件,确保元数据加载完成后再启用跳转按钮:
- 在JavaScript末尾添加:
// 音频元数据加载完成后启用跳转按钮 audioPlayer.addEventListener('loadedmetadata', function() { skipBackwardBtn.disabled = false; skipForwardBtn.disabled = false; });
- 在HTML中给跳转按钮添加默认禁用属性:
<button id="skipBackwardBtn" disabled> <span class="material-symbols-rounded playerSymbols">replay_10</span> </button> <button id="skipForwardBtn" disabled> <span class="material-symbols-rounded playerSymbols">forward_10</span> </button>
修复原理
- 校验
audioPlayer.duration是否存在,避免在元数据未加载时执行无效的时间计算 - 使用
Math.max和Math.min约束时间范围,确保currentTime始终在0到duration之间,符合浏览器的时间规范
内容的提问来源于stack exchange,提问作者Oliver Gray Silva
相关产品推荐
相关产品推荐

