前言

毫无疑问,当初是短视频、直播的时代。视频内容逐步代替图文模式成为网友们获取陈腐事物以及展示自我的一大媒介。随着5G的到来,2020年属于直播短视频爆发式增长的一年,电商平台也都涌入直播营销的大风口,成为了各自平台引流转化的要害。不论是用户还是开发者,咱们处于这个风口中。本文将带你摸索浏览器视频播放的神秘。

视频的形成

一个残缺可播放的视频文件是由视频和音频两局部形成。视频和音频又有各自的封装格局(容器)和编码格局。

编码格局

常见的视频编码格局有:MPEG4、H.264、H.265等。
常见的音频编码格局有:MP3、AAC、WAV等。

封装格局

常见的视频封装格局有:MP4、FLV、mov、AVI、RMVB等。

先了解几个名词

就是影像动画中的最小单位的影像画面。一帧就是一张静止的图像。视频中的动画就是由多幅间断的帧画面形成。

帧率

帧率是以帧为单位的图像在显示器上呈现的频率,也叫帧速率,单位:赫兹(Hz)。简略了解为每秒播放图片的数量。

码率

码率是比特率的俗称,是指每秒传送的比特数。

FFmpeg

FFmpeg是能够用来记录、转换数字视频和音频的一套计算机程序。FFmpeg是在linux下开发,所以天生跨平台。它对音视频编码格局的反对比拟全面,能对视频的各个组成部分进行编码。

H264

通常被称之为H.264/AVC;是由国内标准化阻止和国际电信联盟独特提出的继MPEG4之后的新一代数字视频压缩格局。采纳H.264压缩后的数据具备低码率、高质量图像、容错能力强、网络适应性强等长处。

MP4

MP4是一中规范的数字多媒体容器格局;用于音频、视频的压缩编码,也能够存储字幕和静止图像,同时能以流的形式进行网络传输。

fMP4(Fragmented MP4)

fMP4是基于MPEG-4 Part 12的流媒体格式,与MP4很类似。简略来说fMP4区别与MP4最大的区别就是它能很好地适应流式播放。

浏览器播放视频

video标签播放

在浏览器播放视频,能够应用HTML5原生的video标签。但其播放的格局应用肯定限度的,目前video只反对三种格局WebM、Ogg、MP4。

  • WebM:WebM 文件应用 VP8 视频编解码器和 Vorbis 音频编解码器
  • Ogg :Ogg 文件应用 Theora 视频编解码器和 Vorbis音频编解码器
  • MP4:MPEG 4文件应用 H264 视频编解码器和AAC音频编解码器

下面三种能够间接应用video播放:

<video id="video-box" src="//cloud.video.taobao.com/play/u/755731755/p/1/e/6/t/1/283631891407.mp4" controls width="400px" heigt="400px"></video>

在页面初始化实现后,video标签会将整个mp4文件下载到浏览器,实现后即可播放。然而当mp4文件较大时,缓存工夫就比拟长,播放体验不好。当然也能够应用video.js 来播放,这里就不赘述了。

播放HLS流

HLSHTTP Live Streaming)是一个由Apple公司提出的基于HTTP的流媒体传输协定。视频的封装格局是TS,编码格局是H.264/ACC,除了定义TS视频文件自身,还定义了用来管制播放的m3u8文本文件。挪动端大部分浏览器都反对,也就是说,你能够在挪动端浏览器间接应用vedio标签间接加载一个m3u8文件播放视频或者直播。但在PC端只反对苹果的safari浏览器,其余浏览器想播放须要引入第三方库,如:hls.js:

<script src="https://cdn.jsdelivr.net/npm/hls.js"></script><video id="video"></video><script>  var video = document.getElementById('video');  var videoSrc = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';  if (Hls.isSupported()) {    var hls = new Hls();    hls.loadSource(videoSrc);    hls.attachMedia(video);    hls.on(Hls.Events.MANIFEST_PARSED, function() {      video.play();    });  }</script>

播放HLS流的逻辑很简略,首先依据提供的m3u8地址源通过HTTP申请获取到一级index文件内容如:

#EXTM3U#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=64000500kbps.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7740001000kbps.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=887000500kbps.m3u8#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=76920001000kbps.m3u8

bandwidth 指定视频流的码率,每一个 #EXT-X-STEAM-INF 的下一行是二级index文件的门路,能够是相对路径或者是绝对路径。申请到的二级文件内容如:

#EXTM3U#EXT-X-PLAYLIST-TYPE:VOD#EXT-X-TARGETDURATION:10#EXTINF:10,1000kbps-00001.ts#EXTINF:10,1000kbps-00002.ts#EXTINF:10,1000kbps-00003.ts#EXTINF:10,1000kbps-00004.ts#EXTINF:10,... ...#EXT-X-ENDLIST

