vue使用mediaSource拿到视频流,并且播放

新手上路,请多包涵

视频文件使用的是MDN的例子的视频,所以不会存在ffmep4问题
后端通过node createReadStream读取视频文件流,通过pipe输出响应。
前端vue框架,主要参考了[MDN的例子],(https://developer.mozilla.org...
拿到后端返回之后转为arraybuffer类型

getvideosource () {
      let cid = this.$route.query.chapterId
      let path = 'http://localhost:3000/api/chapter/learning/video'
      let mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
      // let video = this.$refs.v1
      let video = document.getElementById('v1')
      let mediaSource
      let that = this
      if('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
        console.log('MediaSource')
        mediaSource = new MediaSource()
        video.src = URL.createObjectURL(mediaSource)
        mediaSource.addEventListener('sourceopen',sourceOpen.bind(this))
      } else{
        console.error('Unsupported MIME type or codec:',mimeCodec)   
      }
      function sourceOpen () {
        console.log('has opened')
        URL.revokeObjectURL(video.src)
        let sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
        fetchAB(path,sourceBuffer)
      }
      function fetchAB (url,sourceBuffer) {
        axios.get(url).then((result)=>{
          console.log(Object.prototype.toString.call(result.data));
          // console.log(result.data);
          // let data = new Blob([result.data],{type: 'application/octet-stream'})
          // console.log(Object.prototype.toString.call(data));
          // console.log(data);
          // var reader = new FileReader();
          // reader.onload = function() {
          //   console.log(this.result);
          // }
          // reader.readAsArrayBuffer(blob);
          function toArrayBuffer(buf) {
            var ab = new ArrayBuffer(buf.length);
            var view = new Uint8Array(ab);
            for (var i = 0; i < buf.length; ++i) {
                view[i] = buf[i];
            }
            return ab;
          }
          let r = toArrayBuffer(result.data)
          console.log(Object.prototype.toString.call(r))
          sourceBuffer.addEventListener('updateend', function () {
            console.log(mediaSource.readyState);
            console.log(sourceBuffer)
            console.log(mediaSource);
            mediaSource.endOfStream()
          })
          sourceBuffer.appendBuffer(r)
        })
      }
    },

以上是全部的代码。
这个函数在mounted内调用
浏览器运行会在mediaSource.endOfStream()处报错

Failed to execute 'endOfStream' on 'MediaSource': The MediaSource's readyState is not 'open'.
有大佬知道这是怎么回事吗???

阅读 14.5k
2 个回答
新手上路,请多包涵

mediaSource.endOfStream()需要在sourceBuffer.appendBuffer(r)之后,你结束了流,就不能添加sourceBuffer了

咨询你个 问题 我是 音频流 视频流 我单独
mediaSource.addSourceBuffer(video/mp4; codecs="${a_codecs}")
mediaSource.addSourceBuffer(audio/mp4; codecs="${a_codecs}")
单独可以放 怎么合并到一起呀

加个 判断

fetch(url).then(r=>r.arrayBuffer()).then(r=>{
          this.data.track.audio.appendBuffer(new Uint8Array(r));
          var that = this
          that.data.track.audio.onupdateend = function(){
            console.log( 'track.audio initialization')
            if (!that.data.track.audio.updating && that.data.mediaSource.readyState === 'open') {
              console.log( 'track.audio endOfStream' )
              that.data.mediaSource.endOfStream();
              // that.data.mediaSource.duration = 0;
              // video.play()
            }
          }
          this.audio(1)
        })

appendBuffer 在前 然后 onupdateend 里面处理 endOfStream

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题