之前在项目中需要快速验证一条“RTMP 推流 + WebRTC 低延时播放”的链路是否可行,结果卡在测试环境搭建上:资料很散,有的讲 RTMP 推流,有的讲 WebRTC 播放,却没有人把中间转换层说清楚。折腾了两天才跑通第一帧画面,后面整理成一套可复用的 rtmp2webrtc 测试环境搭建流程,正好分享出来。如果你也正在做直播、音视频通话、低延迟播放相关的验证,这篇文章可以帮你少踩很多坑。
本文会从 RTMP 和 WebRTC 各自解决什么问题讲起,接着给出测试环境的目标架构和组件选型,然后基于开源流媒体服务器搭建一套完整的 rtmp2webrtc 测试环境,包含 Docker 部署、推流、播放、自动化验证、常见报错排查,以及测试环境落地时的一些工程建议。新手可以按步骤从头跟到尾,有经验的开发者可以直接跳到第 4 节复制部署命令。
1. RTMP 与 WebRTC 核心概念
1.1 RTMP 是什么
RTMP 全称 Real-Time Messaging Protocol,也就是实时消息传输协议。它最早由 Macromedia 设计,后来 Adobe 持续维护,曾经是直播行业事实上的标准协议。目前常见的 RTMP 推流工具 OBS、FFmpeg,以及各大直播平台的服务端,大多都支持 RTMP 协议。
RTMP 基于 TCP 传输,默认端口是 1935。它的优点是生态特别成熟,推流端不管是用 OBS 还是 FFmpeg,都能很方便地把音视频数据推到流媒体服务器上。缺点是延迟比较高,通常在 2 到 5 秒左右,而且浏览器原生不支持 RTMP,用户要在网页里看 RTMP 流,必须依赖 Flash 插件或者服务端转封装。
虽然 Flash 已经退出历史舞台,但 RTMP 作为“推流侧协议”依然很常用。你手里的大量直播流、存量系统、硬件编码器,可能都还在走 RTMP 推流。
1.2 WebRTC 是什么
WebRTC 全称 Web Real-Time Communication,也就是网页实时通信。它是一套由 Google 主导并开源的标准能力,让浏览器之间可以不经插件直接进行音视频通话、数据传输。
WebRTC 的传输层通常基于 UDP,通过 SRTP 加密、NACK 重传、JitterBuffer 抖动缓冲等机制,把端到端延迟压缩到 500 毫秒甚至更低。由于浏览器原生支持 WebRTC,不需要安装任何插件,所以它在在线教育、视频会议、远程医疗、低延迟直播等场景里越来越流行。
WebRTC 的短板也明显:一是没有统一的“拉流 URL”概念,播放端需要经过信令协商、ICE 候选收集等流程才能建立连接;二是对网络环境和服务器公网 IP 的依赖比较强,稍不注意 candidate 配置错误,页面就会一直处于 connecting 状态。
1.3 为什么需要 RTMP 转 WebRTC
现实中大量直播源、编码器、旧的推流端都支持 RTMP,但用户更想在浏览器里直接用 WebRTC 低延迟观看。此时就需要一个“中间层”把 RTMP 流转换成 WebRTC 流,这个中间层就是 rtmp2webrtc 转换的核心。
如果去掉中间层,常见做法是让客户端拉 HLS,延迟基本在 5 到 15 秒,适合点播但不适合互动直播。做实时连麦、互动答题、指挥调度、直播带货这类对延迟敏感的场景时,延迟一高体验就会明显变差。所以“推流端保留 RTMP,播放端走 WebRTC”成了一种性价比很高的组合。
1.4 常见应用场景
rtmp2webrtc 测试环境的常见应用场景包括:
- 验证现有 RTMP 直播源能否被低延迟播放。
- 评估 WebRTC 在局域网内或公网下的播放效果。
- 对比不同流媒体服务器的转协议能力和资源消耗。
- 为产品提供低延迟播放能力做技术预研。
- 在测试环境复现线上 WebRTC 播放失败问题,便于排查。
理解了背景之后,接下来要明确一点:我们并不是在自己的代码里实现私有转换算法,而是借助成熟的开源流媒体服务器完成协议转换。
2. 测试环境目标与整体架构
2.1 测试环境要验证什么
搭建 rtmp2webrtc 测试环境时,重点不是“把服务跑起来”就结束,而是要验证下面几件事:
- RTMP 推流是否正常。
- 流媒体服务器是否成功接收并转封装。
- WebRTC 播放是否能在浏览器中出画面。
- 延迟大概处于什么水平。
- 并发播放时服务器资源消耗是否可控。
- 断流重推、播放端刷新是否影响其他观看端。
如果当前只是为了做功能验证,只要跑通“推流 -> 转换 -> 播放”链路即可。如果是为了生产选型,则还需要叠加长时间稳定性、并发压力、弱网环境等测试。
2.2 整体链路设计
整个 rtmp2webrtc 测试链路可以用下面这张简图表示:
推流端(OBS/FFmpeg) --RTMP--> 流媒体服务器(SRS) --WebRTC--> 浏览器(Chrome/Edge)实际工作时,推流端先通过 RTMP 协议将 H.264 + AAC 音视频数据推送给流媒体服务器。流媒体服务器接收后,把数据转封装成 WebRTC 需要的 RTP/SRTP 包,并通过信令和 ICE 流程与浏览器建立连接。浏览器再通过 WebRTC 协议拉取视频画面。
这里有一个容易混淆的点:RTMP 推流和 WebRTC 播放并不要求使用同一个播放 URL。RTMP 地址通常是rtmp://ip/live/stream,而 WebRTC 播放地址通常是webrtc://ip/live/stream,或者通过 HTTP 页面触发播放。实际测试时,这两个地址的流名要一致,否则服务器找不到对应流。
2.3 组件选型
当前开源社区里支持 rtmp2webrtc 的常见方案有:
- SRS:国产开源流媒体服务器,支持 RTMP、WebRTC、HLS、HTTP-FLV 等,配置简单,文档完善,是很多团队的首选。
- ZLMediaKit:基于 C++ 的高性能流媒体服务器,支持 RTSP、RTMP、WebRTC、GB28181 等,适合嵌入式设备和企业级项目。
- Janus:一个通用 WebRTC 网关,功能更偏 SFU 和音视频会议,但也能接入 RTMP 流。
- Medooze:面向 SFU 的流媒体服务器,主要用在云会议场景。
如果你是第一次搭 rtmp2webrtc 测试环境,我更推荐先用 SRS,因为它的 Docker 镜像体积小、启动快,内置的 WebRTC 播放页面可以直接用来验证,能省掉不少前端开发工作。本文的完整实战案例也以 SRS 为主。
3. 环境准备与版本说明
3.1 服务器要求
rtmp2webrtc 测试环境不需要太高配置,2 核 4G 的虚拟机或云主机就够跑通验证链路。操作系统可以选择 CentOS 7.9、Ubuntu 20.04/22.04,也可以使用国产化操作系统如麒麟 V10,只要内核支持 Docker 或主流 Linux 依赖库,整体部署思路一致。
需要特别注意的是 WebRTC 使用 UDP 传输,因此要把相关的 UDP 端口在防火墙上放行。网络环境尽量让推流端、流媒体服务器、浏览器播放端处于同一个局域网内,这样可以减少公网 NAT 带来的 candidate 问题。
3.2 软件版本说明
本文示例以 SRS 5.0 为例,使用 Docker 方式启动。不同小版本的配置项可能略有差异,如果你使用的是 SRS 4.0 或其他分支,建议以对应版本的官方文档为主。Docker 和 FFmpeg 的安装命令也依赖你的操作系统发行版本,实际使用时按当前环境调整即可。
下面给出一个参考版本清单:
| 组件 | 说明 |
|---|---|
| 操作系统 | CentOS 7.9 / Ubuntu 22.04 / 麒麟 V10 |
| Docker | 20.10 及以上 |
| SRS | 5.0 系列 |
| FFmpeg | 4.4 及以上 |
| 浏览器 | Chrome / Edge 最新版 |
如果你的环境里 Docker 安装比较早,建议先检查版本,旧版本 Docker 可能影响 UDP 端口映射行为。
3.3 网络与端口规划
SRS 在 rtmp2webrtc 场景下主要涉及如下端口:
- 1935:RTMP 推流端口。
- 1985:HTTP API 端口。
- 8080:HTTP 服务端口,用来访问内置播放页面。
- 8000/UDP:WebRTC RTC 端口。
真实生产环境中还需要考虑 8000 端口是否被占用,以及云安全组是否放通了 TCP 和 UDP 规则。很多 WebRTC 播放失败的问题,最后排查下来就是 UDP 端口不通。
4. 基于 SRS 搭建 rtmp2webrtc 测试环境
4.1 为什么选 SRS
SRS 对 WebRTC 的支持比较成熟,支持将 RTMP 流转封装为 WebRTC 流播放,也支持 WebRTC 推流。它内置了rtc_player.html播放页面,可以在浏览器里直接验证,不用先写前端代码。SRS 还提供 HTTP API 查询流信息,方便测试环境做自动化检查。
最关键的是 SRS 采用单进程多协程模型,内存占用不高,部署方式简单,很适合测试环境快速验证。即使你后续生产环境准备换成 ZLMediaKit,也可以先用 SRS 验证整体链路是否可行。
4.2 安装 Docker
如果服务器上没有 Docker,先安装 Docker。Ubuntu 和 CentOS 的安装命令不同,这里以两种系统给出参考:
# Ubuntu / Debian 系列 sudo apt update sudo apt install -y docker.io docker-compose # CentOS 7 系列 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io安装完成后启动 Docker 服务:
sudo systemctl enable docker sudo systemctl start docker docker --version看到版本号输出后,说明 Docker 安装成功。
麒麟 V10 这类系统如果仓库里没有 Docker 包,可以考虑使用清华源、阿里源等镜像仓库安装,或者直接下载静态二进制包解压使用。这里不展开具体镜像源配置,按你所在团队的安全策略来即可。
4.3 启动 SRS 并开启 WebRTC
先用最简单的默认配置启动 SRS,验证镜像能否正常运行:
docker run --rm -it \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ ossrs/srs:5这个命令会前台运行 SRS,日志直接打到终端。看到类似下面的日志说明启动成功:
SRS 5.0.xxx Copyright (c) 2013-2024, The SRS Community ... rtmp server listen on 0.0.0.0:1935 http api listen on 0.0.0.0:1985 http server listen on 0.0.0.0:8080 rtc server listen on 0.0.0.0:8000默认配置下 WebRTC 不一定会按照你的网卡 IP 生成 candidate,所以在实际测试环境中,更推荐使用自定义配置文件。在服务器上创建srs.conf:
mkdir -p /opt/srs/conf mkdir -p /opt/srs/objs vi /opt/srs/conf/srs.conf文件内容如下:
listen 1935; max_connections 1000; daemon off; srs_log_tank console; http_api { enabled on; listen 1985; } http_server { enabled on; listen 8080; dir ./objs/nginx/html; } rtc_server { enabled on; listen 8000; # 重要:改成你的服务器实际 IP,否则 WebRTC 无法连接 candidate 192.168.1.100; }配置重点说明:
listen 1935:指定 RTMP 监听端口。http_api:开启 HTTP API,后续可以用1985查询流信息。http_server:开启 HTTP 静态文件服务,用来访问播放页面。rtc_server:WebRTC 服务配置。candidate:告诉浏览器“你要连接的媒体服务器地址是哪个”,必须改成服务器实际可达的 IP。如果填错或保持默认,浏览器会一直连接不上。
然后通过 Docker 挂载配置文件启动:
docker run -d --name srs-rtc \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -v /opt/srs/conf/srs.conf:/usr/local/srs/conf/srs.conf \ -v /opt/srs/objs:/usr/local/srs/objs \ ossrs/srs:5这里挂载了配置文件目录,方便后续调整候选 IP 或端口。
4.4 验证服务状态
容器启动后,查看日志:
docker logs -f srs-rtc然后检查端口监听情况:
ss -lntup | grep -E '1935|1985|8080|8000'如果 TCP 端口能正常监听,说明 RTMP 和 HTTP 服务没问题。UDP 8000 端口也要能看到监听,否则 WebRTC 服务没有成功启动。
还可以通过 HTTP API 检查服务器状态:
curl http://127.0.0.1:1985/api/v1/versions返回的 JSON 里包含 SRS 版本信息,说明 API 服务正常。
4.5 使用 FFmpeg 模拟 RTMP 推流
测试环境不一定有真实的摄像头或编码器,可以用 FFmpeg 生成一段测试视频流并推到 SRS。先确保服务器或本机安装了 FFmpeg:
ffmpeg -version下面这条命令会生成一个 640x480、30 帧每秒的测试画面,并叠加音频,然后通过 RTMP 推流到 SRS:
ffmpeg -f lavfi -re -i testsrc=size=640x480:rate=30 \ -f lavfi -re -i sine=frequency=1000:sample_rate=44100 \ -vcodec libx264 -preset veryfast -tune zerolatency \ -acodec aac \ -f flv rtmp://192.168.1.100:1935/live/livestream参数说明:
-f lavfi -i testsrc:生成测试视频源。-f lavfi -i sine:生成正弦波音频。-vcodec libx264:使用 H.264 编码。-tune zerolatency:降低编码延迟,适合低延迟调试。-f flv rtmp://...:以 FLV 封装格式推送到 RTMP 地址。
推流后,浏览器播放端才能看到画面。如果你有真实摄像头,也可以直接用 OBS 推流,设置里填rtmp://192.168.1.100:1935/live/livestream,流密钥填写livestream即可。
4.6 浏览器 WebRTC 播放验证
SRS 内置了 WebRTC 播放页面,可以通过下面的地址访问:
http://192.168.1.100:8080/players/rtc_player.html打开页面后,在播放地址里填:
webrtc://192.168.1.100/live/livestream点击播放按钮,稍等片刻就能看到 FFmpeg 生成的测试画面。
这里有一个容易混淆的点:WebRTC 播放地址的格式是webrtc://ip/live/livestream,后面不需要再次带1935端口。SRS 会根据配置自动处理 WebRTC 连接。
如果页面一直显示 connecting,优先检查以下几点:
srs.conf中candidate是否填了正确的服务器 IP。- UDP 8000 端口是否被防火墙拦截。
- 浏览器是否限制了 UDP 传输。
- 服务端日志是否提示 RTC 连接失败。
浏览器播放成功后,可以观察一下延迟情况。对着画面同步调整推流端时钟或播放计时器,理论上 WebRTC 播放延迟远低于 RTMP/HLS 播放。
4.7 验证流状态
SRS 提供了 HTTP API 查看当前流列表,可以用来确认这条 rtmp2webrtc 链路是否真的打通:
curl http://127.0.0.1:1985/api/v1/streams/返回 JSON 中会显示当前活跃流的app、name、url等信息。如果能看到类似的流信息,说明 RTMP 推流端、SRS、WebRTC 播放端之间的数据通路是完整的。
5. 备选方案:ZLMediaKit 简介
SRS 验证完整体链路后,有些团队可能还会评估 ZLMediaKit,因为它在 GB28181、RTSP、WebRTC 等场景里也很有优势。ZLMediaKit 的部署比 SRS 略微复杂,一般需要从源码编译或使用第三方构建产物。
ZLMediaKit 的 WebRTC 支持同样是基于原生 WebRTC 网关,默认使用的是 10000 端口范围作为 RTC 端口。配置时重点确认rtc.port范围、服务器外网 IP 映射、SSL 证书等参数。
如果你只是想验证流媒体服务器能否把 RTMP 转成 WebRTC,SRS 是最快的路径;如果你想做更复杂的多协议融合、设备接入,ZLMediaKit 可以作为第二阶段评估对象。
6. 常见问题与排查思路
rtmp2webrtc 测试环境常见问题主要集中在网络、candidate、防火墙和浏览器兼容性上。下面整理成一张排查表:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| WebRTC 页面一直 connecting | candidate 配置错误 | 修改rtc_server.candidate为服务器实际 IP |
| 推流成功但播放黑屏 | 编码格式或参数兼容问题 | 使用 H.264 + AAC,避免使用浏览器不支持的编码 |
| WebRTC 页面打开就报错 | 访问地址是公网但未走 HTTPS | 公网环境需要配置 HTTPS,localhost 推荐用 HTTP |
| 播放延迟依然很高 | 推流端视频编码参数未优化 | 增加-tune zerolatency,降低 GOP 大小 |
| UDP 端口无法连接 | 云安全组未放行 UDP | 开放 8000/UDP 端口,测试环境可临时关闭防火墙验证 |
| 多个播放端互相影响 | 服务器带宽或连接数不足 | 检查 CPU、带宽和 SRS 连接数日志 |
| FFmpeg 推流中断 | 网络不稳定或编码参数不合理 | 降低码率、增大缓冲区、检查网络丢包 |
如果遇到 WebRTC 连接失败,可以在 Linux 服务器上用tcpdump抓包确认 UDP 包是否到达服务器:
tcpdump -i eth0 udp port 8000 -n如果在播放期间看不到 UDP 包进入服务器,说明网络路径不通,优先排查安全组、防火墙和路由。
浏览器层面,WebRTC 播放对 HTTPS 有严格限制。在公网测试时,如果访问的是 HTTPS 页面,页面里的 WebRTC 连接也必须使用 HTTPS 或 localhost 白名单。测试环境如果搭建在云主机上,建议先用http://IP访问验证,后续要生产化再补 HTTPS。
还有一个常见坑是服务器有多个网卡。candidate 如果填错网卡 IP,浏览器能把信令发给 SRS,但媒体流到不了浏览器。你可以通过ip addr查看服务器所有网卡 IP,选择浏览器真正能访问到的那个地址。
7. 测试环境最佳实践与工程建议
7.1 保持版本一致性
rtmp2webrtc 测试环境从测试到生产,最怕的就是版本漂移。SRS 4.0 和 5.0 的 WebRTC 配置项不同,FFmpeg 4.x 和 5.x 的编码器行为也有差异。建议把镜像版本、配置文件、推流命令都记录到项目文档中,方便后续复现。
测试环境建议锁定 SRS 镜像版本,例如ossrs/srs:5.0.128,避免每次拉取最新镜像导致行为变化。等选型确定后,再统一升级生产环境版本。
7.2 网络配置要单独整理
WebRTC 对 UDP 依赖很强,测试环境的网络配置不能只靠“不用管”。建议单独记录:
- 服务器公网 IP / 内网 IP。
- candidate 最终填的是什么。
- 防火墙规则、云安全组规则。
- 浏览器访问使用的是 HTTP 还是 HTTPS。
- 服务器到浏览器之间是否有 NAT 或负载均衡。
这些信息最容易复现问题,也最容易遗漏。之前遇到过一次 WebRTC 播放失败,排查两小时后发现是安全组只放行了 TCP 端口,UDP 8000 被漏掉了。
7.3 建立自动化验证脚本
手动推流、播放验证只是第一步。如果这个测试环境要被团队反复使用,建议写一个自动化验证脚本,至少完成:
- 检查 SRS 容器是否存活。
- 检查 1935、1985、8080、8000 端口是否监听。
- 用 FFmpeg 推流 10 秒。
- 调用 API 验证流是否存在。
- 清理推流进程。
下面是一个简单的脚本示例:
#!/bin/bash SRS_IP="192.168.1.100" SRS_PORT="1935" SRS_API="192.168.1.100:1985" echo "==== 1. 检查 SRS 容器 ====" docker ps | grep srs-rtc || echo "容器未运行" echo "==== 2. 检查端口 ====" ss -lntup | grep -E '1935|1985|8080|8000' echo "==== 3. 推流 10 秒 ====" timeout 10 ffmpeg -f lavfi -re -i testsrc=size=320x240:rate=15 \ -vcodec libx264 -preset ultrafast -tune zerolatency \ -f flv rtmp://${SRS_IP}:${SRS_PORT}/live/livestream echo "==== 4. 查询流状态 ====" curl -s "http://${SRS_API}/api/v1/streams/" | grep livestream || echo "未查到流"脚本不追求复杂,重点是让每个验证步骤可重复、可输出、可交给 CI 使用。
7.4 日志与监控
SRS 启动时如果使用daemon off; srs_log_tank console;,日志会输出到 Docker 标准输出。可以用docker logs查看。如果想持久化日志,可以让 Docker 日志驱动对接文件,或者把容器日志接入团队日志平台。
测试期间建议重点记录:
- 推流开始和结束时间。
- WebRTC 连接建立时间。
- 播放端是否出现丢包。
- 服务器 CPU、内存、带宽占用。
这些数据在做不同流媒体服务器对比时特别有用。
7.5 安全边界
测试环境虽然不直接面对生产用户,但也要注意安全。SRS 的 HTTP API 可以查询和操作流信息,如果暴露到公网,存在被恶意调用风险。建议测试环境只开放必要的端口到内网,或者限制来源 IP。
如果业务最终要对外开放 WebRTC 播放,建议在前端套一层 HTTPS,并在流媒体服务器外层增加鉴权逻辑。不要直接暴露裸 API 到公网。
另外,FFmpeg 推流测试时生成的是合成视频流,不涉及真实用户数据。如果要使用真实视频源,需要注意隐私和数据合规要求,避免将敏感画面传到测试环境。
7.6 国产化操作系统适配注意
部分团队的测试环境会部署在麒麟 V10 等国产化操作系统上。这类系统底层通常是 Linux 内核,Docker 和 FFmpeg 的部署思路与 CentOS 基本一致。需要特别注意两点:
第一,国产化系统的软件源可能不像 CentOS/Ubuntu 那么通用,安装 Docker、FFmpeg 时可能遇到包缺失或源不可用的问题,建议提前准备好离线安装包或镜像仓库代理。
第二,防火墙管理工具可能不是firewalld,而是iptables或者厂商自研安全组件。配置 UDP 放行时要先确认使用哪种工具,不要照搬 CentOS 文档。
整体上,先在内网测试机验证 Docker 可用性,再进入 rtmp2webrtc 链路调试,可以减少很多环境类问题。
8. 总结与下一步
到这里你已经掌握了一条完整的 rtmp2webrtc 测试环境搭建路径:从 RTMP 与 WebRTC 的概念差异,到 SRS 的 Docker 启动、自定义配置、FFmpeg 推流、浏览器 WebRTC 播放,再到常见问题的排查思路。
如果你用本文的配置顺利跑通了第一条 WebRTC 播放链路,下一步可以继续研究三件事:一是 SRS 的 HTTPS/WSS 配置,让公网环境下播放更稳定;二是用 ZLMediaKit 做多协议对比测试,评估不同流媒体服务器的资源占用;三是设计并发播放压测脚本,用不同路数和码率测试服务器的承载能力。
无论你的最终目标是直播低延迟方案选型,还是给现有 RTMP 业务增加 WebRTC 播放能力,先把测试环境的链路跑通、把 candidate 和 UDP 端口这类基础问题摸清楚,后面真正做生产架构时就会顺利很多。