html5用video标签流式加载的实现


Posted in HTML / CSS onMay 20, 2020

video标签

浏览器的video标签通常是接收一个src属性,然后浏览器就会根据这个src属性来自动加载视频。
这个过程是浏览器来加载video的。

这种方式有什么问题吗?

  • mp4文件不能流式加载
  • webm,flv,hls等格式兼容性问题
  • 播放器ui太丑,一些常用的功能都没有
  • 清晰度切换,等一些操作需要重载视频,比较慢而且还会黑屏
  • 无法对视频加密

请求video流视频

我们可以通过设置responseType为arraybuffer来获取视频流,也可以通过range字段来获取视频流片段。比如

let xhr = new window.XMLHttpRequest();
xhr.responseType = 'arraybuffer'
xhr.open('get', 'http://www.w3school.com.cn/i/movie.mp4')
xhr.responseType = 'arraybuffer';
// xhr.setRequestHeader('Range', `bytes=0-390625`)
xhr.onload = function () {
    if (xhr.status === 200 || xhr.status === 206) {
        console.log(xhr.response)
    }
}
xhr.send();

或者fetch的arrayBuffer方法返回视频流。

fetch(videoUrl).then(function(response) {
       return response.arrayBuffer();
 })

获取到的数据是什么呢?二进制的视频流。
获取这个有什么用呢?

video去播“流”

MediaSource

MediaSource简称mse,是h5的一个api,它允许通过js生成媒体流,让浏览器播放。

使用

我们通过 URL.createObjectURL来创建一个blob格式的视频文件,来给video标签播。
具体用法就是new MediaSource,然后根据这个MediaSource生成blob文件,然后向MediaSource中添加mime和视频流。

<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>

我们的mine是什么呢?
video/webm是视频格式,codecs后面第一段是一些视频编解码的一些重要信息,诸如编码方式、分辨率、帧率、码率以及对解码器解码能力的要求。
第二段是关于音频部分的信息。

html5用video标签流式加载的实现
 

生成这样的一个video标签。我们现在绕过了浏览器直接去请求src这一步,ajax请求视频流,然后我们可以对视频流进行处理,直接操作视频流实现我们需要的各种功能。
但是对于mp4格式,是不支持流式加载的,所以只能通过我们自己操作流来实现流式播放。

播放器

公司同事研发了一款开源播放器,https://github.com/bytedance/xgplayer ,西瓜视频好几千万dau的产品实测。

播放器原理

它是利用了流式处理视频源,不仅仅是简单的请求流然后交给video标签播放,它是请求视频流然后用js解码然后进行一些需要的操作,交给video播放。

为什么要用js解码呢?

公司大部分视频是mp4,怎么让mp4支持流播放呢?我们把mp4的流拿过来,js解析出它的视频信息,然后js转换成支持视频流的fmp4格式的文件。
它的优势是

  1. 解决了chrome不支持hls格式的问题(还有各种不支持格式的问题),因为我们是直接操作二进制视频数据,所以不存在video标签不支持的情况。
  2. 解决了切换清晰度重新刷新视频的问题
  3. 对于mp4文件快进操作进行最小化的请求加载,让它支持流式加载。
  4. 支持直播和弹幕

我们直接操作的视频流,所以在对视频进行清晰度切换,或者快进的时候,我们后计算当前时间的流,然后用js加载视频的新的流,从而进行最快的加载和响应。

到此这篇关于html5用video标签流式加载的实现的文章就介绍到这了,更多相关html5用video标签流式加载内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

HTML / CSS 相关文章推荐
在css3中background-clip属性与background-origin属性的用法介绍
Nov 13 HTML / CSS
CSS3径向渐变之大鱼吃小鱼之孤单的大鱼
Apr 26 HTML / CSS
HTML5+CSS3 诱人的实例:3D立方体旋转动画实例
Dec 30 HTML / CSS
HTML5引入的新数组TypedArray介绍
Dec 24 HTML / CSS
HTML5实现一个能够移动的小坦克示例代码
Sep 02 HTML / CSS
Canvas绘制浮动球效果的示例
Dec 29 HTML / CSS
canvas环形倒计时组件的示例代码
Jun 14 HTML / CSS
html5手机端页面可以向右滑动导致样式受影响的问题
Jun 20 HTML / CSS
3种方式实现瀑布流布局小结
Sep 05 HTML / CSS
原生canvas制作画图小工具的踩坑和爬坑
Jun 09 HTML / CSS
HTML5单选框、复选框、下拉菜单、文本域的实现代码
Dec 01 HTML / CSS
CSS实现背景图片全屏铺满自适应的3种方式
Jul 07 HTML / CSS
video.js支持m3u8格式直播的实现示例
May 20 #HTML / CSS
video实现有声音自动播放的实现方法
May 20 #HTML / CSS
基于html5 canvas做批改作业的小插件
May 20 #HTML / CSS
video下autoplay属性无效的解决方法(添加muted属性)
May 19 #HTML / CSS
html2canvas生成的图片偏移不完整的解决方法
May 19 #HTML / CSS
html5简介及新增功能介绍
May 18 #HTML / CSS
Html5让容器充满屏幕高度或自适应剩余高度的布局实现
May 14 #HTML / CSS
You might like
PHP启动windows应用程序、执行bat批处理、执行cmd命令的方法(exec、system函数详解)
2014/10/20 PHP
WordPress中给媒体文件添加分类和标签的PHP功能实现
2015/12/31 PHP
PHP入门教程之会话控制技巧(cookie与session)
2016/09/11 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
宝塔面板在NGINX环境中TP5.1如何运行?
2021/03/09 PHP
Mootools 1.2教程 排序类和方法简介
2009/09/15 Javascript
JQuery Easyui Tree的oncheck事件实现代码
2010/05/28 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
2011/04/02 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
解决jQuery动态获取手机屏幕高和宽的问题
2014/05/07 Javascript
轻松使用jQuery双向select控件Bootstrap Dual Listbox
2015/12/13 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
Nodejs进阶之服务端字符编解码和乱码处理
2017/09/04 NodeJs
Vue.js实现的表格增加删除demo示例
2018/05/22 Javascript
微信小程序JS加载esmap地图的实例详解
2019/09/04 Javascript
vue-i18n实现中英文切换的方法
2020/07/06 Javascript
python基于phantomjs实现导入图片
2016/05/13 Python
用python制作游戏外挂
2018/01/04 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
详解python的argpare和click模块小结
2019/03/31 Python
Python 闭包,函数分隔作用域,nonlocal声明非局部变量操作示例
2019/10/14 Python
Flask 上传自定义头像的实例详解
2020/01/09 Python
如何给Python代码进行加密
2020/01/10 Python
Python3之乱码\xe6\x97\xa0\xe6\xb3\x95处理方式
2020/05/11 Python
Python可以用来做什么
2020/11/23 Python
css3实现平移效果(transfrom:translate)的示例
2020/11/13 HTML / CSS
HTML5网页音乐播放器的示例代码
2017/11/09 HTML / CSS
美国豪华的多品牌精品店:The Webster
2019/07/31 全球购物
RIP版本1跟版本2的区别
2013/12/30 面试题
中学生励志演讲稿
2014/04/26 职场文书
社团活动总结格式
2014/08/29 职场文书
领导班子群众路线与四风问题对照检查材料思想汇报
2014/10/11 职场文书
中学综治宣传月活动总结
2015/05/07 职场文书
2019让人心动的商业计划书
2019/06/27 职场文书
Python 装饰器(decorator)常用的创建方式及解析
2022/04/24 Python
Windows server 2012 R2 安装IIS服务器
2022/04/29 Servers