写点什么

视频直播技术干货:一文读懂主流视频直播系统的推拉流架构、传输协议等

作者:JackJiang
  • 2022 年 5 月 31 日
  • 本文字数:7422 字

    阅读完需:约 24 分钟

视频直播技术干货:一文读懂主流视频直播系统的推拉流架构、传输协议等

本文由蘑菇街前端开发工程师“三体”分享,原题“蘑菇街云端直播探索——启航篇”,有修订。

1、引言

随着移动网络网速的提升与资费的降低,视频直播作为一个新的娱乐方式已经被越来越多的用户逐渐接受。特别是最近这几年,视频直播已经不仅仅被运用在传统的秀场、游戏类板块,更是作为电商的一种新模式得到迅速成长。

本文将通过介绍实时视频直播技术体系,包括常用的推拉流架构、传输协议等,让你对现今主流的视频直播技术有一个基本的认知。

2、蘑菇街的直播架构概览

目前蘑菇街直播推拉流主流程依赖于某云直播的服务。

云直播提供的推流方式有两种:

  • 1)一是通过集成 SDK 的方式进行推流(用于手机端开播);

  • 2)另一种是通过 RTMP 协议向远端服务器进行推流(用于 PC 开播端或专业控台设备开播)。

除去推拉流,该云平台也提供了云通信(IM 即时通讯能力)和直播录制等云服务,组成了一套直播所需要的基础服务。

3、推拉流架构 1:厂商 SDK 推拉流

如上题所示,这一种推拉流架构方式需要依赖腾讯这类厂商提供的手机互动直播 SDK,通过在主播端 APP 和用户端 APP 都集成 SDK,使得主播端和用户端都拥有推拉流的功能。

这种推拉流架构的逻辑原理是这样的:

  • 1)主播端和用户端分别与云直播的互动直播后台建立长连接;

  • 2)主播端通过UDT私有协议向互动直播后台推送音视频流;

  • 3)互动直播后台接收到音视频流后做转发,直接下发给与之建立连接的用户端。

这种推拉流方式有几点优势:

  • 1)只需要在客户端中集成 SDK:通过手机就可以开播,对于主播开播的要求比较低,适合直播业务快速铺开;

  • 2)互动直播后台仅做转发:没有转码,上传 CDN 等额外操作,整体延迟比较低;

  • 3)主播端和用户端都可以作为音视频上传的发起方:适合连麦、视频会话等场景。

4、推拉流架构 2:旁路推流

之前介绍了通过手机 SDK 推拉流的直播方式,看起来在手机客户端中观看直播的场景已经解决了。

那么问题来了:如果我想要在 H5、小程序等其他场景下观看直播,没有办法接入 SDK,需要怎么处理呢?

这个时候需要引入一个新的概念——旁路推流。

旁路推流指的是:通过协议转换将音视频流对接到标准的直播 CDN 系统上。

目前云直播开启旁路推流后,会通过互动直播后台将音视频流推送到云直播后台,云直播后台负责将收到音视频流转码成通用的协议格式并且推送到 CDN,这样 H5、小程序等端就可以通过 CDN 拉取到通用格式的音视频流进行播放了。

目前蘑菇街直播旁路开启的协议类型有 HLS、FLV、RTMP 三种,已经可以覆盖到所有的播放场景,在后续章节会对这几种协议做详细的介绍。

5、推拉流架构 3:RTMP 推流

随着直播业务发展,一些主播逐渐不满足于手机开播的效果,并且电商直播需要高保真地将商品展示在屏幕上,需要通过更加高清专业的设备进行直播,RTMP 推流技术应运而生。

我们通过使用 OBS 等流媒体录影程序,对专业设备录制的多路流进行合并,并且将音视频流上传到指定的推流地址。由于 OBS 推流使用了 RTMP 协议,因此我们称这一种推流类型为 RTMP 推流。

我们首先在云直播后台申请到推流地址和秘钥,将推流地址和秘钥配置到 OBS 软件当中,调整推流各项参数,点击推流以后,OBS 就会通过 RTMP 协议向对应的推流地址推送音视频流。

这一种推流方式和 SDK 推流的不同之处在于音视频流是直接被推送到了云直播后台进行转码和上传 CDN 的,没有直接将直播流转推到用户端的下行方式,因此相比 SDK 推流延迟会长一些。

总结下来 RTMP 推流的优势和劣势比较明显。

