MediaSource实时播放mp3流的问题?

websocket 后台返回MP3音频流,前端实时播放
使用MediaSource API 偶尔在appendBuffer会报错
大佬怎么解啊,这个问题折磨得我头发快掉光了

<audio id="audios"></audio>

const audioPlay = document.getElementById('audios')
const mediaSource = new MediaSource();
let sourceBuffer;
audioPlay.src = window.URL.createObjectURL(mediaSource)
createWebSocket(wsUrl);
mediaSource.addEventListener('sourceopen', () => {
    // 给 sourceBuffer 赋值
    sourceBuffer = mediaSource.addSourceBuffer('audio/mpeg');
    
    
 });

var queue = [];
var WS_OnMessage=function(e){
    var data=e.data;
        if(data instanceof ArrayBuffer) {
            if (!sourceBuffer.updating) {
                sourceBuffer.appendBuffer(data);
            } else {
                queue.push(data);
            }
            sourceBuffer.addEventListener('updateend', function (_) {
                if (queue.length > 0) {
                    sourceBuffer.appendBuffer(queue.shift());
                }
                if (queue.length === 0 && mediaSource.readyState === 'open') {
                    mediaSource.endOfStream();
                }
                audioPlay.play();
            });
        }
    
};

阅读 3.7k
2 个回答
const audioPlay = document.getElementById('audios');
const mediaSource = new MediaSource();
let sourceBuffer;
audioPlay.src = window.URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', () => {
    sourceBuffer = mediaSource.addSourceBuffer('audio/mpeg');
    sourceBuffer.addEventListener('updateend', function (_) {
        if (mediaSource.readyState === 'open') {
            mediaSource.endOfStream();
        }
        audioPlay.play();
    });
});

var WS_OnMessage = function(e) {
    var data = e.data;
    if (data instanceof ArrayBuffer) {
        if (!sourceBuffer.updating) {
            sourceBuffer.appendBuffer(data);
        }
    }
};

我也遇到了这个问题,还有就是播放的时候完全没有声音

 playSingleAudio(index) {
      if (this.audioFiles.length) {
        const video = this.$refs.audioEl
        const mineCodes = 'audio/mpeg'
        if (window.MediaSource && MediaSource.isTypeSupported(mineCodes)) {
          const sourceOpen = (e) => {
            // URL.revokeObjectURL 主动释放引用
            URL.revokeObjectURL(video.src)
            const mediaSource = e.target
            // addSourceBuffer根据传入的mineCodes,创建一个新的 SourceBuffer 并添加到 MediaSource 的 SourceBuffers 列表
            const sourceBuffer = mediaSource.addSourceBuffer(mineCodes)
            // 将媒体数据添加到sourceBuffer中
            // while (this.audioFiles.length !== 0) {
            const blob = this.audioFiles.shift()
            this.blobToArrayBuffer(blob).then(arrayBuffer => {
              console.log('buffer: ', arrayBuffer)
              console.log('arrayBuffer: ', arrayBuffer)
              console.log('sourceBuffer: ', sourceBuffer)
              console.log('mediaSource: ', mediaSource)
              sourceBuffer.appendBuffer(arrayBuffer)
            })
            // }

            sourceBuffer.addEventListener('updateend', function(e) {
              console.log('e:1 ', e)
              if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
                // 数据添加完毕后,调用endOfStream结束当前流
                mediaSource.endOfStream()
              }
              video.play()
            })
          }
          // 检测当前环境是否支持 MediaSource API以及是否支持此mineCodes
          var mediaSource = new MediaSource()
          // 使用 mediaSource对象创建blob url,并赋给video.src
          video.src = URL.createObjectURL(mediaSource)
          console.log(' video.src: ', mediaSource, video.src)
          mediaSource.addEventListener('sourceopen', sourceOpen)
        } else {
          console.log('The Media Source Extensions API is not supported.')
        }
        video.addEventListener('canplay', function() { video.play() })
        // const list = _.cloneDeep(this.audioFiles)
        // const singleAudioFiles = this.audioFiles.shift()
        // console.log('this.audioFiles: ', this.audioFiles)
        // console.log('singleAudioFiles: ', singleAudioFiles)
        // // 连接多个base64数据播放
        // this.getBase64([singleAudioFiles]).then((base64) => {
        //   console.log('base64', base64)
        //   this.playAudioEl(index, base64, true)
        // })
      } else {
        this.resetPlayAudioIcon(index)
      }
    },
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题