ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

用FFmpeg、OBS与SRS搭建开源直播系统:推流、分发与拉流全解析

用FFmpeg、OBS与SRS搭建开源直播系统:推流、分发与拉流全解析 做直播对接这件事我前前后后折腾过不少方案。最开始图省事直接买云直播服务后来发现费用、配置自由度、还有对私有化部署的限制一直不那么顺手。尤其是给客户做内网视频传输、设备端画面回传这类需求云直播几乎用不起来。后来我把目光转到开源方案上用这三款工具搭出了一整套从推流、服务端接收、到多端拉流的完整链路纯开源、免费商用、源码可改覆盖了服务器、云平台、移动设备这些典型目标端。如果你也正在做直播相关的东西这篇文章应该能帮你省下好几天的调研时间。我要聊的三款工具分别是ffmpeg、OBS Studio和SRSSimple Realtime Server。它们不是三个平级选项而是一条生产链上的不同环节ffmpeg 负责命令行推流和灵活的拉流转码OBS 负责桌面端的高画质推流SRS 负责在服务端接收、汇聚、分发。三者的源码都开放文档齐全社区活跃不管你是做嵌入式设备、搭私有流媒体服务还是给内容创作者做直播工具都能直接拿过去用。1. 选型前的判断先弄清推流、拉流、服务端这三件事很多刚接触直播的同学容易一上来就问“哪个工具最好”但实际项目里更该先问的是你的场景缺哪一环我习惯把整个直播链路拆成三块推流端采集编码发送、流媒体服务端接收汇聚分发、拉流端解码播放。这三块各有各的坑也各有各的合适工具。推流端解决的是“画面怎么送出去”的问题。摄像头、屏幕、视频文件都只是信号源要变成能在网络上传输的流需要经过采集、编码、封装、上传这一串动作。OBS 和 ffmpeg 都能干这件事区别在于 OBS 有图形界面、适合人坐在电脑前操作ffmpeg 是纯命令行工具适合写脚本、跑在服务器或嵌入式设备上、做无人值守的自动推流。服务端解决的是“流怎么收下来、再发给很多人”的问题。直接拿推流端的地址给观众播放是不可行的因为一个推流端通常只能维持有限的并发连接而且你也不想让主播端直接暴露给所有观众。SRS 这类流媒体服务器就是把推上来的流接收住再按需分发给成千上万个拉流端。它还可以做录像、转码、鉴权这些增值功能。判断要不要自建服务端很简单只要你的观众超过三五个或者需要直播录制、防盗链、多协议分发就必须有这一层。拉流端解决的是“观众用什么看”的问题。VLC、ffplay、浏览器里的 hls.js、手机 App 里的播放器 SDK都是拉流端。不同拉流端支持的协议不一样这就是为什么服务端要支持多种分发协议——你不能要求用户为了看你的直播特意装一个播放器。目标端是移动设备还是 PC、是浏览器还是原生 App直接影响服务端需要开放哪些协议。三款工具正好对应这三块ffmpeg 在推流和拉流两头都能用OBS 专注桌面推流SRS 负责服务端接收与分发。所以与其纠结“哪个工具最强”不如先画出你自己的链路再看缺哪个环节。我自己的经验是哪怕只是一个临时演示项目也值得把服务端立起来因为这样可以完整验证推流、拉流、鉴权、录像、延迟表现等真实生产环境才会遇到的问题后面交付的时候心里有底。2. 三款开源工具逐一拆解2.1 ffmpeg命令行全能的推拉流瑞士军刀ffmpeg 是老牌开源项目几乎所有音视频处理工具背后都有它的影子。它本身不是专为直播设计的但它的推流和拉流能力极其强大一条命令行就能把本地摄像头推到远程服务器也能把远程流保存成文件或转成另一种协议。先看推流。最经典的命令是这样ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -f flv rtmp://your-server/live/stream1这里每个参数都有讲究-re让 ffmpeg 按文件本身的帧率读取输入不然它会以最快速度把文件读爆推流就成了“瞬发”-c:v libx264指定 H.264 编码-preset veryfast是在编码速度和画质之间取平衡直播场景下推荐 veryfast 或 ultrafastCPU 压力小-tune zerolatency是专门为低延迟场景设计的它会让编码器少做缓冲-c:a aac指定 AAC 音频编码这是直播兼容性最好的组合最后-f flv加上 rtmp 地址把流封装成 FLV 推到 RTMP 服务端。拉流也很简单。如果你想看一个 RTMP 流的内容不想开笨重的播放器用 ffplay 就能直接预览ffplay rtmp://your-server/live/stream1如果想把一条直播流保存成文件一条命令搞定ffmpeg -i rtmp://your-server/live/stream1 -c copy record.flv-c copy表示不需要重新编码直接把接收到的数据写进文件CPU 占用几乎为零。这个做法在直播录制、回放归档场景里非常实用我做过的一个项目就是用这条命令给值班室做 24 小时循环录像跑得非常稳。ffmpeg 源码托管在 GitHub 的 FFmpeg 官方仓库编译配置有很强的定制性比如可以只编译你需要的协议封装格式把体积压到十几 MB这对嵌入式设备特别友好。唯一要适应的是它的命令行学习曲线但一旦熟悉了你能拿它做的事会远超预期。2.2 OBS Studio桌面端专业级直播推流OBSOpen Broadcaster Software是我见过最有“生产力”的开源推流软件。它支持窗口采集、显示器采集、摄像头、图片、文本、媒体源多种输入可以自由叠加图层、设置场景切换、混音、加滤镜而且全流程实时预览。对内容创作者来说它的定位几乎是不可替代的。OBS 的核心使用逻辑是“场景 来源 输出设置”三段式。你先建一个场景在场景里添加你要用的各种来源比如摄像头画面、演示窗口、通知条然后到设置里配置输出。推流到 SRS 或任何 RTMP 服务端时只需要填两个信息服务器地址和推流密钥。以 SRS 为例服务器地址填rtmp://your-server/live推流密钥填stream1最终完整推流地址就是rtmp://your-server/live/stream1。关键的输出参数在“设置 - 输出”里。我建议新手直接切换到“高级输出模式”这样能看到更多参数。视频比特率一般按分辨率来定1080p 30fps 推荐 4500-6000 Kbps720p 30fps 推荐 2500-3500 Kbps编码器优先选硬件编码NVIDIA 显卡选 NVENCAMD 显卡选 AMFIntel 核显选 QSV硬件编码能大幅降低 CPU 占用关键帧间隔设置为 2 秒也就是 GOP 为 6030fps 下这样拉流端在开播或切换清晰度时能更快找到关键帧减少起播黑屏。另外要提醒的是“延迟模式”这个老坑。在“设置 - 高级”里有个“串流延迟”如果你勾选了“启用串流延迟”并设置了秒数画面会故意延后输出这是给需要审片场景用的。普通直播千万不要开不然你这边说完话观众那边要等几十秒才听到排查半天还以为网络问题。OBS 一直是开源软件遵循 GPL 协议源码在 GitHub 上可以完整获取。它的插件生态也很开放比如你现在看到的虚拟摄像头功能就可以把 OBS 的输出作为虚拟设备提供给 Zoom、腾讯会议调用极大扩展了它的应用场景。2.3 SRS服务端的推流汇聚与多协议分发SRS 是我在服务端最推荐的开源流媒体服务器名字是 Simple Realtime Server。它最大的特点是部署极其简单、单机性能好、支持的协议非常全。RTMP、HTTP-FLV、HLS、WebRTC、SRT、GB28181 它都支持对国内流媒体生态尤其友好。SRS 的架构思路很清晰接收推流端ffmpeg、OBS 或任何 RTMP 客户端推上来的流然后把同一条流转成多种协议分发给拉流端。比如一条 RTMP 推上来的流浏览器端可以用 HTTP-FLV 或 WebRTC 看移动端 App 可以用 HTTP-FLV 或者 HLS 看传统播放器可以用 RTMP 直接拉。服务端一个进程就能同时服务几百上千路并发配合 HTTP 负载均衡还能水平扩展。从源码角度看SRS 是纯 C 项目代码结构清晰模块划分明确官方有详细的架构文档。如果你需要二次开发比如自定义鉴权回调、接入自己已有的用户体系SRS 的 HTTP 回调机制可以做到而且社区里有很多现成的扩展案例。对嵌入式场景它也有 ARM 架构的编译支持我曾在 RK3399 板子上成功跑过 SRS稳定推了多路监控画面没有问题。我不太推荐再用 Nginx-RTMP 模块来搭直播服务不是说它不能用而是它的维护状态已经比较冷却WebRTC 支持基本没有HLS 的切片能力也远不如 SRS 顺手。SRS 的文档和示例脚本都非常完善Docker 部署一键就能起来新手也能很快建立起完整概念。3. 核心协议与参数细节决定成败的往往是配置3.1 推流协议怎么选RTMP、RTSP、SRT、WebRTC 对比协议选择直接决定延迟、穿透性和播放器兼容性这是搭建直播系统时最需要下判断的地方。我给你的建议是根据“内容类型”和“观众端环境”一起决定而不是只看延迟参数。协议适用场景典型延迟防火墙友好性成熟度RTMP推流到服务端、传统播放器拉流2-5 秒一般依赖 1935 端口极高RTSP局域网内摄像头、安防设备对接0.5-2 秒一般依赖 554 端口高SRT跨网络弱网环境、公网传输1-3 秒好可跑在 UDP 端口上中高WebRTC浏览器、低延迟互动直播0.1-0.5 秒好基于 UDP 且自适应近年快速成熟我的习惯是内网设备接入首选 RTSP因为它天然适合音视频设备和安防生态公网直播推流首选 RTMP因为它对 CDN、播放器、云平台的兼容性最好网络条件差、要跨公网传高清信号用 SRT如果对延迟有极致要求比如远程操控、视频会议、在线考试这类直接用 WebRTC。SRS 把这几种协议都支持了所以你可以在推流端选一个适合路径的协议在拉流端再按播放器情况分发非常灵活。3.2 编码参数才是画质和延迟的关键协议只是容器和传输方式画质和延迟很大程度上由编码参数决定。我在调优时第一个固定下来的是编码规格视频 H.264、音频 AAC。为什么不用 H.265因为 H.265 虽然在同等码率下画质更好但浏览器和移动端硬解的兼容性参差不齐而且在弱网下容易踩雷。直播场景要的是“所有人都能看”不是“极限画质”。第二个关键参数是GOPGroup of Pictures关键帧间隔也叫关键帧间隔。播放器要能随时解码播放必须等下一个关键帧到达。如果 GOP 太长观众切换清晰度、中途进入直播间时就会长时间黑屏或卡在缓冲。我一般把 GOP 控制在 2 秒以内比如 30fps 就设 60 帧一个关键帧。但也不要过短因为关键帧体积大太频繁会浪费码率。第三个是码率控制方式。直播场景推荐 CBR恒定比特率而不是 VBR可变比特率因为流媒体传输吃的是恒定带宽VBR 的码率波动在弱网下更容易引发延迟和卡顿。ffmpeg 里可以用-b:v指定码率OBS 高级输出模式里也有“比特率”选项本质上就是在做 CBR 控制。给一个保守的起步码率参考分辨率帧率推荐视频码率Kbps1280x72030fps2500-35001920x108030fps4500-60002560x144030fps8000-100003840x216030fps15000-25000音频码率一般 128-192Kbps 就够了人声内容 128Kbps 即可音乐直播可以提到 192Kbps。超过 256Kbps 在直播场景下意义不大浪费带宽还容易卡。3.3 拉流端HTTP-FLV、HLS、WebRTC 各自怎么用服务端把流收下来最终还是要让拉流端能看。不同播放环境支持的协议完全不同这是我踩过很多坑之后才彻底想通的。HTTP-FLV是目前国内直播最主流的拉流方式。它把 FLV 封装的数据通过 HTTP 流式传输兼容性好、延迟低移动端 App 通过播放器 SDK 播放也就 2-4 秒延迟。关键是它只要一个 HTTP 地址浏览器里也可以用 flv.js 播放服务端配一个 HTTP 端口就行不像 RTMP 那样需要单独开 1935 端口。SRS 对 HTTP-FLV 的支持是开箱即用的。HLSHTTP Live Streaming是苹果主导的标准服务端把流切成一段段 TS 或 fMP4 文件播放器逐段下载播放。它的天然优点是任何支持 HTTP 的环境都能看CDN 友好还能自动适配不同清晰度但它有 6-30 秒的延迟不适合互动场景。如果你要分享给微信、网页、通用播放器用户HLS 是不二之选SRS 可以用-c copy方式实时切片或者走在线转封装。WebRTC则是低延迟场景的终极解法。它做到亚秒级延迟浏览器原生支持不需要装任何插件。远程连麦、在线教育、远程控制这种场景它比 FLV 和小儿 科式的 RTMP 靠谱太多。SRS 从 4.0 开始把 WebRTC 作为一个一等公民支持推流拉流都可以走 WHIP/WHEP 协议配合浏览器端播放器实测局域网延迟能压到 200-500 毫秒。4. 完整实操从推流到拉流的一条龙复现4.1 用 Docker 快速部署 SRS 服务端SRS 提供了官方 Docker 镜像一条命令就能跑起来非常适合先验证整体链路docker run --rm -p 1935:1935 -p 8080:8080 -p 1985:1985 -p 8000:8000/udp registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4这条命令映射了四个端口1935 是 RTMP 推拉流端口8080 是 HTTP 服务端口用来分发 HTTP-FLV、HLS1985 是 SRS 的 HTTP API 端口8000/udp 是 WebRTC 需要的 UDP 端口。起来之后浏览器访问http://your-server:8080/players/可以看到官方自带的播放器测试页到这里服务端就算搭好了。如果你不想用 Docker也可以直接从源码编译。SRS 的编码过程在官方文档中写得很简单三步git clone -b 4.0release https://github.com/ossrs/srs.git cd srs/trunk ./configure make ./objs/srs -c conf/srs.conf编译时间取决于机器性能普通配置下 5-10 分钟能完成。我推荐新手先用 Docker 跑通全流程再去碰源码编译这样可以把“环境问题”和“逻辑问题”分开排查。4.2 用 ffmpeg 把本地视频推送到 SRS服务端起来之后用 ffmpeg 推流验证。没有摄像头或现场画面的情况下可以先用本地视频文件模拟ffmpeg -re -i test.mp4 -c:v libx264 -preset veryfast -tune zerolatency -c:a aac -f flv rtmp://localhost/live/stream1推流命令执行后如果没有任何报错并且持续有输出说明流已经送上去了。可以在浏览器打开 SRS 的播放器测试页选择“HTTP-FLV”选项填地址http://localhost:8080/live/stream1.flv看画面是否正常出来。如果你不想用文件想直接推摄像头画面Linux 下可以用ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset veryfast -tune zerolatency -f flv rtmp://localhost/live/stream1Windows 下可以用 dshow 设备名替代/dev/video0。注意摄像头分辨率、帧率要和编码参数匹配否则容易出现画面花屏或者推流失败。建议先用ffmpeg -f v4l2 -list_formats all -i /dev/video0查看设备支持的分辨率列表。4.3 多协议拉流验证VLC、浏览器、ffplay 各来一遍验证完推流下一步是验证拉流。我建议你至少测试三种拉流方式确认服务端多协议分发正常。第一种VLC 拉 RTMP 流。打开 VLC选择“媒体 - 打开网络串流”填rtmp://localhost/live/stream1。如果看到画面说明 RTMP 协议正常。第二种浏览器拉 HTTP-FLV。直接访问http://localhost:8080/live/stream1.flv浏览器一般不能直接显示 FLV所以要么用 SRS 自带的播放器页要么用一个支持 flv.js 的页面。SRS 播放器页可以帮你实测 flv.js 的延迟表现。第三种ffplay 拉流对比延迟ffplay -fflags nobuffer -flags low_delay -analyzeduration 0 -probesize 32 rtmp://localhost/live/stream1这几个参数的组合是 ffplay 做低延迟播放的关键。-fflags nobuffer关闭输入缓冲-flags low_delay让解码器尽快输出-probesize 32限制探测数据量。实测下来局域网内这种方式拉流延迟能控制在 1 秒左右。WebRTC 的验证方式稍特殊SRS 的播放器页里也提供 WebRTC 播放选项填webrtc://localhost/live/stream1即可。需要说明的是WebRTC 对网络环境要求高跨公网播放需要保证 UDP 端口可达很多云平台默认安全组不开放 UDP这一点要提前检查。4.4 让移动设备也能看公网部署与内网穿透移动设备拉流是高频需求。把 SRS 部署在公网服务器上手机 VLC 直接填rtmp://your-server-ip/live/stream1就能看。但要注意RTMP 用的 1935 端口很多 5G 网络或公司 Wi-Fi 会封所以移动端我更建议走 HTTP-FLV 或 HLS。移动端拉流地址示例HTTP-FLVhttp://your-server-ip:8080/live/stream1.flvHLShttp://your-server-ip:8080/live/stream1.m3u8HLS 地址可以直接填进手机浏览器iOS Safari、Android Chrome 都原生支持也可以填进 VLC 等播放器。如果你自己在家里调试网 上没有公网 IP可以借助内网穿透工具把 8080 端口映射出去但不能用“特定”的任一工具用常见的 frp、nps 这类自搭建方案都行。记得穿透性能选项选择 TCP 模式HLS 和 HTTP-FLV 都是 HTTP 协议TCP 一样能跑。5. 常见问题排查与避坑技巧实录做流媒体直播一次就会遇到各种奇葩问题。我把自己真实踩过的坑整理成速查表下次你再遇到可以直接按图索骥。现象可能原因排查与解决拉流黑屏、无画面推流端 GOP 太长、编码格式不兼容检查推流端关键帧间隔是否大于 4 秒确认视频编码是 H.264音频是 AAC延迟越来越大播放器缓冲设置过大、网络拥塞、编码端码率过高优先排查播放器缓冲查看服务端连接数降低推流码率声音和画面不同步音频采样率不匹配、时间戳错乱确认音频统一为 44100 或 48000Hz不要随意混用不同源的音视频拉到一半就断流推流端网络抖动、RTMP 发布链接超时检查推流端日志适当调整 SRS 超时配置加强推流端网络稳定性手机浏览器看不了 RTMPRTMP 需要播放器插件改用 HTTP-FLV 或 HLS 地址开播后服务器 CPU 爆满软件编码压力大、客户端人数多优先优化编码参数使用低分辨率测试升级硬件或用硬件编码必要时做集群嵌入式板子推流很卡开发板 CPU 性能不足、编码没有硬件加速降低分辨率帧率用-preset ultrafast检查板载编码器是否能直接用硬件编码视频发白或偏色HDR 信号未转换、采集端色彩空间错误在 OBS 输出设置中关闭 HDR或在 ffmpeg 中加-color_range limited还有一个极其重要的避坑点开播前先测一下服务端端口是否对外开放。我经常遇到推流地址写对了、命令也没报错但别人在外面就是拉不到流。一查云平台安全组只开了 22 和 80 端口1935 和 8080 根本没有放行。这件事建议在部署清单里作为一个固定校验项写完配置先访问服务端的 HTTP 端口和 RTMP 端口确认可达再做后续调试。安全方面也别忽视。SRS 自带的 HTTP 接口默认没有鉴权如果你的服务器暴露在公网别人也能推流进来。SRS 4.x 支持on_publish回调做推流鉴权你可以配置一个自己的 API 来校验推流密钥。OBS 端只需在推流地址后拼上自定义的 stream 名就能当推流密钥用。生产环境务必开启内部测试环境则可以保持简单。另外关于 HLS 延迟很多同学会说“HLS 不是有 6-30 秒延迟吗”。我实测 SRS 的 HLS 默认切片时长是 5 秒还有 3 个分片的缓冲所以延迟大概在 10-20 秒。如果你用 HLS 做非互动直播比如监控展示、活动录播轮播这个延迟无感但如果做互动问答一定要切到 HTTP-FLV 或 WebRTC别在 HLS 上死磕。最后再分享一个真实项目的经验。当时我需要在几个工业现场各部署一块 RK 开发板把摄像头画面实时传回总部的大屏展示。板子上跑 ffmpeg 硬件编码 SRS 轻量部署总部端用 WebRTC 拉流延迟稳定在 500 毫秒以内比现场遥控轮子还跟手。整个过程涉及的代码、配置、协议就是这篇文章讲到的这些。开源工具的组合很自由真正上手之后你会发现直播系统并没有想象中那么复杂只要把协议和服务端这两层吃透剩下的就是按需拼装。
返回列表