优势主要是:

  • 1)可以接入专业的直播摄像头、麦克风,直播的整体效果明显优于手机开播;

  • 2)OBS 已经有比较多成熟的插件,比如目前蘑菇街主播常用 YY 助手做一些美颜的处理,并且 OBS 本身已经支持滤镜、绿幕、多路视频合成等功能,功能比手机端强大。

劣势主要是:

  • 1)OBS 本身配置比较复杂,需要专业设备支持,对主播的要求明显更高,通常需要一个固定的场地进行直播;

  • 2)RTMP 需要云端转码,并且本地上传时也会在 OBS 中配置 GOP 和缓冲,延时相对较长。

6、高可用架构方案:云互备

业务发展到一定阶段后,我们对于业务的稳定性也会有更高的要求,比如当云服务商服务出现问题时,我们没有备用方案就会出现业务一直等待服务商修复进度的问题。

因此云互备方案就出现了:云互备指的是直播业务同时对接多家云服务商,当一家云服务商出现问题时,快速切换到其他服务商的服务节点,保证业务不受影响。

直播业务中经常遇到服务商的 CDN 节点下行速度较慢,或者是 CDN 节点存储的直播流有问题,此类问题有地域性,很难排查,因此目前做的互备云方案,主要是备份 CDN 节点。

目前蘑菇街整体的推流流程已经依赖了原有云平台的服务,因此我们通过在云直播后台中转推一路流到备份云平台上,备份云在接收到了直播流后会对流转码并且上传到备份云自身的 CDN 系统当中。一旦主平台 CDN 节点出现问题,我们可以将下发的拉流地址替换成备份云拉流地址,这样就可以保证业务快速修复并且观众无感知。

7、视频直播数据流解封装原理

介绍流协议之前,先要介绍我们从云端拿到一份数据,要经过几个步骤才能解析出最终需要的音视频数据。

如上图所示,总体来说,从获取到数据到最终将音视频播放出来要经历四个步骤。

第一步:解协议。

协议封装的时候通常会携带一些头部描述信息或者信令数据,这一部分数据对我们音视频播放没有作用,因此我们需要从中提取出具体的音视频封装格式数据,我们在直播中常用的协议有 HTTP 和 RTMP 两种。

第二步:解封装。

获取到封装格式数据以后需要进行解封装操作,从中分别提取音频压缩流数据和视频压缩流数据,封装格式数据我们平时经常见到的如 MP4、AVI,在直播中我们接触比较多的封装格式有 TS、FLV。

第三步:解码音视频。

到这里我们已经获取了音视频的压缩编码数据。

我们日常经常听到的视频压缩编码数据有 H.26X 系列和 MPEG 系列等,音频编码格式有我们熟悉的 MP3、ACC 等。

之所以我们能见到如此多的编码格式,是因为各种组织都提出了自己的编码标准,并且会相继推出一些新的议案,但是由于推广和收费问题,目前主流的编码格式也并不多。

获取压缩数据以后接下来需要将音视频压缩数据解码,获取非压缩的颜色数据和非压缩的音频抽样数据。颜色数据有我们平时熟知的 RGB,不过在视频的中常用的颜色数据格式是 YUV,指的是通过明亮度、色调、饱和度确定一个像素点的色值。音频抽样数据通常使用的有 PCM。

第四步:音视频同步播放。

最后我们需要比对音视频的时间轴,将音视频解码后的数据交给显卡声卡同步播放。

PS:如果你对上述流程还不太理解,建议进一步阅读以下系列文章:

  1. 移动端实时音视频直播技术详解(一):开篇

  2. 移动端实时音视频直播技术详解(二):采集

  3. 移动端实时音视频直播技术详解(三):处理

  4. 移动端实时音视频直播技术详解(四):编码和封装

  5. 移动端实时音视频直播技术详解(五):推流和传输

  6. 移动端实时音视频直播技术详解(六):延迟优化

另外:有关音视频编解码技术的文章,也可以详细学习以下文章:

  1. 视频编解码之:《理论概述》、《数字视频介绍》、《编码基础》、《预测技术介绍

  2. 认识主流视频编码技术H.264

  3. 如何开始音频编解码技术的学习

  4. 音频基础及编码原理入门

  5. 常见的实时语音通讯编码标准

  6. 实时视频编码H.264的特点与优势》、《视频编码H.264、VP8的前世今生

  7. 详解音频编解码的原理、演进和应用选型》、《零基础,史上最通俗视频编码技术入门

8、视频直播传输协议 1:HLS

