mediaDevices-new MediaSource() 流媒体处理

new MediaSource()


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <video controls></video>
    <script>
      var video = document.querySelector('video');

      var assetURL = 'frag_bunny.mp4';
      // Need to be specific for Blink regarding codecs
      // ./mp4info frag_bunny.mp4 | grep Codec
      var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
      
      if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
        var mediaSource = new MediaSource;
        //console.log(mediaSource.readyState); // closed
        video.src = URL.createObjectURL(mediaSource);
        mediaSource.addEventListener('sourceopen', sourceOpen);
      } else {
        console.error('Unsupported MIME type or codec: ', mimeCodec);
      }

      function sourceOpen (_) {
        //console.log(this.readyState); // open
        var mediaSource = this;
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
          sourceBuffer.addEventListener('updateend', function (_) {
            mediaSource.endOfStream();
            video.play();
            //console.log(mediaSource.readyState); // ended
          });
          sourceBuffer.appendBuffer(buf);
        });
      };

      function fetchAB (url, cb) {
        console.log(url);
        var xhr = new XMLHttpRequest;
        xhr.open('get', url);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function () {
          cb(xhr.response);
        };
        xhr.send();
      };
    </script>
  </body>
</html>

来自:https://developer.mozilla.org/zh-CN/docs/Web/API/MediaSource
参考:https://www.jianshu.com/p/1bfe4470349b

  var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

参照表:https://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support

方法

从父接口EventTarget上继承而来。

MediaSource.addSourceBuffer()
创建一个带有给定MIME类型的新的 SourceBuffer 并添加到 MediaSource 的 SourceBuffers 列表。
MediaSource.removeSourceBuffer() (en-US)
删除指定的SourceBuffer 从这个MediaSource对象中的 SourceBuffers列表。
MediaSource.endOfStream()

属性

MediaSource.sourceBuffers (en-US) 只读
返回一个SourceBufferList (en-US) 对象,包含了这个MediaSource的SourceBuffer的对象列表。
MediaSource.activeSourceBuffers (en-US) 只读

返回一个 SourceBufferList (en-US) 对象,包含了这个MediaSource.sourceBuffers (en-US)中的SourceBuffer 子集的对象—即提供当前被选中的视频轨 (video track),启用的音频轨 (audio tracks) 以及显示/隐藏的字幕轨 (text tracks) 的对象列表。

MediaSource.readyState 只读
返回一个包含当前MediaSource状态的集合,即使它当前没有附着到一个media元素(closed),或者已附着并准备接收SourceBuffer 对象 (open),亦或者已附着但这个流已被MediaSource.endOfStream()关闭(ended.)
MediaSource.duration
获取和设置当前正在推流媒体的持续时间。

流媒体处理

<div class="a">
        <video id="video" controls preload="auto"></video>
    </div>
    <script>
        $(function() {
            var video = document.querySelector('#video');
            var mediaSource = new MediaSource();
            video.src = URL.createObjectURL(mediaSource);
            mediaSource.addEventListener('sourceopen', sourceOpen);

            function sourceOpen(e) {
                URL.revokeObjectURL(video.src);
                // 设置 媒体的编码类型
                var mime = 'video/webm; codecs="vorbis,vp8"';
                var mediaSource = e.target;
                var sourceBuffer = mediaSource.addSourceBuffer(mime);
                var videoUrl = 'http://localhost:9090/examples/mp4/video.webm';
                fetch(videoUrl).then(function(response) {
                        console.log(response)
                        return response.arrayBuffer();
                    })
                    .then(function(arrayBuffer) {
                        sourceBuffer.addEventListener('updateend', function(e) {
                            if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
                                mediaSource.endOfStream();
                                // 在数据请求完成后,我们需要调用 endOfStream()。它会改变 MediaSource.readyState 为 ended 并且触发 sourceended 事件。
                                video.play().then(function() {}).catch(function(err) {
                                    console.log(err)
                                });
                            }
                        });
                        sourceBuffer.appendBuffer(arrayBuffer);
                    });
            }
        })
</script>

参考:https://www.cnblogs.com/dh-dh/p/9254172.html

**视频分段加密: https://blog.csdn.net/camike/article/details/82797768

参考:https://blog.csdn.net/panqisheng/article/details/51470624

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)
        })
      }
    },

node后台

router.get('/GetStream', function(req, res, next) {
  let filePath = 'public/videos/frag_bunny.mp4'
  res.set('Content-Type', 'application/octet-stream');
  fs.createReadStream(filePath).pipe(res)
})

前端代码

export default {
    data() {
        return {
            mediaSource: null,
            sourceBuffer: null,
            mimeType: 'video/mp4;codecs="avc1.42E01E,mp4a.40.2"'
        }
    },
    mounted() {
        // MediaSource.isTypeSupported('video/webm;codecs="vorbis,vp8"');//是否支持webm 
        // MediaSource.isTypeSupported('video/mp4;codecs="avc1.42E01E,mp4a.40.2"')//是否支持MP4 
        // MediaSource.isTypeSupported('video/mp2t;codes="avc1.42E01E,mp4a.40.2"')//是否支持ts
        // 首先判断一下对视频格式的支持度,MediaSource提供了isTypeSupported方法
        if ('MediaSource' in window && MediaSource.isTypeSupported(this.mimeType)) {
            this.createMediaSource()
        } else {
            this.$message({message: '您的浏览器不支持MediaSource', type: 'warning'})
        }
    },
    methods: {
        createMediaSource() {
	        // 创建MediaSource对象,并使用URL.createObjectURL来创建指向MediaSource对象的URL供video播放
            this.mediaSource = new MediaSource()
            this.$refs.h5video.src = window.URL.createObjectURL(this.mediaSource)
            // 监听sourceopen
            this.mediaSource.addEventListener('sourceopen', this.onSourceOpen)
        },
        onSourceOpen() {
            let self = this
            // 创建一个新的 SourceBuffer 对象,然后会将它追加到 MediaSource 的 SourceBuffers 列表中。
            this.sourceBuffer = this.mediaSource.addSourceBuffer(this.mimeType)
            // 监听buffer更新结束事件
            this.sourceBuffer.addEventListener('updateend', () => {
	            // 停止stream
                self.mediaSource.endOfStream()
                // 开始播放
                self.$refs.h5video.play()
            })
            this.requestBuffer()
        },
        requestBuffer() {
            let self = this
            // 请求接口去拉流
            this.$http.get('GetStream', null, {responseType: 'arraybuffer'}).then(resp => {
	            // 拉到的流塞进sourceBuffer里。
                self.sourceBuffer.appendBuffer(resp)
            })
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web修理工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值