ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

JRS免费直播平台:从0到1自建低延迟直播系统全指南

JRS免费直播平台:从0到1自建低延迟直播系统全指南 很多做内容的人第一次听到“JRS免费直播平台”这个项目代号第一反应是“又一个直播软件”。实际上它并不是某个现成的App而是一套低成本、可自行部署的直播系统方案的项目代号。核心思路很直接用开源推流工具加轻量转发服务把采集、编码、分发、播放四个环节串起来在没有商业直播平台“入场费”和“抽成”的前提下跑通一条完整直播链路。这篇文章我会把这条链路的每一个环节拆开从选型到落地从参数配置到踩坑排查完整过一遍给想做个人直播、在线教学、小规模分享会的人一个可以直接抄作业的参考。1. 先看本质一套“免费”直播系统的链路到底由什么组成1.1 核心需求拆解你要的其实不是“免费”是“可控”很多人一听到免费直播平台脑子里出现的是“不花钱”。但我在实际做这套方案的时候发现真正驱动大家去自建系统的诉求远远不只是省钱。更核心的两个词是“可控”和“可定制”。商业直播平台几十块钱一个月的基础套餐看起来不贵但问题出在细节观众进来要注册、直播间有平台Logo和水印、直播内容审核规则不透明、数据接口封闭、回放功能要另外加钱。对于一场内部培训、一场产品发布演练、或者一次小圈子技术分享这些限制非常致命。你自己搭一套系统推流地址是你自己的播放器是你自己的观众进来不用登录视频画质和延迟自己调数据自己统计。这不只是钱的问题是整个直播体验和品牌展示的自主权。另外一个很现实的需求是“流量隔离”。自建方案可以只服务特定的用户群体比如公司内部员工、付费社群成员、线下合作机构的学员做一个独立的观看入口。这个场景下通用直播平台反而是累赘。所以这套系统的目标不是“替代所有直播平台”而是“在特定场景下提供比通用平台更贴身的直播服务”。理解这个定位后面选型才不会走偏。1.2 一条直播链路的四个不可省略环节任何直播系统无论商业还是自建本质上都是四个环节的串联直播画面从摄像头、采集卡或屏幕捕获而来这是信号的源头。然后是编码环节把原始视频信号压缩成适合网络传输的H.264或H.265码流。编码后的数据需要依赖一个分发服务即推流和转发的服务器端把一路输入复制成多路输出推给各个观看端。最后是播放环节观众通过浏览器、小程序或播放器App解码并实时呈现画面。只要把这四个环节理解透所谓的“自建直播平台”其实没那么神秘。你只需要在每个环节选一个工具把它们拼起来。真正决定项目难度的是各个环节之间是否兼容、协议是否统一、参数是否匹配。我见过太多人一上来就折腾搭建服务器最后发现瓶颈根本不在服务器而是在推流端的编码参数没调对。所以我的建议是先摸清链路再动手。2. 工具选型四环节分别选什么为什么这么选2.1 推流端OBS Studio依然是最稳的基石推流端的任务是把画面采集并编码后推给服务器。这个环节我非常推荐直接用OBS Studio免费开源Windows、macOS、Linux全平台支持硬件加速编码和软件编码都做得很成熟。为什么不用它自带的“简易推流”模式我见过很多小白用户直接填服务器地址就开推结果画面模糊、音画不同步然后跑来问我怎么回事。问题几乎都出在默认参数上。OBS的安装很简单真正影响直播质量的是推流前你必须手动确认的四个参数分辨率、帧率、视频码率、音频码率。我们在后面的实操部分会逐项讲清楚怎么配。补充一点如果你是纯手机直播场景可以四环节里的推流端直接用带RTMP推流功能的App比如摄像头类的专业推流应用。但在稳定性上电脑端OBS依然是首选。手机端更适合户外突发场景电脑端适合正式、长时间的内容输出。多数自建项目我建议优先考虑电脑推流。2.2 分发端SRS比nginx-rtmp更适合新手和长期维护分发端是整个系统的中枢接收推流端的RTMP流再转成不同协议分发给观看端。最常用的开源方案是nginx-rtmp-module和SRSSimple Realtime Server。我的建议很明确优先选SRS。原因不复杂nginx-rtmp-module已经很多年没有大版本维护了功能也相对单一主要就是收RTMP推流、再吐RTMP或者HLS切片。而SRS对现代播放需求的支持更完整可以同时对外提供RTMP、HTTP-FLV、HLS、WebRTC等多种协议配置也更简单还有清晰的中文文档和活跃社区。SRS部署起来也并不重。用官方Docker镜像方式一条命令就能起一个服务实例docker run -d -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5这里容器里的1935端口是RTMP入口1985是SRS的HTTP API端口8080用于对外提供HTTP-FLV和HLS文件流。命令跑起来之后SRS就会在默认配置下运行。生产环境你需要改改配置这个我们在实操部分细说。2.3 播放端按延迟需求决定用HTTP-FLV还是HLS播放端是观众直接接触的环节也是坑最多的地方。最底层的逻辑是延迟目标和分发协议强相关。想低延迟就得在播放端用能实时拉流的协议想要极致的兼容性就得接受几秒钟以上的延迟。三种主流协议的取舍可以参考这个对比协议典型延迟浏览器支持适用场景RTMP1~3秒需插件或原生播放器已非主流拉流到播放器端非首选HTTP-FLV1~3秒需flv.js等JS库移动端H5可用延迟敏感场景推荐HLS5~15秒H5原生video标签基本都支持兼容优先、回放场景我在实际项目里的默认组合是播放端优先用HTTP-FLV方案配套flv.js收流延迟能压到三秒内画质损失也小。如果某些播放端浏览器兼容性实在解决不了或要做回放就直接切HLS。后者的延迟虽然高一些但胜在开箱即用几乎不用写额外代码。2.4 为什么我不建议一开始就上“高可用”架构很多刚接触自建直播平台的人上来就问“要不要搞负载均衡、多节点分发”。我得泼一盆冷水绝大多数场景根本不需要。如果你的观众规模在几百人到几千人这个级别一台带宽够用的SRS服务器已经能撑住。你真正的瓶颈往往不是软件而是上行带宽。比如一台服务器按H.264 1080P直播用4.5Mbps码率算一小时约2GB流量。单台云服务器按每月500GB流量套餐算足够支撑两百多个小时的直播观看这对绝大多数个人创作者和中小企业来说绰绰有余。真正需要上多节点、做CDN、做边缘转发的是那种同时几千人在线、跨地域大规模实时互动的场景。起步阶段就上这种架构只会把简单问题复杂化。能用单机解决的问题先不要用集群来解决。3. 实操部分从0到1跑通一条直播链路的完整过程3.1 推流端编码参数的计算逻辑在OBS里推流参数绝对不是拍脑袋填的它由你的“源头画质”和“上传带宽”共同决定。我建议的基准配置是视频分辨率按你内容源的原始分辨率来常见的1080P居多帧率设定在30fps视频码率区间则为4500~6000Kbps。如果你上传带宽不够比如只有8Mbps上行那么码率建议降到3000Kbps以下别硬顶1080P改720P2500~3500Kbps更现实。音频这块讲话类内容一个人对着麦克风说话128Kbps就够双声道的音乐类内容建议拉到192Kbps更高的音频码率对直播体感和成本提升都有限不必追求极值。还有两个容易被忽略的进阶参数关键帧间隔和编码档位。关键帧间隔我称为直播延迟的“隐形开关”OBS里设置的“关键帧间隔秒”直接影响播放端的起播速度。建议设置为2秒这样播放器能快速找到关键帧并开始解码延迟体验明显更好。编码档位则是在OBS的“输出—输出模式—高级”里选软件编码选x264设定为“medium”画质和CPU负载均衡。硬件编码如NVENC在同码率下画质略逊但CPU占用低你可以按需选择。注意不要用“无损”或者高码率的录制参数直接直播。直播和录制的码率模型不同过高的码率会让观众端缓冲卡顿而你自己的长传带宽也容易打满反而丢帧。3.2 分发端配置SRS接收推流并输出多协议SRS的默认配置已经能接收RTMP流但我建议按实际需要改一下配置再上线。一个典型的SRS配置大概长这样listen 1935; max_connections 1000; daemon off; srs_log_tank console; http_server { enabled on; listen 8080; dir ./objs/nginx/html; } vhost __defaultVhost__ { hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 2; hls_window 12; } http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } }这个文件里几个关键项解释一下http_remux 就是用来开启HTTP-FLV拉流转发的开启后观众端可以直接用HTTP地址拉流hls_fragment设置为2秒意思是每个TS切片时长为2秒切片时长直接影响HLS播放的延迟和兼容性太短了会让播放器频繁请求切片导致卡顿太长了则延迟明显2秒是经实测比较平衡的值。配置改好之后重启容器让配置生效。用文件挂载的方式启动SRS确保配置变更不会因为容器重建而丢失docker run -d \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -v /data/srs.conf:/usr/local/srs/conf/srs.conf \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 \ ./objs/srs -c conf/srs.conf启动完成后用下面这个地址测试推流推流地址里的app和stream的名字可以自己起但要和后续拉流地址保持一致rtmp://你的服务器IP:1935/live/room13.3 播放端接入flv.js实现低延迟播放播放端这一环我们直接在HTML页面里引入flv.js从SRS拉HTTP-FLV流。flv.js是一个通过Media Source Extensions来播放FLV格式的JavaScript库核心思路是在前端把FLV数据流无损转成浏览器能识别播放的片段从而实现“纯浏览器看低延迟流”的能力。一个最小可用的播放器页面如下script srchttps://cdn.jsdelivr.net/npm/flv.js1.6.2/dist/flv.min.js/script video idplayer controls autoplay muted/video script if (flvjs.isSupported()) { var video document.getElementById(player); var flvPlayer flvjs.createPlayer({ type: flv, url: http://你的服务器IP:8080/live/room1.flv }); flvPlayer.attachMediaElement(video); flvPlayer.load(); flvPlayer.play(); } /script这个地址里的“你的服务器IP:8080”就是SRS里http_server监听的端口。注意这里用的是HTTP而非RTMP因为浏览器原生不支持RTMP必须通过FLV协议经过去延迟转发。flv.js在桌面端Chrome、Edge、Firefox上表现都很好移动端iOS上的Safari因为不支持MSE所以无法播放HTTP-FLV这种情况下需要降级到HLS。我通常推荐的做法是页面里同时放两个播放器逻辑一个是flv.js一个是原生video标签拉HLS地址。通过简单的浏览器能力检测自动选择走哪种协议。这样你在观看端的体验能维持一个相对稳定的水平不会因为某个用户用iPhone就直接卡死。3.4 完整链路联调与延迟实测配置完所有环节别急着关掉OBS先做三轮完整的链路验证。第一轮是“本地验证”OBS推流后在同一个内网的手机或另一台电脑上拉流播放重点看画面是否连贯、音画是否同步。内网环境不受外网带宽影响如果这里都卡顿说明推流端参数或服务器端口配置有问题。第二轮是“公网验证”把播放地址发给一个外网环境的朋友让他实际打开观看。这能暴露你的服务器带宽是否够用、防火墙是否挡了不必要的端口。RTMP需要放通1935端口HTTP-FLV和HLS需要放通8080端口。云服务商的安全组和服务器防火墙都要检查缺一不可。第三轮是“持续稳定性验证”运行一场超过30分钟的直播观察CPU占用、内存变化、网络流量曲线。SRS在长连接场景下偶尔会触发文件句柄数限制可以提前调大系统限制避免直播到一半服务挂掉。我实测下来全链路用HTTP-FLV延迟普遍能稳定在2~3秒左右。这里的延迟指的是从主播说话到观众听到的延迟。配合2秒关键帧间隔观众端的起播速度也很快基本是点开播放器后1秒内出画面。3.5 一个完整案例一场1小时技术分享的直播用一个真实跑过的场景来做全流程复盘当时我以一个几十人规模的技术社群身份做一场“Web性能优化入门”的公开分享观众通过一个网页看直播不要求登录也不要求注册。我的完整执行清单是主讲人电脑装OBS分辨率1080P帧率30fps视频码率5000Kbps音频码率128Kbps关键帧间隔2秒编码用x264的medium档位。画面采集用的是显示器捕获加摄像头小窗。分发端用一台2核4G的云服务器系统为Ubuntu带宽出口是5Mbps部署SRS单机服务。观看端网页用flv.js为主、HLS兜底。直播结束后额外用ffmpeg把录制好的FLV文件转成MP4回放文件ffmpeg -i record.flv -c copy record.mp4整场直播1小时服务器流量消耗约2.4GB全程无卡顿观众端延迟稳定在2.5秒左右后台看到的在线峰值人数约60人服务器CPU占用长期低于30%。这个结果很能说明问题一个几百人规模的自建直播场景对资源的要求完全在个人可控范围内。4. 常见问题与排查技巧实录4.1 推流失败或反复断流这种问题最常见的原因是地址拼写错误。注意区分推流地址和串流密钥Stream KeyOBS里填的是“rtmp://服务器IP:1935/live/”二者不能搞混。其次要检查端口是否放通云服务器安全组、ECS防火墙、本机防火墙三层都要检查。你可以在本地用telnet做端口测试telnet 服务器IP 1935如果端口不通先查安全组放行情况。还有一个容易忽略的点串流密钥不要包含特殊字符。有些播放器或服务器对接时对特殊字符处理不规范直接导致推流地址解析失败密钥用数字加字母最稳妥。4.2 播放端延迟过大从3秒涨到15秒延迟突然飙升最常见的原因是播放端走了HLS而不是HTTP-FLV。排查方法很简单用浏览器的开发者工具看网络请求如果发现大量TS切片文件的请求说明播放器被降级到HLS了。这时候优先检查flv.js是否能正常加载、浏览器是否支持MSE。次要原因是OBS里关键帧间隔配置过大。如果关键帧间隔被设成了5秒甚至10秒播放端就要等下一个关键帧才能起播感知上的延迟就会成倍增加。记得关键帧间隔按2秒配。4.3 画面清晰度不足观众反馈“糊”我先提一个概念直播清晰度和码率强相关分辨率高不代表画质好。如果码率只有1500Kbps却硬压1080P的画面画面会出现严重的马赛克和噪点。判断标准很简单用直播画面截图对比原始画面截图查看细节损失情况。解决办法有两个方向一是降低分辨率到720P同时把码率稳定在2500~3500Kbps二是保持1080P并把码率提到6000Kbps。前者适合内容源清晰度有限的场景后者适合屏幕共享、演示文稿这类细节丰富的画面。注意屏幕共享时建议把OBS的“色彩范围”设为“完整”避免画面发灰。4.4 观众数量增多后出现卡顿单机SRS不加CDN的情况下卡顿一般不是服务器性能问题而是带宽瓶颈。假设每路观看端以HTTP-FLV方式拉流码率5000Kbps意味着一个观众要占用约0.6MB/s带宽。如果你的服务器带宽只有5Mbps约0.6MB/s那么超过8个观众在线就开始卡了这是一个很简单的乘法问题。这种情况下最直接的方案是升级服务器带宽。如果已知在线规模固定那么就把码率适当降下来。更复杂的方案是接入CDN做分发但那属于扩展话题了。起步阶段明确你的容灾能力边界就好。4.5 移动端H5无法播放的兼容性问题iOS Safari对MSE支持不足导致flv.js在iPhone上无法工作。这个问题没有银弹只能做协议降级。我建议在页面加载时做UA判断和特性检测——如果浏览器支持MSE就走HTTP-FLV如果不支持就换原生video标签直接拉HLS地址。SRS已配置HLS所以移动端降级后的体验是有保障的延迟约5~8秒但画面流畅稳定。这是现阶段在纯前端方案里最可靠的处理方式。4.6 直播中途服务器突然自动断开这个坑我踩过不止一次。默认的Linux系统对每个进程能打开的文件数有上限长时间运行的SRS进程可能触碰到这个上限服务直接停摆或拒绝新连接。解决办法是修改全局文件句柄限制在启动SRS前执行ulimit -n 65535为了系统重启后仍然生效建议把这条写到SRS的启动脚本或systemd服务文件里。此外云服务器上的OOM Killer也可能在内存不足时杀掉SRS进程建议给SRS的systemd服务加上自动重启参数。一个默认宕机自愈的配置能省去你半夜爬起来手动拉服务的麻烦。5. 这套方案还能怎么延伸最后分享一个我实际用得比较多的小扩展给这套系统加一个“安全房间号”机制。SRS本身支持通过HTTP回调接口做鉴权验证推流前或播放前服务器会向你的业务接口询问“这个流是否允许访问”。我在一个付费社群场景里就是把观众端和火箭验证绑定用户购买后获得一个有时效性的播放token播放器拉流时带上tokenSRS回调你的接口校验。整体实现并不复杂但对一个运营性质的直播项目来说这种可控性非常宝贵。如果你只是个人用来做内容试播或小众分享建议从最小配置起步一台云服务器加一套SRS加OBS也就两三个小时能跑通。踩过几次坑之后你会发现直播的核心难点不在工具而在于你对“采集、编码、分发、播放”这条链路里每一个环节的掌控能力。工具是死的链路是通的真正让你项目稳定跑下去的是对这些细节的持续打磨。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进