Skip to content

传输协议 ​

在零几年的时候,想要看视频往往需要先将视频文件完整地下载到本地,然后再进行播放。经过了十多年的时间,如今已经可以在线直接播放视频,而且能随意拖曳进度条,这样的变化多亏于音视频背后传输协议的演变。

视频的封装协议决定了音视频信息的组织方式,视频的传输协议则决定了这些信息如何从服务器端传输到客户端。就例如下图中,封装格式就类似于集装箱般组织数据,而传输协议则就像船一样,负责将数据传输给用户。

tranform ship

视频播放主要分为点播和直播两个场景,不同的场景适用不同的传输协议,不过有些协议也可以同时应用于两个场景值,我们先通过表格来整体看一下:

HTTP 渐进式下载HLSHTTP-FLVRTMPwebRTC
适用场景点播点播/直播点播/直播直播直播
简单介绍过渡性方案,一边下载一边播放将视频文件拆分成许多个小文件,然后通过 HTTP 传输通过 JS 将 FLV 文件解析后喂给 video 标签Adobe 公司推出,依赖 Flash 进行播放谷歌推出,原本用于小型会议 P2P 直播
传输层HTTP 长连接HTTP 短连接HTTP 短连接TCP 长连接UDP
封装格式MP4TSFLVFLVRTP
实现复杂度简单简单简单复杂复杂
直播的启播延时-很长(10秒)较低(2-5秒)低(1-2秒)较低(1秒内)
客户端依赖原生支持iOS/Android 支持,PC 端部分浏览器需引入 hls.js 依赖引入 flv.js 依赖Flash有待提升

由于我在腾讯课堂负责的是 HLS 点播相关的功能,所以接下来主要讲一讲 HLS 相关的知识。

HLS ​

HLS 的全称是 HTTP Live Streaming,翻译下就是基于 HTTP 的流媒体传输协议,由苹果公司在 2009 年推出。

整体流程 ​

服务器端提前将视频文件拆分成许多小片段(常称为切片,封装格式为 ts),并得到含有全部分片信息的 M3U8 文件,然后分发给 CDN 网络,最后通过 HTTP 协议传输给用户,因而架构上非常简便。

客户端在看视频的时候,会先请求 M3U8 文件,然后再根据网络状况、设备分辨率等来加载对应的视频切片,整体流程如下:

M3U8 流程

M3U8 文件 ​

这里谈到了两种用途的 M3U8 文件:

  • master playlist:包含了适用于不同分辨率、不同带宽下的 media playlist 文件请求地址列表。
  • media playlist:包含了一个视频文件中所有分片的请求地址列表。

首先来看一个 master playlist 的例子,分别在第 3、5、7 行,通过 BANDWIDTH=399580,RESOLUTION=1136x480 这种方式,指出了在不同带宽和分辨率下应该请求的 media playlist 地址。

txt
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=399580,RESOLUTION=1136x480
xxxxxxxx(URL1)
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=707342,RESOLUTION=1706x720
yyyyyyyy(URL2)
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=1093740,RESOLUTION=2560x1080
zzzzzzzz(URL3)

接下来看看 media playlist 的例子,大体上它是一个接一个的分片地址组成的 M3U8 文件,例如 v.f30742.ts?start=0&end=770991&type=mpegts/v.f30742.ts?start=770992&end=1297023&type=mpegts 这样依次排列,然后再加上一些额外信息,在下面的例子中包含了以下的信息:

  • #EXT-X-VERSION:3:表示至少应该用第三版 HLS 规范解析该文件。
  • #EXT-X-TARGETDURATION:10:表示每一个分片的时长不超过 10 秒。
  • #EXT-X-MEDIA-SEQUENCE:0:表示在分片地址列表中,第一个地址对应的分片序号为 0。
  • #EXT-X-KEY:METHOD=AES-128,URL="xxx":表示分片被 AES-128 加密,密钥需要从 xxx 地址去获得。
  • #EXTINF:10.000000:表示下一个分片的时长是 10 秒。

TIP

这些字段的含义都可以快速的在 RFC 8216 - HTTP Live Streaming 中找到。

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="https://ke.qq.com/cgi-bin/qcloud/get_dk?edk=xxxxxxx",IV=0x00000000000000000000000000000000
#EXTINF:10.000000,
v.f30742.ts?start=0&end=770991&type=mpegts&us=4449635466523407452&t=5f44f0e4&sign=4e68d431d681968c833cb8a21c86c67f
#EXT-X-KEY:METHOD=AES-128,URI="https://ke.qq.com/cgi-bin/qcloud/get_dk?edk=xxxxxxx",IV=0x00000000000000000000000000000000
#EXTINF:10.000000,
v.f30742.ts?start=770992&end=1297023&type=mpegts&us=4449635466523407452&sign=4e68d431d681968c833cb8a21c86c67f&t=5f44f0e4

.....

#EXT-X-ENDLIST

正由于通过 M3U8 来进行视频信息的传递,所以它非常的灵活,不过也由于需要先请求 M3U8 文件,然后解析出分片地址,最后再去请求视频文件的分片,所以这种方式的启播延时也较长。

Web 端实现 ​

在 Android/iOS 设备及 PC 端的 Safari 浏览器上,已经原生支持 HLS。在 PC 端的其它浏览器上,需要引入 hls.js 进行兼容,它通过 MediaSource Extensions,将视频数据解析之后喂给 <video> 标签进行播放。

参考资料 ​

  1. RFC 8216 - HTTP Live Streaming

保持独立思考