能够从二级文件中读取到ts文件的门路,同样能够是相对路径或者绝对路径。 #EXTINF 示意每个ts切片的时长。 #EXT-X-ENDLIST 是视频完结标记,如果有这个标记也表明该流不是一个直播流。
HLS播放的劣势:

  • 能够应用http协定申请数据流
  • 能够切换不同的码率,实现无缝播放

劣势:

  • 提早较高,实时性差,个别提早在10s以上,不适宜做直播
  • ts文件切片小且多,对存储和缓存都有肯定的要求

播放FLV流

FLV(Flash Video)是一种网络视频格式,FLV只能基于flash播放,然而因为flash存在很多平安问题曾经被泛滥厂商摈弃,当初咱们如果要在H5中播放flv格局的视频流能够应用Blibli的开源库:Flv.js,flv.js 原理是解析视频的flv流并实时转换为fmp4格局,再通过 Media Source Extension 喂给浏览器的 video 标签。

<script src="flv.min.js"></script><video id="videoElement"></video><script>    if (flvjs.isSupported()) {        var videoElement = document.getElementById('videoElement');        var flvPlayer = flvjs.createPlayer({            type: 'flv',            url: 'http://example.com/flv/video.flv'        });        flvPlayer.attachMediaElement(videoElement);        flvPlayer.load();        flvPlayer.play();    }</script>

基于Media Source Extensions播放视频流

咱们常常在很多直播网站去看视频,你有没有留神到他们是用的什么流?咱们去B站轻易找一个直播或者视频关上控制台查看播放器,你会发现 video 标签的 src 竟然是 blob 结尾的一个 url 。在后面讲FLV播放时,咱们提到了Media Source Extension ,本节将介绍这种基于MSE的直播计划。

Media Source Extensions 是什么

媒体源扩大(Media Source Extensions,缩写MSE)是一项W3C标准,MSE容许Javascript为audio标签和video标签动静地结构媒体源。

借助MSE的能力,咱们能够将接管到的实时流通过 blob url 往video标签中灌入二进制数据(如fmp4格局流),或者应用 canvas 来实现直播。

简略实现

首先,判断浏览器是否反对MediaSource:

const supportMediaSource = window.MediaSource &&            typeof window.MediaSource.isTypeSupported === 'function' &&            window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42c01f,mp4a.40.2"');

MediaSource反对状况:

接下来新建 MediaSource 实例,并应用生成blob url 加到video标签。并且监听 sourceOpen 事件来判断初始化实现。

const mediaSource = new MediaSource();const video = document.querySelector('#video-box');video.src = URL.createObjectURL(mediaSource);mediaSource.addEventListener('sourceopen',function(){    // TODO})

接下来咱们通过websocket获取原始视频流,解决后通过 SourceBuffer 喂给 mediaSource

const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');const ws = new WebSocket("wss://xxx.websocket.com");ws.onopen = function(evt) {   console.log("Connection open ...");   ws.send("fetch Data");};ws.onmessage = function(evt) {  // 能够在灌入数据前进行转码等操作  sourceBuffer.appendBuffer(evt.data);};ws.onclose = function(evt) {  console.log("Connection closed.");};

通过MSE的形式咱们能够将接管到的视频或者音频流进行端解决,配合WebWorker技术实现疾速转码、反对多播,给咱们有限的设想空间。

H.265视频播放

H.265是ITU-T VCEG继H.264之后所制订的新的视频编码标准。H.265规范围绕着现有的视频编码标准H.264,保留原来的某些技术,同时对一些相干的技术加以改进。新技术应用先进的技术用以改善码流、编码品质、延时和算法复杂度之间的关系,达到最优化设置。
然而因为浏览器不反对H265格局的流,所以咱们无奈间接播放。这时候能够应用MSE的形式在 sourceBuffer.appendBuffer(evt.data) 前将 evt.data 应用 libde265.js  等转码库转码后给到sourceBuffer。或者应用业界成熟的播放器进行播放,如淘系的@ali/videox播放器。

总结

越来越多的厂商更加偏差于H.265的编码格局,然而浏览器对该格局的反对度不敌对的前提下咱们不得不进行转码。应用MSE形式在浏览器端转码,则能借助GPU提高效率和升高提早。但还是无奈兼容所有的PC或者挪动端浏览器,这条路还须要咱们去持续摸索。5G给互联网带来的福利不仅仅是在视频、直播的暴发,我置信web端图像视频技术也将冲破现有的技术瓶颈,WebAssembly、硬件编码等图像渲染技术也将越来越丰盛。

参考

https://baike.baidu.com/item/ffmpeg
https://github.com/Bilibili/flv.js/
https://developer.mozilla.org/zh-CN/docs/Web/API/MediaSource

文章可随便转载,但请保留此原文链接。
十分欢送有激情的你退出 ES2049 Studio,简历请发送至 caijun.hcj@alibaba-inc.com 。