首先介绍一下 HLS 协议。HLS 是 HTTP Live Streaming 的简写,是由苹果公司提出的流媒体网络传输协议。

从名字可以明显看出:这一套协议是基于 HTTP 协议传输的。

说到 HLS 协议:首先需要了解这一种协议是以视频切片的形式分段播放的,协议中使用的切片视频格式是 TS,也就是我们前文提到的封装格式。

在我们获取 TS 文件之前:协议首先要求请求一个 M3U8 格式的文件,M3U8 是一个描述索引文件,它以一定的格式描述了 TS 地址的指向,我们根据 M3U8 文件中描述的内容,就可以获取每一段 TS 文件的 CDN 地址,通过加载 TS 地址分段播放就可以组合出一整段完整的视频。

使用 HLS 协议播放视频时:首先会请求一个 M3U8 文件,如果是点播只需要在初始化时获取一次就可以拿到所有的 TS 切片指向,但如果是直播的话就需要不停地轮询 M3U8 文件,获取新的 TS 切片。

获取到 M3U8 后:我们可以看一下里面的内容。首先开头是一些通用描述信息,比如第一个分片序列号、片段最大时长和总时长等,接下来就是具体 TS 对应的地址列表。如果是直播,那么每次请求 M3U8 文件里面的 TS 列表都会随着最新的直播切片更新,从而达到直播流播放的效果。

HLS 这种切片播放的格式在点播播放时是比较适用的,一些大的视频网站也都有用这一种协议作为播放方案。

首先:切片播放的特性特别适用于点播播放中视频清晰度、多语种的热切换。比如我们播放一个视频,起初选择的是标清视频播放,当我们看了一半觉得不够清晰,需要换成超清的,这时候只需要将标清的 M3U8 文件替换成超清的 M3U8 文件,当我们播放到下一个 TS 节点时,视频就会自动替换成超清的 TS 文件,不需要对视频做重新初始化。

其次:切片播放的形式也可以比较容易地在视频中插入广告等内容。

在直播场景下,HLS 也是一个比较常用的协议,他最大的优势是苹果大佬的加持,对这一套协议推广的比较好,特别是移动端。将 M3U8 文件地址喂给 video 就可以直接播放,PC 端用 MSE 解码后大部分浏览器也都能够支持。但是由于其分片加载的特性,直播的延迟相对较长。比如我们一个 M3U8 有 5 个 TS 文件,每个 TS 文件播放时长是 2 秒,那么一个 M3U8 文件的播放时长就是 10 秒,也就是说这个 M3U8 播放的直播进度至少是 10 秒之前的,这对于直播场景来说是一个比较大的弊端。

HLS 中用到的 TS 封装格式,视频编码格式是通常是 H.264 或 MPEG-4,音频编码格式为 AAC 或 MP3。

一个 ts 由多个定长的 packtet 组成,通常是 188 个字节,每个 packtet 有 head 和 payload 组成,head 中包含一些标识符、错误信息、包位置等基础信息。payload 可以简单理解为音视频信息,但实际上下层还有还有两层封装,将封装解码后可以获取到音视频流的编码数据。

9、视频直播传输协议 2:HTTP-FLV

HTTP-FLV 协议,从名字上就可以明显看出是通过 HTTP 协议来传输 FLV 封装格式的一种协议。

FLV 是 Flash Video 的简写,是一种文件体积小,适合在网络上传输的封包方式。FlV 的视频编码格式通常是 H.264,音频编码是 ACC 或 MP3。

HTTP-FLV 在直播中是通过走 HTTP 长连接的方式,通过分块传输向请求端传递 FLV 封包数据。

在直播中,我们通过 HTTP-FLV 协议的拉流地址可以拉取到一段 chunked 数据。

打开文件后可以读取到 16 进制的文件流,通过和 FLV 包结构对比,可以发现这些数据就是我们需要的 FLV 数据。

首先开头是头部信息:464C56 转换 ASCII 码后是 FLV 三个字符,01 指的是版本号,05 转换为 2 进制后第 6 位和第 8 位分别代表是否存在音频和视频,09 代表头部长度占了几个字节。

后续就是正式的音视频数据:是通过一个个的 FLV TAG 进行封装,每一个 TAG 也有头部信息,标注这个 TAG 是音频信息、视频信息还是脚本信息。我们通过解析 TAG 就可以分别提取音视频的压缩编码信息。

