流媒体服务架构及协议

概述

这篇文章介绍了当前常见的流媒体服务架构和实现协议,以及各种流媒体协议的特点对比。

关于流媒体服务

流媒体服务是提供音频、视频等多媒体数据传输和存储服务,比如视频直播服务。

流媒体服务工作原理

视频播放转码工作流程

graph TB;
videoFile(视频文件) ---> decapsulation(解封装) ---> videoAudioBlock(音视频数据块)
videoAudioBlock ---> videoDecoder(视频解码器) ---> videoFrame(视频帧) ---> videoCoder(视频编码器) ---> videoAudioBlock2(音视频数据块) 
videoAudioBlock ---> audioDecoder(音频解码器) ---> audioFrame(音频甄) ---> audioCoder(音频编码器) ---> videoAudioBlock2
videoFrame --"处理, 如改变分辨率、合成图像"--> videoFrame
audioFrame --"处理, 如修改采样率"--> audioFrame
videoAudioBlock2 ---> encapsulation(封装) ---> newVideoFile(新视频)

直播工作流程

graph TB;
liveStream(直播流) --"推流"--> streamServer(流媒体服务器) 
tramsform(转码程序) --"拉流"--> streamServer
tramsform --"推流"--> streamServer2(流媒体服务器)
user(用户观看) --"拉流"--> streamServer2

(1)推流:直播源将视频流推送到流媒体服务器;

(2)转码:转码程序从流媒体服务器拉取视频流,对视频流进行转码,转成用户观看使用的协议,将新的视频流推送到用户观看的流媒体服务器。

流媒体服务器作为视频流的中转站,会在内存中实时存储视频流的一部分数据,供用户拉取,随时间推移不断用新数据覆盖。

(3)拉流:用户从流媒体服务器拉取视频流到本地观看。

如果直播推流和用户观看拉流使用的协议相同,不需要转码,则只需要一个流媒体服务即可。

直播流媒体服务相关协议技术

推流

直播场景相关协议

直播推流一般采用 RTMP 协议推流,流媒体服务软件可以是 SRS、加了 RTMP-server 插件的 Nginx 等。

graph RL;
pusher(推流软件) --"推流(RTMP)"--> streamServer(流媒体服务区)
transform(转码程序) --"拉流"--> streamServer
转播场景相关协议

转播场景下,已经有服务方提供了流媒体服务,只需要让转码程序从其中拉流即可,协议可能是 RTMP、HLS、HTTP-FLV、RTSP等。

graph RL;
streamServer(流媒体服务)
transform(转码程序) --"拉取"--> streamServer
录播(视频文件播放)

转码程序直接按时间读取视频文件即可。

graph RL;
transform(转码程序) --"读取文件"--> videoFile(视频文件)

直播转码

直播转码程序的意义在于实现一些高级功能,在对直播流进行转码时,可对直播流添加水印、高清/流畅转换、码率限制、直播录像、直播倒计时、自动补帧、导播/轮播、画中画等。

简单的转码工作可交给流媒体服务软件完成,如SRS。

用户拉流

直播观看的协议一般是 HTTP-FLV、HLS 等;如果对延迟要求高,一般使用 RTMP、WEBRTC 等。

直播CDN:

为了减轻服务器压力,可以将转码后的视频流推到第三方直播CDN服务,用户从直播 CDN 服务拉流观看,让直播 CDN 承担多用户拉流的压力,减轻自己服务器带宽压力。

graph LR;
transform(转码程序) --"推流"--> cdn(直播CDN)
user(用户) --"拉流"--> cdn

一般使用 RTMP 协议推流到直播CDN,直播 CDN 提供的观看拉流协议一般是 HTTP-FLV、RTMP、HLS等。

流媒体协议

协议 优势 使用场景 延迟 地址 流媒体软件
RTMP 延迟低,有一定弱网抵抗能力,数据块小重发成本低 直播系统内推流 1-3s rtmp:// SRS、Nginx(rtsp插件)
HTTP-FLV 适配多个播放场景,加入插件即可播放,网页引入 flv.js 即可播放 客户端拉流观看 1-3s http:// SRS、Nginx(HTTP-FLV插件)
HLS 适配多个播放场景,加入插件即可播放,网页引入 hls的js插件即可。不删除视频碎片文件即可生成直播录像。直播转点播、录播更简单(修改m3u8索引文件即可) 拉流观看 5-30s http://0.0.0.0/live.m3u8 不需要,能提供http服务即可
WEBRTC 延迟低 交互性高的直播 <1s webrtc:// SRS
RTSP 支持TCP/UDP切换,支持推流/拉流,支持点播/直播 监控摄像头等硬件设备 <1s rtsp:// simple-rtsp-server

SRS

SRS (Simple Realtime Server) | SRS: http://ossrs.net/lts/zh-cn/

SRS(Simple Realtime Server)是一个简单高效的实时视频服务器,支持RTMP、WebRTC、HLS、HTTP-FLV、SRT等多种实时流媒体协议。

