实现
一、认识
柏拉文播放器 基于hlsjs
和web components
,让原生的标签r-player
拥有统一的视频控件。 不采用new Player(options)
的方式挂载到指定dom
,视图的归视图,逻辑的归逻辑,所见及所得,更加直观。
1.1 服务端
-
视频转码
-
生成不同码率的视频
-
进行视频标准加密
-
不同码率视频合并,用于动态码率播放
1.2 Web 端
-
web
端播放器的设计 -
web
端播放器的自定义扩展 -
可拖拽进度条
-
音量控制
-
根据当前带宽自适应码率切换
-
手动清晰度切换
-
倍速播放
-
样式自定义覆 盖
-
**
hls
**协议标准加密视频播放 -
基于原生开发,可在所有框架运行,统一跨框架情况
-
各浏览器控件统一
二、方案
2.1 MediaSource和视频编码,解码,封装
在web
上播放音视频其实限制还是很大的。如何解决这些限制,就会用到 MediaSource
。视频其实是无数个图片的叠加,如果视频是一秒60
帧,大约一秒中需要播放60
张图片。这就导致一个几分钟的视频,就会非常大。比如上面介绍的无损格式,avi
格式,每分钟视频大约 2-3 GB
。这时候视频就需要进行编码。其实就是压缩。
编码分为视频编码和音频编码
-
常见的视频编码有:
-
MPEG
系列:MPEG-1
第二部分、MPEG-2
第二部分(等同于H.262
)、MPEG-4
第二部分、MPEG-4
第十部分(等同于H.264
,有时候也被叫做MPEG-4 AVC
或H.264/AVC
)。 -
H.26x
系列:H.261
、H.262
、H.263
、H.264
(等同于MPEG-4
第十部分)、H.265/HEVC
(ITU-T
和ISO/IEC
联合推出)。 -
其它视频编码:
WMV
系列、RV
系列、VC-1
、DivX
、XviD
、X264
、X265
、VP8
、VP9
、Sorenson Video
、AVS
。
-
-
常见的音频编码有:
AAC
,MP3
,AC-3
等
编码之后,还需要将音频和视频合并在一个文件里,这就是封装。
所以相对的,播放一个视频,就需要解封装,解码,音视频同步喂给声卡和显卡进行播放。
MediaSource
做的就是这个工作,读取视频流,转换成浏览器能播放的格式。
2.2 HLS 播放方案
采用 HLS
技术方案,有以下几个原因:
-
兼容性: 上面介绍了各种视频格式,还有浏览器的兼容性, 其中
HLS
协议是Apple
公司实现的,在Apple
的全系列产品包括iPhone
、iPad
、Safari
等都可以原生支持播放HLS
。对于其他浏览器,可以通过MediaSource
解封装,解码,转码,进行播放。这样也就解决了MediaSource
的兼容性问题。 -
业务场景需求: 目前对于视频的加密有着强需求,比如需要用户付费才能观看一些视频。而
HLS
协议天然自带标准加密,同时也能基于HLS
扩展私有加密。 -
HLS
协议自带支持分片传输和动态码率自适应播放 -
有现成的技术方案,
Hls.js
三、服务端
服务端 主要是生成了HLS
协议的视频播放的地址。
3.1 视频转码
选择了采用HLS
协议的播放方式,那么首先需要处理视频,这部分目前是在服务端进行处理。利用ffmpeg
的能力。
如果以后能将ffmpeg
搬上浏览器,且没有性能问题就好了。现在有类似的webassembly
的npm
包,但性能有点小问题
基于 ffmpeg
视频的转码命令如下:
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_segment_filename output_%05d.ts output.m3u8 -y
-
-i
: 指定输入的视频 -
-hls_time
: 指定分片的时间,单位是秒 -
-hls_list_size
: 指定hls
列表的数量,这里不限制 -
-c:v
: 指定视频的编码格式 -
-b:v
: 指定视频的码率,这里是2M比特率 -
-hls_segment_filename
: 指定输出的ts文件名字,这里表示是output_
+
五位数字 -
output.m3u8
指定输出m3u8
文件的名字 -
-y
有些场景,比如是否覆盖,直接选择是,避免程序卡住
为了自动化执行,这里会用到node
的spawn
模块,创建一个子进程,在子进程中执行ffmpeg
的命令。
const exec = ({ params, data }: ExecOption): Promise<ExecResult> => {
return new Promise((r, j) => {
const cp = spawn('ffmpeg', params);
cp.stderr.pipe(process.stdout);
cp.on('error', (err) => {
j(err);
});
cp.on('close', (code) => {
r({ code, data });
});
cp.on('exit', (code) => {
r({ code, data });
});
});
};
这时候,视频就会在指定的位置输出了,会生成一个m3u8
和多个ts
ts
是视频文件,m3u8
更像是索引文件,用来描述ts
,比如在什么时间,播放什么ts
。主要内容如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.380622,
5_00000.ts
#EXTINF:10.380622,
5_00001.ts
#EXTINF:10.380622,
5_00002.ts
#EXTINF:10.380622,
5_00003.ts
#EXTINF:6.560556,
5_00004.ts
#EXTINF:1.619378,
5_00005.ts
#EXTINF:5.024189,
5_00006.ts
#EXT-X-ENDLIST