FLV 这一种格式在 video 中并不是原生支持的,我们要播放这一种格式的封包格式需要通过 MSE 对影视片的压缩编码信息进行解码,因此需要浏览器能够支持 MSE 这一 API。由于 HTTP-FLV 的传输是通过长连接传输文件流的形式,需要浏览器支持 Stream IO 或者 fetch,对于浏览器的兼容性要求会比较高。

FLV 在延迟问题上相比切片播放的 HLS 会好很多,目前看来 FLV 的延迟主要是受编码时设置的 GOP 长度的影响。

这边简单介绍一下 GOP:在 H.264 视频编码的过程中,会生成三种帧类型:I 帧、B 帧和 P 帧。I 帧就是我们通常说的关键帧,关键帧内包括了完整的帧内信息,可以直接作为其他帧的参考帧。B 帧和 P 帧为了将数据压缩得更小,需要由其他帧推断出帧内的信息。因此两个 I 帧之间的时长也可以被视作最小的视频播放片段时长。从视频推送的稳定性考虑,我们也要求主播将关键帧间隔设置为定长,通常是 1-3 秒,因此除去其他因素,我们的直播在播放时也会产生 1-3 秒的延时。

10、视频直播传输协议 3:RTMP

RTMP协议实际可以与 HTTP-FLV 协议归做同一种类型。

他们的封包格式都是 FlV,但 HTTP-FLV 使用的传输协议是 HTTP,RTMP 拉流使用 RTMP 作为传输协议。

RTMP 是 Adobe 公司基于 TCP 做的一套实时消息传输协议,经常与 Flash 播放器匹配使用。

RTMP 协议的优缺点非常明显。

RTMP 协议的优点主要是:

  • 1)首先和 HTTP-FLV 一样,延迟比较低;

  • 2)其次它的稳定性非常好,适合长时间播放(由于播放时借用了 Flash player 强大的功能,即使开多路流同时播放也能保证页面不出现卡顿,很适合监控等场景)。

但是 Flash player 目前在 web 端属于墙倒众人推的境地,主流浏览器渐渐都表示不再支持 Flash player 插件,在 MAC 上使用能够立刻将电脑变成烧烤用的铁板,资源消耗很大。在移动端 H5 基本属于完全不支持的状态,兼容性是它最大的问题。

11、视频直播传输协议 4:MPEG-DASH

MPEG-DASH 这一协议属于新兴势力,和 HLS 一样,都是通过切片视频的方式进行播放。

他产生的背景是早期各大公司都自己搞自己的一套协议。比如苹果搞了 HLS、微软搞了 MSS、Adobe 还搞了 HDS,这样使用者需要在多套协议封装的兼容问题上痛苦不堪。

于是大佬们凑到一起,将之前各个公司的流媒体协议方案做了一个整合,搞了一个新的协议。

由于同为切片视频播放的协议,DASH 优劣势和 HLS 类似,可以支持切片之间多视频码率、多音轨的切换,比较适合点播业务,在直播中还是会有延时较长的问题。

12、如何选择最优的视频直播传输协议

视频直播协议选择非常关键的两点,在前文都已经有提到了,即低延时和更优的兼容性。

首先从延时角度考虑:不考虑云端转码以及上下行的消耗,HLS 和 MPEG-DASH 通过将切片时长减短,延时在 10 秒左右;RTMP 和 FLV 理论上延时相当,在 2-3 秒。因此在延时方面 HLS ≈ DASH > RTMP ≈ FLV。

从兼容性角度考虑:HLS > FLV > RTMP,DASH 由于一些项目历史原因,并且定位和 HLS 重复了,暂时没有对其兼容性做一个详尽的测试,被推出了选择的考虑范围。

综上所述:我们可以通过动态判断环境的方式,选择当前环境下可用的最低延迟的协议。大致的策略就是优先使用 HTTP-FLV,使用 HLS 作为兜底,在一些特殊需求场景下通过手动配置的方式切换为 RTMP。

对于 HLS 和 HTTP-FLV:我们可以直接使用 hls.js 和 flv.js 做做解码播放,这两个库内部都是通过 MSE 做的解码。首先根据视频封装格式提取出对应的音视频 chunk 数据,在 MediaSource 中分别对音频和视频创建 SourceBuffer,将音视频的编码数据喂给 SourceBuffer 后 SourceBuffer 内部会处理完剩下的解码和音视频对齐工作,最后 MediaSource 将 Video 标签中的 src 替换成 MediaSource 对象进行播放。

在判断播放环境时我们可以参照flv.js内部的判断方式,通过调用 MSE 判断方法和模拟请求的方式判断 MSE 和 StreamIO 是否可用:

