RTMP在直播领域取得了不错的应用,某项目需要针对RTMP流进行多路并发录制,在分析了多种解决方案的弊端后,我们实现了一种轻量级、低耦合、高可靠性的RTMP并发录制方案。
背景
现有录制方案包括:
A、在RTMP流媒体服务器上实现录制。比如第三方的阿里云、腾讯云等均提供录制服务。比如使用SRS\Nginx-rtmp作为媒体服务器时,在其基础上增加服务器端录制。
B、使用ffmpeg+脚本方式搭建录制服务。
综合权衡,方案A与媒体服务器耦合度较高,在某些场景下无法实施。方案B是一个快速实现相关功能到不错选择,但未经改造的ffmpeg在掉线自动重连等异常情况的检测恢复方面存在较多问题,对于可靠性要求较高的工程场合不太适合,且因为ffmpeg本身比较庞大,对其进行自定义改造开发工作量不小。
最终,我们选择C方案:开发一种独立于媒体服务器的RTMP高并发收录系统,系统具备高可靠、低耦合、精简可扩展的特征。
1、系统对外采用极少数几个WEB接口:收录任务查询接口、收录任务状态反馈接口、录制文件入库接口,耦合性低可很快集成到用户现有系统之中。
2、支持RTMP自动重连、支持实时监控收录程序工作状态和媒体流状态,对异常情况自行恢复。
3、采用多进程架构,不同的收录任务使用相互独立的子进程,实现高可靠性。
4、实时录制时采用TS容器作为载体,在掉电、断网等异常情况下始终确保文件无损坏。
5、支持将TS文件自动转换为播放器兼容性更好的MP4文件。
6、支持按指定的时长间隔或文件大小生成录制片段。
7、支持缩略图生成。
8、支持主备,支持集群化部署。
9、支持H264、AAC组合的标准RTMP流,支持H265扩展。
设计
系统架构如下图所示:
系统由WEB服务、RtmpCapServer收录服务端、RtmpCapClient收录客户端、TS转MP4服务四大部分组成。
RtmpCapServer收录服务端定时调用WEB接口获取当前时刻需要启动的收录任务,获取到任务后将在本机启动对应的RtmpCapClient收录客户端子进程,子进程启动后建立与RtmpCapServer服务端之间的TCP长连接用于双方之间的信令交互。其后子进程开始RTMP的流录制。
RtmpCapClient收录客户端可通过TCP长连接向RtmpCapServer收录服务端上报任务状态(启动录制成功、录制失败、录制完成等)和媒体流状态(分辨率、码率等信息),后者通过WEB接口反馈上层应用。
一个收录任务对应一个唯一的收录子进程,一个RTMP地址可以对应多个收录任务(最常见的场景,为同一路RTMP流创建两个收录任务分别用于主备)。
RTMP流录制时按指定的时间间隔生成一个个独立的TS文件,存放于用户指定的目录之下,举例如下:./2020-02-20/10086/2020-02-20-16-30-00.ts,其中10086是对应WEB上的收录任务ID,2020-02-20-16-30-00对应该片段的起始录制时间。
选择使用TS作为录制格式是基于TS的随时可中断特性,面对各类异常情况(收录服务进程异常退出、服务器掉电、断网等),TS文件始终能保证录制文件的可播性。相比而言,MP4文件因为需要在最终时刻生成重要的MOOV头部而容易产生文件损坏。
TS文件有存储的优势,MP4文件则有播放器兼容性的优势,目前几乎所有WEB播放器均支持MP4容器。为此我们启动了一个单独的TS转MP4服务,该服务会查询TS路径下待转换的文件(已转换的或者正在录制中的片段不会参与转换,通过标志文件可以轻松实现这样的目标),并调用ffmpeg实现文件容器的转换、缩略图生成、文件时长的获取等。MP4的转换完成后,该服务将调用用户配置的WEB接口实现文件的上报入库。这类离线式文件处理正是ffmpeg到优势之处,避免了繁琐的二次开发。
我们可以在多台服务器上部署多套独立的本系统(RtmpCapServer+RtmpCapClient+MP4转换服务),它们共用同一套WEB服务,从而实现集群化处理。(通过在WEB接口处附带服务器ID号来便于WEB服务区分处理,比如WEB后台可据此进行任务调度等)
开发语言
RtmpCapServer收录服务端、RtmpCapClient收录客户端使用C++(非C++11)开发,使用HTTP-JSON格式与WEB交互。其代码精简占用资源小,非常适合嵌入式平台。
TS转MP4服务使用python开发,使用HTTP-JSON格式与WEB交互。
WEB服务原则上不属于本系统,我们提供的演示DEMO中使用PHP+MySql实现,用户只需要按我们WEB接口要求实现相关WEB接口功能即可。
支持平台
得益于跨平台的中间件,系统同时支持Linux和Windows
系统对外WEB接口
相关演示DEMO下载地址:
https://github.com/waterfoxfox/RtmpCaptureSer