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

音频ended事件触发后无法暂停/播放问题求助

问题描述

首次加载曲目时,暂停按钮功能正常,可暂停音频并切换按钮图标;通过上一曲/下一曲按钮切换歌曲后,按钮仍能正常工作。但当audio.addEventListener('ended', nextTrack);事件触发自动切歌后,暂停按钮仅能切换图标和playing变量状态,无法控制音频的播放/暂停,所有音频的暂停/播放功能彻底失效。

相关代码
let audio = new Audio;
let playing = false;
let playpause = document.getElementById('play-pause');
let root = document.documentElement;
let songname = document.getElementById('name');
let next = document.getElementById('next');
let prev = document.getElementById('previous');

let index = 0;

songlist = [
    {"name":"Love Again"
    ,"artist":"The Kid LAROI",
    "path":"resources/music/love-again.mp3",
    },
    {
    "name":"Always Do",
    "artist":"The Kid LAROI",
    "path":"resources/music/always-do.mp3",
    },
    {
        "name":"Bye Bye",
        "artist":"Juice WRLD",
        "path":"resources/music/bye-bye.mp3",
    },
    {
        "name":"Understand",
        "artist":"BoyWithUke",
        "path":"resources/music/understand.mp3",
    }
]

function progress_animation(){
    var currentTime = audio.currentTime;
    var duration = audio.duration;
    $('#progbar').stop(true, true).animate({ 'width': (currentTime + .25) / duration * 100 + '%' }, 250, 'linear');
    window.requestAnimationFrame(progress_animation);
    
};

function load(index){
    songname.textContent = `${songlist[index].artist} - ${songlist[index].name}`;
    audio.src = songlist[index].path;
    audio.load()
};

audio.addEventListener('ended', nextTrack);

$('#play-pause').click(function (){
    if (!playing) {
        Play()
        playing = true

    } else {
        Pause()
        playing = false
    }
});

function nextTrack(){
    if (index < songlist.length - 1) {
        index++;
    } else {
        index = 0;
    }
    load(index);
};

function prevTrack(){
    if (index > 0) {
        index--;
    } else {
        index = songlist.length - 1;
    }
    load(index);
};

function Play() {
    audio.play();
    playing = true;
    playpause.innerHTML = '<i class="fa-solid fa-pause"></i>';
};

function Pause() {
    audio.pause()
    playing = false;
    playpause.innerHTML = '<i class="fa-solid fa-play"></i>';
};
问题原因与修复方案

核心问题

  1. 状态不同步:音频自然结束时,未更新playing变量状态,导致切歌后playing仍为true,但新加载的音频处于未播放状态,点击按钮时逻辑完全混乱。
  2. 切歌后未自动续播:原逻辑中歌曲结束后应该自动播放下一首,但nextTrack仅加载新音频,未触发播放操作。
  3. 进度动画潜在错误:音频未加载完成时audio.duration为NaN,会导致动画代码报错,影响后续功能。

修复后的代码

let audio = new Audio;
let playing = false;
let playpause = document.getElementById('play-pause');
let root = document.documentElement;
let songname = document.getElementById('name');
let next = document.getElementById('next');
let prev = document.getElementById('previous');

let index = 0;

songlist = [
    {"name":"Love Again"
    ,"artist":"The Kid LAROI",
    "path":"resources/music/love-again.mp3",
    },
    {
    "name":"Always Do",
    "artist":"The Kid LAROI",
    "path":"resources/music/always-do.mp3",
    },
    {
        "name":"Bye Bye",
        "artist":"Juice WRLD",
        "path":"resources/music/bye-bye.mp3",
    },
    {
        "name":"Understand",
        "artist":"BoyWithUke",
        "path":"resources/music/understand.mp3",
    }
]

function progress_animation(){
    var currentTime = audio.currentTime;
    var duration = audio.duration;
    // 避免音频未加载完成时的NaN错误
    if (isNaN(duration)) {
        window.requestAnimationFrame(progress_animation);
        return;
    }
    $('#progbar').stop(true, true).animate({ 'width': (currentTime + .25) / duration * 100 + '%' }, 250, 'linear');
    window.requestAnimationFrame(progress_animation);
    
};

function load(index){
    songname.textContent = `${songlist[index].artist} - ${songlist[index].name}`;
    audio.src = songlist[index].path;
    audio.load();
    // 如果之前处于播放状态,音频加载完成后自动播放
    if (playing) {
        // 监听音频可播放事件,确保加载完成后再播放
        audio.addEventListener('canplay', function playNewTrack() {
            audio.play();
            // 移除一次性监听,避免重复触发
            audio.removeEventListener('canplay', playNewTrack);
        }, { once: true });
    }
};

// 修改ended事件处理,先更新状态再切歌
audio.addEventListener('ended', function() {
    Pause(); // 先同步状态为未播放
    nextTrack();
    // 自动播放下一首
    Play();
});

$('#play-pause').click(function (){
    if (!playing) {
        Play()
    } else {
        Pause()
    }
});

function nextTrack(){
    if (index < songlist.length - 1) {
        index++;
    } else {
        index = 0;
    }
    load(index);
};

function prevTrack(){
    if (index > 0) {
        index--;
    } else {
        index = songlist.length - 1;
    }
    load(index);
};

function Play() {
    // 确保音频加载完成再播放,捕获播放失败错误
    if (audio.src) {
        audio.play().catch(err => console.error('播放失败:', err));
    }
    playing = true;
    playpause.innerHTML = '<i class="fa-solid fa-pause"></i>';
};

function Pause() {
    audio.pause();
    playing = false;
    playpause.innerHTML = '<i class="fa-solid fa-play"></i>';
};

// 初始化加载第一首歌
load(index);

关键修改点

  1. ended事件处理优化:音频结束时先调用Pause()同步状态,再切歌并自动播放下一首,确保状态与音频实际播放情况一致。
  2. load函数增强:添加音频canplay事件监听,确保新音频加载完成后再播放,避免因未加载完成导致的播放失败;同时根据当前playing状态决定是否自动播放。
  3. 进度动画容错:增加isNaN(duration)判断,避免音频未加载时的代码报错。
  4. Play函数容错:添加播放错误捕获,同时判断音频src是否存在,避免无意义的播放调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:54