// 判断 MediaSource 是否被浏览器支持,H.264 视频编码和 Acc 音频编码是否能够被支持解码

window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');

如果 FLV 播放不被支持的情况下:需要降级到 HLS,这时候需要判断浏览器环境是否在移动端,移动端通常不需要 hls.js 通过 MSE 解码的方式进行播放,直接将 M3U8 的地址交给 video 的 src 即可。如果是 PC 端则判断 MSE 是否可用,如果可用就使用 hls.js 解码播放。

这些判读可以在自己的逻辑里提前判断后去拉取对应解码库的 CDN,而不是等待三方库加载完成后使用三方库内部的方法判断,这样在选择解码库时就可以不把所有的库都拉下来,提高加载速度。

13、同层播放如何解决

电商直播需要观众操作和互动的部分比起传统的直播更加多,因此产品设计的时候很多的功能模块会悬浮在直播视频上方减少占用的空间。这个时候就会遇到一个移动端播放器的老大难问题——同层播放。

同层播放问题:是指在移动端 H5 页面中,一些浏览器内核为了提升用户体验,将 video 标签被劫持替换为 native 播放器,导致其他元素无法覆盖于播放器之上。

比如我们想要在直播间播放器上方增加聊天窗口,将聊天窗口通过绝对定位提升 z-index 置于播放器上方,在 PC 中测试完全正常。但在移动端的一些浏览器中,video 被替换成了 native 播放器,native 的元素层级高于我们的普通元素,导致聊天窗口实际显示的时候在播放器下方。

要解决这个问题,首先要分多个场景。

首先在 iOS 系统中:正常情况下 video 标签会自动被全屏播放,但 iOS10 以上已经原生提供了 video 的同层属性,我们在 video 标签上增加 playsinline/webkit-playsinline 可以解决 iOS 系统中大部分浏览器的同层问题,剩下的低系统版本的浏览器以及一些 APP 内的 webview 容器(譬如微博),用上面提的属性并不管用,调用三方库 iphone-inline-video 可以解决大部分剩余问题。

在 Android 端:大部分腾讯系的 APP 内置的 webview 容器用的都是 X5 内核,X5 内核会将 video 替换成原生定制的播放器已便于增强一些功能。X5 也提供了一套同层的方案(该方案官方文档链接已无法打开),给 video 标签写入 X5 同层属性也可以在 X5 内核中实现内联播放。不过 X5 的同层属性在各个 X5 版本中表现都不太一样(比如低版本 X5 中需要使用 X5 全屏播放模式才能保证 MSE 播放的视频同层生效),需要注意区分版本。

在蘑菇街 App 中,目前集成的 X5 内核版本比较老,在使用 MSE 的情况下会导致 X5 同层参数不生效。但如果集成新版本的 X5 内核,需要对大量的线上页面做回归测试,成本比较高,因此提供了一套折中的解决方案。通过在页面 URL 中增加一个开关参数,容器读取到参数以后会将 X5 内核降级为系统原生的浏览器内核,这样可以在解决浏览器视频同层问题的同时也将内核变动的影响范围控制在单个页面当中。

14、相关文章

[1] 移动端实时音视频直播技术详解(四):编码和封装

[2] 移动端实时音视频直播技术详解(五):推流和传输

[3] 实现延迟低于500毫秒的1080P实时音视频直播的实践分享

[4] 浅谈开发实时视频直播平台的技术要点

[5] 直播系统聊天技术(七):直播间海量聊天消息的架构设计难点实践

[6] 从0到1:万人在线的实时音视频直播技术实践分享(视频+PPT) [附件下载]

[7] 实时视频编码H.264的特点与优势

[8] 视频编码H.264、VP8的前世今生

[9] 零基础,史上最通俗视频编码技术入门

[10] 视频编解码之编码基础

[11] 零基础入门:实时音视频技术基础知识全面盘点

[12] 实时音视频面视必备:快速掌握11个视频技术相关的基础概念

[13] 写给小白的实时音视频技术入门提纲

学习交流:

- 移动端 IM 开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源 IM 框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

(本文已同步发布于:http://www.52im.net/thread-3922-1-1.html

用户头像

JackJiang

关注

还未添加个人签名 2019.08.26 加入

开源IM框架MobileIMSDK、BeautyEye的作者。

评论

发布
暂无评论
视频直播技术干货:一文读懂主流视频直播系统的推拉流架构、传输协议等_实时音视频_JackJiang_InfoQ写作社区