RTMP

RTMP、HTTP-FLV 都是基于 FLV 封装格式。RTMP 一般用于直播源推流,直播系统内直播流数据传递;HTTP-FLV 一般用于客户端直播流观看。

RTMP 协议即可用于推流,也可以用于拉流,RTMP 推流拉流的地址一致,地址以 rtmp:// 开头。

常见 RTMP 流媒体服务软件:SRS、Nginx(rtmp插件)。

由于浏览器废弃了 flash 播放器,且高并发下可能存在稳定性问题,所以 RTMP 一般只用作直播源推流、推流到直播 CDN 等场景。

RTMP 协议基于 TCP 长链接,在封装音视频时会强制对数据切片,限制每个数据包大小,强制切片一定程度保证了实时性,具有一定弱网抵抗能力,因为数据块小传输失败时重发成本低。但数据切片与合并数据块会增加 CPU 压力。

HTTP-FLV

HTTP-FLV 协议基于 http 协议,与 RTMP 工作原理相似(可以看做 RTMP 的 HTTP 版本),延迟 1-3 秒(略高于RTMP),HTTP-FlV 一般只用作客户端拉流观看。

主流的直播推流拉流协议

Nginx 的 HTTP-FLV 插件包含了 RTMP 功能,所以一般的 HTTP-FLV 流媒体服务会采用 RTMP 推流,HTTP-FLV 拉流。

HLS

HLS 协议是苹果公司发布的标准,在苹果设备上默认支持,与HLS 协议类似的还有 MPEG-DASH 协议(国际标准协议)。只用于拉流观看,可用于直播、点播观看。原理是通过http 协议下载静态文件,其中包含一个索引文件(.m3u8 文件)和多个只有几秒的视频文件(.ts 文件),索引文件中记录了相关视频文件的路径。客户端先获取索引文件,然后从索引文件中获取视频碎片文件的下载路径,然后下载视频碎片文件进行播放。

HLS 的视频碎片文件是直接写入磁盘的,所以不需要特殊的流媒体软件。

点播场景下,索引文件中会记录所有视频碎片文件地址、时长。由于 HLS相关文件是无状态的静态文件,且每个文件大小是有限的,所以负载均衡、CDN 加速的效果更加明显。HLS 的点播视频会比 mp4、flv 视频更快地播放出来,且在加载中跳转视频会更加顺滑。

直播场景下,转码文件直接生成 HLS 相关文件到磁盘,客户端通过 http 服务下载静态文件即可。

graph RL;
transform(转码软件) --"生成静态文件"--> hlsFile(HLS相关文件)
httpServer(HTTP服务) --"磁盘读取"--> hlsFile
user(客户端) --"http://xxx.m3u8"--> httpServer

直播场景下,也可以让转码软件将直播流以 RTMP 推送到安装了RTMP 插件的 Nginx 服务,由 Nginx 生成 HLS 相关文件,用户直接访问 Nginx 提供的 http 服务。在后续业务中可直接将 Nginx 替换成直播CDN ,无需修改架构。

graph RL;
transform(转码软件) --RTMP推流--> nginx(Nginx+Rtmp插件)
user(客户端) --"http://xxx.m3u8"--> nginx
nginx -."替换".-> cdn(直播CDN)

直播场景下的索引文件会随时间改变,因为视频碎片文件在改变,且索引文件中记录的视频碎片文件数量是有上限的,当达到上限时,默认会删除旧的视频碎片文件并更新索引文件,因此客户端需要不断重新获取索引文件,从而获得新的视频文件地址。

m3u8 索引文件支持二级索引,可以将不同清晰度(高清、标清、流畅等)的地址整合到一个索引文件中,也可以支持音视频分离,播放器可以根据当前带宽自动切换不同的观看地址。

优化建议:由于 HLS 协议需要将视频碎片文件写入磁盘,直播场景下会有大量的写磁盘操作,将会严重损耗磁盘使用寿命。建议将一段内存空间作为 HLS 文件的写入位置,将文件写入内存而非磁盘。这种方式在系统重启时会丢失数据,可做一些定时备份的措施。

1
mount -t tmpfs -o size=10g tmpfs /data

如以上 linux 命令,可将视频文件写入 /data 目录。

WEBRTC

WebRTC 是一种点对点的视频/语音通话协议,是基于 UDP 的,延迟低(1秒内),适合交互性较高的场景,如直播带货、视频会议。

WebRTC 支持推流和拉流,地址一般以 webrtc// 开头,推流与拉流地址一般也是相同的。

WebRTC 设计为点对点的通信协议,在直播场景下,需要搭建 WebRTC 服务为用户提供连接服务,可用的流媒体服务软件:SRS。

RTSP

一般用于摄像头等硬件设备的实时视频观看、推流。

RTSP支持推流、拉流,可切换 TCP/UDP,支持点播、直播。

一般不用于直播,现代浏览器不支持,在 web 领域一般不使用 RTSP。

参考资料