广电行业做视频服务器的同学,最近一年听到最多的一个词应该就是“安可”。落到实际工作上,就是原来跑得很顺的转码服务器、收录服务器、流媒体分发服务器,都开始要考虑迁移到一套约束完全不同的国产化软硬件环境里。刚开始你可能觉得“不就是Linux换Linux、CPU换CPU”,真上手以后才知道,坑全在细节里:指令集不兼容、软件包没有、编译过不去、跑起来性能差一大截。而开源模块几乎成了唯一的出路,因为你不可能从零自研整套信号处理栈。
这篇文章我把自己在广电视频服务器适配安可系统的思路、模块选型和部署过程完整写出来。既面向负责系统选型的,也面向一线动手编译部署的。内容里不会出现那种“这个模块很火所以你也用”的废话,只讲我实际验证过、压过、跑过线上业务的模块,以及每个模块在安可环境下会踩的坑。如果你正准备把视频服务器往安可环境迁移,这篇文章可以直接拿来当参考清单。
1. 先搞清楚:安可环境下的广电视频服务器到底差在哪
1.1 视频服务器的典型职责
很多人一提广电视频服务器,就以为是“一台跑流媒体的Linux机器”,其实广电体系里的视频服务器身兼数职,至少要覆盖这几类核心能力:
- 信号采集与收录:从卫星、有线网、SDI等来源接入音视频信号,按频道、按时间段录制,生成素材文件。
- 转码与压缩:把采集到的高码率源信号转成适合播出、存储或分发的格式,常见编码是H.264/H.265,音频是AAC或MPEG Audio。
- 封装与切片:把转码后的流封装成MP4、TS、FLV等格式,再按HLS/DASH协议切成小分片,方便CDN和终端播放器拉流。
- 协议分发:支撑RTMP、HTTP-FLV、HLS、DASH甚至WebRTC等多种播出协议,对接不同的终端和播出平台。
- 播控与调度:在内部做节目单管理、素材调度、多路并发控制。
一句话概括:视频服务器是一条“信号进、内容出”的流水线。迁移到安可环境,不是把某一个软件装进去就完事,而是整条流水线里的每个齿轮都要能转起来。
1.2 安可给技术层面带来的三个真实差异
我在实际项目里体会到,安可系统对视频服务器研发的影响,技术层面可以归纳成三点:
第一,CPU指令集变了。老系统里很多优化是围绕x86指令集做的,比如使用AVX、SSE的汇编优化库。换到新的国产化CPU平台上,支持的可能是ARM指令集或其它架构,过去那种“直接拿二进制就能跑”的做法基本失效。编译时汇编器不识别、运行时指令不支持,这两类问题几乎天天遇到。
第二,基础软件生态变了。安可系统通常采用特定的操作系统底座,很多常见的apt/yum软件源里根本没有现成的包。FFmpeg、Nginx、OpenSSL这些软件想用,基本都得走源码编译。依赖关系一环套一环,有时候一个库编译失败,后面全卡住。
第三,硬件加速链路变了。老平台通常依赖Intel Quick Sync或者NVIDIA显卡做硬件转码。国产化平台上的硬件编解码能力也存在,但对应的驱动、接口和用户态库跟老平台不完全一致。软件层面的转码方案必须提上日程,并且要针对新平台的NEON/SIMD指令做适配,否则一个4K频点的转码任务就把CPU吃满。
理解了这三个差异,你才知道选型时该看什么。不是谁的Star多就选谁,而是谁能在这个新环境里顺利编译、稳定运行、性能达标,谁才是能用的模块。
2. 选型逻辑:不要上来挑模块,先把链路画出来
2.1 一条完整的视频处理链路
我第一次迁移时犯过一个错误:上来就在GitHub上翻开源项目,看到功能看起来齐全的就准备用。结果方案东拼西凑,模块之间协议对不上、数据格式不兼容,返工成本非常高。
正确做法是先画链路。一条典型的广电视频服务链路,按顺序分为四段:
- 接入段:拉流、推流、SDI采集、文件导入,统一转成内部原始流格式。
- 处理段:转码、缩放、添加台标、字幕混入、录制、抽帧。
- 封装切片段:按目标协议重封装,生成分片、索引文件,比如HLS的m3u8+ts,DASH的mpd+mp4。
- 分发输出段:对外提供RTMP、HTTP-FLV、HLS、WebRTC访问,做鉴权、限制并发、内容缓存。
画完这条链路以后,每个“节点”缺什么模块就很清楚了。比如接入段需要支持RTSP/RTMP拉流协议,处理段需要FFmpeg和x264/x265库,切片段可以是FFmpeg内部能力,分发段需要SRS或ZLMediaKit这类服务。
2.2 评估开源模块的三个硬指标
链路画完,再去给每个节点找模块,评估标准只有三个:
- 有没有人持续维护:要看最近一年有没有提交,社区是否活跃。视频协议更新快,尤其WebRTC、GB28181这些方向,一个停更多年的模块,在安可环境下出了问题没人帮你解决。
- 能不能在目标架构上编译通过:这点最实际。有的模块对x86的汇编优化做了强依赖,在ARM平台上编译时会挂。如果模块官方已经出了aarch64的release包,兼容性风险会小很多。
- 依赖是否可控:有的开源模块看起来功能强大,但一拉依赖就是几十个库,有些库还要求特定版本,这种模块在安可环境下很可能变成时间黑洞。优先选那种依赖清单短、编译方式清晰的模块。
我认识的同行里,有人因为贪图功能丰富选了一款带过多依赖的流媒体平台,最后光解决编译链就花了两周。这个教训挺深刻:功能可以慢慢补,编译不过去就是零。
3. 值得收藏的开源模块名单与适配细节
3.1 转码引擎:FFmpeg 及配套编解码库
点名模块第一名,没有任何争议,就是FFmpeg。它在视频处理领域的地位相当于文本处理界的标准工具:解封装、转封装、解码、编码、滤波、切片、推流,样样都能干。安可环境下,FFmpeg承担的工作通常有三个:信号录制、转码压缩、HLS切片。
FFmpeg真正让人放心的一点是它对CPU架构的适应能力。它同时支持x86、ARM、MIPS等多种架构,而且在ARM平台上有针对NEON指令集的优化代码。这意味着在主流国产化CPU平台上,只要编译时把相关选项打开,FFmpeg通常能正常工作。但在安可环境下,FFmpeg不是“拿个二进制就能落地”的,必须走一次源码编译,并且要特别留意编解码库的取舍。
我建议的最小编译方案是:FFmpeg主体 + x264 + x265 + fdk-aac。其中x264负责H.264编码,x265负责H.265编码,fdk-aac负责AAC音频编码。这三个库在广电业务里覆盖了绝大多数转码需求。
编译FFmpeg的典型配置如下:
./configure --prefix=/usr/local/ffmpeg \ --enable-gpl \ --enable-version3 \ --enable-libx264 \ --enable-libx265 \ --enable-libfdk-aac \ --enable-nonfree \ --enable-pthreads \ --enable-avfilter编译顺序有讲究:先编译x264、x265、fdk-aac,再编译FFmpeg本身,否则configure阶段找不到对应库。
在ARM架构平台编译时,我会额外留一个心眼:如果目标CPU的指令集支持程度不明确,先不要把NEON优化选项强制打开,用默认的自动检测。等编译通过、功能验证完,再单独做一轮优化测试。
提示:FFmpeg的configure默认会自动检测CPU特性。遇到“asm”相关的编译错误时,先排查是不是汇编器版本太老,再考虑关闭特定指令集优化,不要一上来就全关,那样性能损耗很大。
3.2 流媒体服务:SRS、ZLMediaKit、Nginx-RTMP
流媒体分发是广电视频服务器的核心出口。目前开源社区里真正经过大规模生产环境验证的,主要就是SRS和ZLMediaKit,另外Nginx-RTMP模块在老项目中出镜率也很高。我把它们放在一起对比。
SRS是音频视频直播服务器,定位非常聚焦:直播分发。它支持RTMP、HTTP-FLV、HLS、WebRTC,配置简单,性能高。我在实际测试中,用SRS转发1080p直播流,单机支撑几千路播放没什么压力。而且SRS本身是C++写的,依赖少,编译比FFmpeg省事很多,对国产化平台比较友好。
SRS编译过程大概是:
git clone -b v4.0 https://github.com/ossrs/srs.git cd srs/trunk ./configure --full make -j$(nproc)编译完生成objs/srs,启动就能用。
ZLMediaKit是后起之秀,最大的特点是协议覆盖面广,对国标GB28181、RTSP、RTMP、HLS、WebRTC都有支持。广电场景里经常要接入GB28181的摄像头或编码器,ZLMediaKit提供的国标接入能力几乎成了刚需。它的架构更模块化,核心库和业务层分离,适合做二次开发。缺点是配置项比SRS多,上手门槛略高。
Nginx-RTMP模块的优势是老团队熟悉,毕竟Nginx在广电系统里用得极广。但这个模块本身更新不太活跃,而且功能偏基础,适合“老项目继续用Nginx做透传”的场景。如果是新项目,我不太推荐从它起步,因为RTMP之外的能力它覆盖很弱,HLS/WebRTC还得另寻出路。
三款模块的取舍,我用下面这张表说明:
| 模块 | 核心优势 | 适用场景 | 安可适配注意 |
|---|---|---|---|
| SRS | 直播分发性能强,配置简单 | 大规模RTMP/HLS直播分发 | 编译依赖少,注意openssl版本 |
| ZLMediaKit | 多协议覆盖,国标接入强 | 需要GB28181/多协议融合的业务 | 依赖较多,编译参数需仔细配置 |
| Nginx-RTMP | 与Nginx生态天然融合 | 老旧系统平滑升级 | 模块更新慢,新协议支持弱 |
3.3 播放与协议适配:hls.js、video.js、flv.js
服务端准备好了,终端播放侧也有对应的开源模块。广电业务里有大量Web播放页面,播放器不能只认一种协议。老系统里播放器多是Flash方案,现在早就淘汰了,必须走HTML5技术栈。
前端播放常用的开源模块包括:
- hls.js:由视频社区维护的HLS播放器库,纯JavaScript实现,兼容性好,在安可后的Web页面上能直接跑,不需要额外插件。
- video.js:老牌播放器框架,支持插件机制,适合需要高度定制播放界面的场景。配合hls.js或flv.js插件使用。
- flv.js:面向HTTP-FLV协议的播放库,低延迟直播场景常用。注意它依赖Media Source Extensions,浏览器必须支持,这点需要在实际终端环境里做测试。
选播放器模块时,我建议优先hls.js。原因很简单:广电业务的播出质量要求高,HLS切片方案容忍网络波动能力强,而且hls.js在国产浏览器、基于Chromium的终端上的兼容性已经相当成熟。如果你的业务要求低延迟,再考虑HTTP-FLV或WebRTC路线。
3.4 周边配套:调度、监控与接入模块
视频服务器不能只有视频处理本身,周边的接入、调度、监控同样缺不了。
接入侧:如果要从摄像头或GB28181设备拉流,可以用ZLMediaKit的国标模块,也可以配合开源的SIP协议栈,把设备注册、信令交互、媒体流拉取串起来。
调度侧:开源领域没有专门针对广电视频服务器的调度模块,但可以拿通用消息队列和缓存来搭。比如用Redis保存任务元数据,用消息队列分发转码任务,再用一套简单的HTTP API把任务状态串起来。这个组合不复杂,胜在稳定。
监控侧:Prometheus + node_exporter是通用方案,主要用于采集服务器CPU、内存、磁盘、网络指标。更细粒度的业务监控,比如当前并发流数、转码队列长度、HLS切片生成延迟,需要自己在FFmpeg和SRS调用链里埋指标。我建议在SRS上开启官方支持的Prometheus监控接口,FFmpeg则靠脚本定期探测转码进程的状态和输出文件的时间戳。
4. 实操记录:在国产化服务器上从编译到出流
4.1 环境准备与工具链
我在项目的试验环境是一台某国产CPU架构的服务器,搭配某国产Linux发行版,内存32GB,CPU核数16。一台典型的安可视频服务器配置大抵如此。
拿到机器第一步,先确认基础信息:
uname -m cat /etc/os-release gcc --version如果gcc都没有,先装编译工具链。不同发行版包管理器不同,但大逻辑一致:
yum install -y git gcc gcc-c++ make cmake autoconf automake libtool pkgconfig这里有个经验:编译FFmpeg之前,一定要先确认pkgconfig和make可用。很多编译失败其实不是代码问题,而是环境缺了基础工具。
4.2 编译依赖库与FFmpeg
我习惯的顺序是先编x264,再编x265,接着fdk-aac,最后才是FFmpeg。每个库的configure参数不需要太多,按默认参数来就好。比如x264:
./configure --enable-shared --enable-pic --prefix=/usr/local make -j8 make install ldconfig每个库装完后,用ls /usr/local/lib确认生成文件,同时要确认pkg-config能找到它:
pkg-config --modversion x264FFmpeg configure时它会自动检测这些库。如果检测不到,最常见的两个原因:一是库装到了非默认路径,需要设置PKG_CONFIG_PATH;二是缺少开发头文件,编译库时没带--enable-shared导致头文件没安装。
FFmpeg编译时间取决于机器性能。16核机器全编一次,大概20到40分钟。第一次编译最好执行:
make -j8不要盲目用-j16,如果内存不够32GB,过大的并行度会导致内存吃满、进程被杀。编译完验证一下转码能力:
ffmpeg -i test_1080p.mp4 -c:v libx264 -preset veryfast -c:a aac out.mp4只要这条命令能顺利走完,说明FFmpeg核心链路打通了。
4.3 配置SRS跑通直播流
FFmpeg编好后,我接着部署SRS做分发测试。SRS配置非常简洁,一个基本的直播分发配置如下:
listen 1935; max_connections 1000; daemon on; srs_log_tank console; vhost __defaultVhost__ { hls { enabled on; hls_path /data/hls; hls_fragment 2; hls_window 10; } }启动SRS:
./objs/srs -c conf/rtmp_hls.conf然后用FFmpeg推流:
ffmpeg -re -i test_1080p.mp4 -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -f flv rtmp://127.0.0.1:1935/live/test这里-re参数很重要,它让FFmpeg按视频原速率推流,防止瞬间发完数据包导致服务器端缓冲异常。
拉流验证用VLC或者ffplay都行:
ffplay rtmp://127.0.0.1:1935/live/test如果拉流稳定、画面不卡,SRS这条链路就算通了。再打开HLS配置后,可以直接播放http://服务器IP:8080/live/test.m3u8。
4.4 用FFmpeg切片HLS并验证
直播之外,广电业务大量涉及点播与回看,HLS切片是常用能力。我常用下面的命令把素材切成HLS流:
ffmpeg -i input.mp4 -c:v copy -c:a copy \ -f hls -hls_time 4 -hls_list_size 0 \ -hls_segment_filename "/data/hls/seg_%03d.ts" \ /data/hls/index.m3u8-hls_time 4表示每4秒一切片,-hls_list_size 0表示m3u8索引里保留所有切片。对回看业务,需要保留全部切片;对直播业务,反而要设置-hls_list_size 5之类的小值,让播放器只看到最近几个切片。
验证方法很简单:把m3u8和ts放进Web目录,用hls.js在浏览器里播放。我一般会再用脚本检查m3u8里每个ts切片文件是否存在,以及切片时长是否均匀,防止播出时出现卡顿。
5. 常见问题与排障技巧实录
5.1 编译期最容易翻车的三个点
安可环境下编译开源模块,翻车率最高的三个点,我总结如下。
第一,找不到nasm/yasm汇编器。编译x264或FFmpeg时,configure阶段报错“require yasm”。原因是x86架构下需要汇编器处理优化代码。解决方法是先安装nasm,或者对FFmpeg加编译参数禁用x86汇编优化。但在性能敏感场景,我推荐前者,因为x264在x86下没有汇编优化,性能差距能到两倍以上。ARM架构平台不受这个影响,但要注意ARM汇编工具链的版本。
第二,系统库版本过低。不少国产Linux发行版内置的OpenSSL、zlib版本都比较保守,某些较新版本的流媒体模块会要求更高版本。这时候我不建议直接升级系统库,因为系统库被很多基础组件依赖,升级容易引入连锁问题。稳妥做法是编译一个独立版本,放到自定义路径,用环境变量或软链接指过去。
第三,编译过程内存爆掉。国产化服务器内存配置差异很大,有的机器只有16GB。FFmpeg开启多路并行编译时,内存轻松吃满。我用16核机器编译时,会把并行数压到8,再配合--disable-doc这类减小编译体积的选项。
5.2 运行期的资源与性能问题
编译过了,运行期依然会有坑。
文件句柄数不够。SRS这类流媒体服务在高并发下要大量建立socket连接。默认的ulimit -n可能只有1024,几百路并发时服务直接拒连。必须调大:
ulimit -n 65535同时要在系统配置里改/etc/security/limits.conf,否则重启失效。
CPU占用过高。转码本身吃CPU是正常的,但如果纯转码时CPU占用异常高,先检查FFmpeg是否用了硬件加速或SIMD优化。查编译日志,看有没有输出NEON enabled相关信息。我遇到过有的编译参数把CPU特性检测禁了,导致FFmpeg全程走C语言路径,性能惨不忍睹。
内存泄漏。长转码任务跑几天几夜时,RSS内存持续上涨,基本就是有内存泄漏。优先把FFmpeg升级到较新版本,很多历史泄漏都是老版本bug。如果用的是SRS,开启--gc内存回收机制,并且定期检查日志中的告警信息。
5.3 业务侧的流异常
业务侧最常见的异常是“推流正常、播放黑屏”或者“画面花屏”。排查思路要按协议分层走:
- 先确认拉流地址参数正确,再确认码流本身没有异常。
- 用ffprobe检查推流上去的码流是不是GOP结构正常,有关键帧缺失的话,播放器起播就会黑屏。
- 检查音视频时间戳是否同步,可以用FFmpeg输出日志观察
Non-monotonic DTS这类提示。 - 如果是HLS播放卡顿,优先查切片时长是否均匀,以及服务器到终端的网络抖动。
安可环境下多了一类特殊问题:不同终端播放器的协议兼容性不一致。有的终端只支持HLS,有的只支持HTTP-FLV。我的做法是在分发层同时开放多协议,让播放器自动选路,这正好能体现ZLMediaKit这类多协议模块的价值。
6. 组合推荐:两套方案供参考
基于前面的实操,我给两类典型场景各配了一套方案。
方案A:轻量直播分发场景
适用情况:单路或多路同步直播、点播回放,终端规模中等,团队对Nginx体系熟悉。
- 处理与切片:FFmpeg + libx264/libx265
- 分发服务:SRS(开启HLS + HTTP-FLV)
- 播放器:hls.js / flv.js
- 监控:Prometheus + node_exporter
这套组合依赖少、部署快,我实测在两台服务器上跑几十路直播完全没有问题,适合快速交付。
方案B:综合全业务场景
适用情况:需要接入GB28181设备、输出WebRTC低延迟流、还要承载多协议分发,团队有二次开发能力。
- 信令接入:ZLMediaKit内置GB28181信令模块
- 处理与切片:FFmpeg + x264 + x265
- 分发服务:ZLMediaKit(RTSP/RTMP/HLS/WebRTC全协议)
- 播放器:video.js + hls.js + WebRTC插件
- 调度与监控:Redis + 消息队列 + Prometheus + Grafana
方案B的复杂度高一些,但胜在统一协议出口。广电业务如果未来要扩展到低延迟互动场景,方案B不用推翻重来。
7. 最后说几句大实话
做安可适配这一年多,我最大的体会是:开源模块本身都不是什么秘密武器,真正的难点在于组合后的工程化能力。FFmpeg谁都会装,但能不能针对特定CPU架构调好编译参数,能不能让转码和分发两个环节之间的协议严丝合缝,这才是区分“能跑”和“能上线”的分水岭。
我的建议是,拿到任何一套方案,先在目标机器上把最小闭环跑通一遍:采集或推流进来,转码,切片,播放器拉流,全部串起来。不要在还没有最小闭环之前就去优化并发、优化画质。基础链路通了,后面的事情都是渐进式的调优。
另外,所有开源模块拉下来以后,第一时间锁定版本,不要追求“最新”。安可环境里用的软件栈组合很讲究匹配关系,一个模块升级可能连带要求另一个模块升到指定版本,然后整个编译链就崩了。我自己吃过这个亏,之后都老老实实在README里写清楚版本矩阵。
最后分享一个小技巧:把整个编译过程写成脚本保存下来。不只是对着终端敲命令,而是每一步都做成可复现的脚本。因为安可环境下你经常会遇到“换一台机器就要全部重来”的情况,有脚本在手,部署时间能从半天压缩到半小时。这也是我觉得整个项目里最值得投入的一笔时间投资。