共计 5105 个字符,预计需要花费 13 分钟才能阅读完成。
前言
毫无疑问,当初是短视频、直播的时代。视频内容逐步代替图文模式成为网友们获取陈腐事物以及展示自我的一大媒介。随着 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 流
HLS(HTTP 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=64000
500kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=774000
1000kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=887000
500kbps.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7692000
1000kbps.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。