hls.js 是一款基于 Media Source Extensions 开发的,用于实现 HTTP Live Streaming 开源JavaScript类库。它可以实现将MPEG-2 和 AAC/MP3码流变成自制的 MP4的分片。并且可以直接绑定在Video 上,实现播放。
文章主要是通过解读源码,希望读者可以了解实现基本的前端 HLS 的主要流程,同事也可以扩展读者对 Media Source Extensions 和 video api 以及 视频编解码的相关知识有更进一部的了解。
第一篇文章可能会从整体方面,让大家理解一下调用的
整体流程,让大家对真个项目的基本代码架构有个基础的认识。
目录指南
只对和项目相关的文件进行说明
dist // 打包后的文件目录,
src
+ cotroler
- abr-controller.js // 用于分片筛选
- audio-stream-controller.js
- audio-track-controller.js
- buffer-controler.js // 用于对 buffer 的操作
- cap-level-controller.js // 限流处理
- fps-controller.js // 监测帧数
- id3-track-controller.js // id3 track 是术语,一般记录 mp3 文件的 封面,歌词等信息
- level-controller.js //
- stream-controller.js // 视频流的处理
- subtitle-track-controller.js // 后面三个 字幕 相关
- subtitle-stream-comtroller.js
- timeline-controller.js
+ crypt 对加密视频流进行解码
+ demux // 逆向多路复用
+ helper
- acc.js
- buffer-helper.js 对 buffer 之类的辅助函数
- level-helper.js
+ loader
- fragment-loader.js // 对分片进行加载
- key-loader.js
- playlist-loader.js // 处理播放内容列表
+ remux
+ utils // 辅助类库 需要用到再提及
- attr-list.js
- binary-search.js
- cea-608-parser.js
- cues.js
- discontinuities.js
- ewma-bandwidth-estimator.js
- fetch-loader.js
- hex.js
- logger.js
- timeRanges.js
- vttcue.js
- vttparser.js
- webvtt-prser.js
- xhr-loader.js
- config.js // 基本配置
- errors.js // 用于定义错误码
- event-handler.js // 这是一个 controller 集成的ji
- events.js // 定义事件类型
- hls.js hls //类库定义
- index.js
基本使用
我们在深入代码之前,可以看下基本使用,可以让页面跑起来。
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video"></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
}
</script>
其中如果你希望自己生成 m3u8 的文件,你可以使用 ffmpeg 进行处理,将单一的 mp4 拆分成多个分片文件。
ffmpeg -i your_file.mp4 -b:v 1M -g 60 -hls_time 2 -hls_list_size 0 -hls_segment_size 500000 output.m3u8
npm
如果你使用 npm 引入模块的话,在 dist
目录下 存在多个文件,其中 hls.light.js ,是通过配置去掉可选音频流和字幕流处理的版本,相对而言其体积更小。
npm install hls.js --save
事件流
由于内部通信都是基于 EventEmitter
来实现,透过事件流,你可以了解到代码运行的整体流程。
hls 整体流程如下
hls实际会先通过 ajax(loader 是可以完成自定义的) 请求 m3u8文件,然后会读取到文件的分片列表,以及视频的编码格式,时长等。随后会按照顺序(非 seek )去对分片进行请求,这些也是通过 ajax 请求二进制的文件,然后借助 Media Source Extensions 将 buffer 内容进行合流,然后组成一个可播的媒体资源文件。
由于内部通过自定事件进行数据传递和流程控制,参考下面的图:
其中主要的流程是在 level-controller.js 以及 stream-controller.js完成。
后面会分析这里面的具体实现。
系列文章
扩展阅读
由于 hls.js 在阅读前,要求作者对视频格式,编解码,以及 Media Source Extensions 以及 buffer 操作等知识有要求。大家可以参考下面提供的一些资料 :
-
[Support for ISOBMFF-based MIME types in Browsers](https://cconcolato.github.io/media-mime-support/#video/mp4; codecs="avc1.64001f")