MediaElementJS切换流媒体后pause事件触发导致isPlaying状态异常求助
问题:MediaElementJS v7切换音频流时isPlaying被错误置为false
使用MediaElementJS v7实现网络电台切换功能时,点击切换新流后,新流可正常播放,但旧流的pause事件会在新流的play事件之后触发,导致全局变量isPlaying被错误设置为false。
原实现代码
$(document).on('click', '.header a[rel=open_player]', function() { var bottom_player = $(document).find('.bottom-player'); var webradio_id = $(this).attr('data-id'); isPlaying = true; var currentStream; $.post('/ajax/webradio/'+ webradio_id, function(data) { bottom_player.html(data); var player = bottom_player.find('audio'); player.mediaelementplayer({ audioWidth: '100%', pluginPath: '/assets/public/js/mediaelement/', alwaysShowControls: true, features: ['playpause','volume'], audioVolume: 'horizontal', isVideo: false, forceLive: true, success: function (mediaElement, domObject) { mediaElement.play(); currentStream = mediaElement.getSrc(); mediaElement.addEventListener('play', function () { console.log('['+Date.now() + '] Media play: getSrc='+ mediaElement.getSrc()+' / currentStream='+currentStream); document.title = '▶ ' + origTitle; isPlaying = true; }, false); mediaElement.addEventListener('pause', function () { if(currentStream == mediaElement.getSrc()) { console.log('['+Date.now() + '] Media pause: getSrc='+ mediaElement.getSrc() + ' / currentStream='+currentStream); document.title = origTitle; isPlaying = false; } }, false); }, }); }); });
控制台日志示例
[1695287178446] Media play: getSrc=https://example.com/stream-wr03.aac?i=94884 / currentStream=https://example.com/stream-wr03.aac?i=94884 [1695287178449] Media pause: getSrc=https://example.com/stream-01.aac?i=30130 / currentStream=https://example.com/stream-01.aac?i=30130 [1695287190405] Media play: getSrc=https://example.com/stream-wr01.aac?i=24717 / currentStream=https://example.com/stream-wr01.aac?i=24717 [1695287190409] Media pause: getSrc=https://example.com/stream-wr03.aac?i=94884 / currentStream=https://example.com/stream-wr03.aac?i=94884
解决方案
核心问题是旧的MediaElement实例未被销毁,其事件监听仍在触发。以下是两种可行的修复方案:
方案1:全局跟踪活跃实例并清理旧实例
每次切换流时,先销毁之前的播放器实例,避免旧事件继续触发;通过全局变量跟踪当前活跃实例,确保pause事件只处理当前正在播放的流。
// 全局变量跟踪当前活跃的播放器实例 let activeMediaElement = null; $(document).on('click', '.header a[rel=open_player]', function() { var bottom_player = $(document).find('.bottom-player'); var webradio_id = $(this).attr('data-id'); // 清理旧实例:暂停播放、移除事件监听、销毁实例 if (activeMediaElement) { activeMediaElement.pause(); activeMediaElement.remove(); activeMediaElement = null; } isPlaying = true; $.post('/ajax/webradio/'+ webradio_id, function(data) { bottom_player.html(data); var player = bottom_player.find('audio'); player.mediaelementplayer({ audioWidth: '100%', pluginPath: '/assets/public/js/mediaelement/', alwaysShowControls: true, features: ['playpause','volume'], audioVolume: 'horizontal', isVideo: false, forceLive: true, success: function (mediaElement, domObject) { activeMediaElement = mediaElement; mediaElement.play(); const currentStream = mediaElement.getSrc(); mediaElement.addEventListener('play', function () { console.log('['+Date.now() + '] Media play: getSrc='+ mediaElement.getSrc()+' / currentStream='+currentStream); document.title = '▶ ' + origTitle; isPlaying = true; }, false); mediaElement.addEventListener('pause', function () { // 仅当当前实例是活跃实例时,才更新状态 if (mediaElement === activeMediaElement) { console.log('['+Date.now() + '] Media pause: getSrc='+ mediaElement.getSrc() + ' / currentStream='+currentStream); document.title = origTitle; isPlaying = false; } }, false); }, }); }); });
方案2:块级作用域变量+实例标记
如果不想使用全局变量,可通过块级作用域变量结合元素dataset标记当前流,确保事件判断的准确性:
$(document).on('click', '.header a[rel=open_player]', function() { var bottom_player = $(document).find('.bottom-player'); var webradio_id = $(this).attr('data-id'); // 销毁旧实例 const oldPlayer = bottom_player.find('audio').data('mediaelementplayer'); if (oldPlayer) { oldPlayer.remove(); } isPlaying = true; $.post('/ajax/webradio/'+ webradio_id, function(data) { bottom_player.html(data); var player = bottom_player.find('audio'); player.mediaelementplayer({ audioWidth: '100%', pluginPath: '/assets/public/js/mediaelement/', alwaysShowControls: true, features: ['playpause','volume'], audioVolume: 'horizontal', isVideo: false, forceLive: true, success: function (mediaElement, domObject) { mediaElement.play(); const currentStream = mediaElement.getSrc(); // 给当前实例标记流地址 mediaElement.dataset.streamSrc = currentStream; mediaElement.addEventListener('play', function () { console.log('['+Date.now() + '] Media play: getSrc='+ mediaElement.getSrc()+' / currentStream='+currentStream); document.title = '▶ ' + origTitle; isPlaying = true; }, false); mediaElement.addEventListener('pause', function () { // 判断暂停的流是否为当前跟踪的流 if (mediaElement.dataset.streamSrc === currentStream) { console.log('['+Date.now() + '] Media pause: getSrc='+ mediaElement.getSrc() + ' / currentStream='+currentStream); document.title = origTitle; isPlaying = false; } }, false); }, }); }); });
内容的提问来源于stack exchange,提问作者Guillaume
相关产品推荐
相关产品推荐

