WebRTC转RTMP测试环境搭建:SRS+Docker完整实战指南
做低延迟直播或者实时互动项目时,很多团队会遇到一个很典型的问题:浏览器端使用 WebRTC 推流,延迟低、免插件、秒开体验好;但下游的 CDN、云直播平台或传统播放器却常常只认 RTMP 流。两边“方言”不通,就需要在中间搭一个转换网关,把 WebRTC 的传输媒体转换成 RTMP 协议输出。这个问题困扰过不少刚接触流媒体开发的同学,网上资料又分散。本文就把“webrtc2rtmp 测试环境”整套链路整理成一份可直接照做的教程,从协议原理讲到容器化部署,再把常见坑点一次说清楚。
1. 为什么要搭 WebRTC 转 RTMP 测试环境
1.1 两个协议各自的定位
WebRTC 是一套浏览器原生支持的实时音视频通信能力集合,底层使用 SRTP 加密媒体包,默认走 UDP 传输,配合 ICE、DTLS、SCTP 等机制完成连接建立和数据收发。它的优势在于端到端延迟极低,通常在几百毫秒以内,非常适合视频会议、连麦、在线课堂这类强互动场景。
RTMP 则是 Adobe 推出的老牌直播协议,基于 TCP 长连接,封装的是 FLV 流。它在直播行业沉淀了十几年,几乎所有 CDN、云直播服务商、播放器软件都支持 RTMP 推流,兼容性极强。虽然延迟比 WebRTC 高一些,通常在 1 到 3 秒,但胜在稳定成熟、接入成本低。
所以,实际项目中往往出现“浏览器用 WebRTC 推流做低延迟采集,但最终要进入 RTMP 生态供大规模分发播放”的需求。webrtc2rtmp 就是连接这两套生态的桥梁。
1.2 测试环境解决什么问题
在生产环境做协议对接之前,我们需要先在一个隔离的测试环境里验证链路是否通。具体来说,测试环境可以解决以下几个问题:
- 验证 WebRTC 推流地址、RTMP 拉流地址是否能正常建立连接;
- 验证转封装后的画面、音频是否能被下游播放器识别;
- 验证端口、防火墙、网络策略是否满足要求;
- 为后续接入 CDN、云直播平台提供本地排错基础。
很多人一开始直接拿着测试机去对接生产 CDN,一旦拉流失败,根本分不清是 CDN 配置问题、网络问题,还是协议转换的问题。所以先搭建一套本地 webrtc2rtmp 测试环境,把链路跑通,再进入下一步,会稳妥很多。
2. 核心链路与协议转换原理
2.1 WebRTC 推流和拉流需要注意什么
WebRTC 本身不区分“推流”和“拉流”两个协议,而是通过 SDP 协商双方的角色。普通话筒端调用
getUserMedia
采集音视频,再通过
RTCPeerConnection
添加轨道,这个过程通常叫推流。浏览器或播放器端收到远端轨道并渲染,这个过程通常叫拉流。
但要注意,WebRTC 是端到端模型,如果没有信令服务器和媒体服务器,浏览器之间无法直接互连。因此在 webrtc2rtmp 的场景里,我们需要一个媒体服务器来接收浏览器的 WebRTC 流,再由媒体服务器转封装后以 RTMP 协议推出去。
这里需要澄清一个概念:webrtc2rtmp 通常不需要重新转码视频编码,而主要是转封装。WebRTC 常见的视频编码是 H.264,音频编码是 Opus;RTMP 常见视频编码是 H.264,音频编码是 AAC。如果双方视频编码一致,那么视频轨道可以直接转封装,但音频轨道如果从 Opus 转为 AAC,就需要考虑音频转码能力。这是后面排错时最容易忽略的地方。
2.2 协议转换的完整步骤
一条标准的 webrtc2rtmp 链路可以拆成以下几步:
- 浏览器采集摄像头和麦克风,得到本地音视频轨道;
- 浏览器与媒体服务器建立 WebRTC 连接,通过 SRTP 上传音视频数据;
- 媒体服务器收到 WebRTC 流,进行解封装;
- 媒体服务器将 H.264 视频重新封装为 FLV,并将音频按需转换为 AAC;
- 媒体服务器以 RTMP 推流模式连接下游 RTMP 服务或者直接对外提供 RTMP 输出;
-
播放器通过
rtmp://地址拉流播放。
在这条链路里,媒体服务器承担了信令、媒体转发、转封装、RTMP 输入输出等多重角色。常见的选择有 SRS、ZLMediaKit、MediaMTX、Ant Media Server 等。本文的实战部分以 SRS 为例,因为它的 Docker 镜像使用方便,WebRTC 和 RTMP 支持都比较完整。
3. 测试环境搭建前期准备
3.1 硬件与操作系统要求
webrtc2rtmp 测试环境不需要很高配置,普通的 Linux 服务器、虚拟机甚至本机 Docker 都可以跑。如果只是本机验证,建议使用 Linux 系统或者 macOS;如果使用 Windows,也可以通过 Docker Desktop 完成,但要注意 WebRTC 的 UDP 端口映射和防火墙设置。
本文示例以 Linux + Docker 为主。这样做的好处是环境隔离、部署快速、清理方便,不会污染宿主机。
3.2 端口规划
在搭建之前,建议先规划好测试环境的端口,避免后面排查时手忙脚乱。SRS 默认使用以下端口:
| 端口 | 协议 | 用途 |
|---|---|---|
| 1935 | TCP | RTMP 推流与拉流 |
| 1985 | TCP | HTTP API 接口 |
| 8080 | TCP | HTTP 服务器 / 演示页面 |
| 8000 | UDP | WebRTC 媒体传输 |
其中
8000/udp
是 WebRTC 媒体流的关键端口,很多人在测试时只开放了 TCP 端口,导致 WebRTC 推流一直失败。搭建测试环境时,一定要保证 UDP 端口可通。
3.3 安装 Docker
如果还没有安装 Docker,可以用以下命令快速安装(Ubuntu/Debian 系):
sudo apt update
sudo apt install -y docker.io docker-compose
sudo systemctl enable docker
sudo systemctl start docker
CentOS/RHEL 系可以用:
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-compose-plugin
sudo systemctl enable docker
sudo systemctl start docker
版本不需要刻意追求最新,能正常拉取镜像、运行容器即可。如果你使用的是其他操作系统,按对应平台的 Docker 安装文档操作就行。
4. 完整实战:用 SRS 搭建 webrtc2rtmp 测试环境
4.1 拉取镜像并启动 SRS
SRS(Simple Realtime Server)是国产开源流媒体服务器,支持 RTMP、WebRTC、HLS、HTTP-FLV 等多种协议。它的 Docker 镜像使用非常方便,一条命令就能启动一个带 WebRTC 能力的服务。
先创建独立的测试目录:
mkdir -p ~/webrtc2rtmp-test
cd ~/webrtc2rtmp-test
然后直接运行容器。假设你的服务器 IP 是局域网地址,例如
192.168.1.10
,那启动命令如下:
docker run --rm -it \
-p 1935:1935 \
-p 1985:1985 \
-p 8080:8080 \
-p 8000:8000/udp \
-e CANDIDATE=192.168.1.10 \
ossrs/srs:5
如果你是纯本机测试,可以把
CANDIDATE
设为
127.0.0.1
:
docker run --rm -it \
-p 1935:1935 \
-p 1985:1985 \
-p 8080:8080 \
-p 8000:8000/udp \
-e CANDIDATE=127.0.0.1 \
ossrs/srs:5
这里
CANDIDATE
是 WebRTC ICE 协商时需要告知浏览器的服务器公网或局域网 IP。如果配置错误,浏览器可能一直停留在 connecting 状态。
4.2 验证 SRS 服务是否正常
容器启动后,可以通过 HTTP API 检查服务状态:
curl http://localhost:1985/api/v1/versions
如果正常,会返回类似下面的 JSON:
{
"code": 0,
"server": "SRS/5.0",
"version": "5.0.x"
}
也可以用浏览器访问
http://localhost:8080/
查看 SRS 自带的演示页面。不同小版本页面地址可能有差异,但一般都有 WebRTC 推流和播放的 demo 入口。如果页面打不开,优先检查 8080 端口是否被占用,以及容器是否还在运行。
4.3 浏览器端 WebRTC 推流
SRS 自带的演示页面承担了信令服务器的角色,我们不需要另外写信令服务。在浏览器打开 SRS 的 WebRTC 演示页面,进入推流/播放相关入口,根据页面提示填写或选择默认参数,点击开始推流。
如果没有现成的页面入口,也可以直接使用 SRS 支持的 WebRTC 推流地址格式:
webrtc://192.168.1.10/live/livestream
在页面或者自定义前端中把推流地址设置成上面的格式,然后授权摄像头和麦克风。浏览器会先获取本地媒体流,再通过 WebRTC 与 SRS 建立连接,开始上传。
这里需要注意:浏览器只有在
localhost
或
HTTPS
环境下才会授予摄像头和麦克风权限。如果你用 IP 访问测试页面,请确认页面是通过 HTTPS 提供的,或者直接使用
127.0.0.1
访问。
推流成功后,SRS 的控制台日志中会出现推流记录,浏览器页面也会显示本地预览和推流状态。此时我们可以认为 WebRTC 推流这半条链路已经通了。
4.4 验证 RTMP 输出链路
WebRTC 推流成功之后,SRS 已经将收到的流转封装为 RTMP 流输出。在测试机上用 ffplay 拉流验证:
ffplay -i rtmp://127.0.0.1:1935/live/livestream
如果没有安装 ffplay,也可以用 VLC 打开同一个地址:
rtmp://127.0.0.1:1935/live/livestream
如果播放器能正常出画面、有声音,说明 webrtc2rtmp 整条链路已经跑通。
如果只想验证 RTMP 服务本身是否正常,可以先用 ffmpeg 推一路普通的 RTMP 流:
ffmpeg -re -i sample.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/test
然后用播放器打开
rtmp://127.0.0.1:1935/live/test
。如果能播放,说明 RTMP 端口没有问题,问题就集中在 WebRTC 一侧。
4.5 用 Docker Compose 固化测试环境
实际工作中,直接跑一条
docker run
命令虽然方便,但参数多,不容易维护。更推荐用 Docker Compose 把测试环境固化下来。
在
~/webrtc2rtmp-test
目录下创建
docker-compose.yml
:
services:
srs:
image: ossrs/srs:5
container_name: srs-webrtc2rtmp
restart: unless-stopped
ports:
- "1935:1935"
- "1985:1985"
- "8080:8080"
- "8000:8000/udp"
environment:
- CANDIDATE=192.168.1.10
volumes:
- ./srs.conf:/usr/local/srs/conf/srs.conf:ro
如果你需要自定义 SRS 配置,可以准备一份
srs.conf
并挂载进容器。例如把 RTMP 和 WebRTC 端口明确写出来:
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;
}
vhost __defaultVhost__ {
rtc {
enabled on;
}
}
配置中的路径和参数需要根据你实际使用的 SRS 版本调整。保存后用下面的命令启动:
docker compose up -d
这样后续重新搭建测试环境就非常快,团队成员之间也能通过一份 compose 文件保持环境一致。
5. 备选方案:Nginx RTMP 和 Node Media Server
5.1 Nginx RTMP 快速启动
SRS 是 webrtc2rtmp 场景里比较省心的方案。但如果你只是想单独搭一个 RTMP 测试地址,用于验证 RTMP 推流和拉流,那么 Nginx RTMP 模块也很常用。
基于 Docker 的启动方式:
docker run -d \
-p 1935:1935 \
-p 8080:80 \
-v /path/to/nginx.conf:/etc/nginx/nginx.conf:ro \
--name nginx-rtmp \
alfg/nginx-rtmp
其中
nginx.conf
至少需要包含以下配置:
worker_processes auto;
events {
worker_connections 1024;
}
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
启动后,RTMP 测试地址就是:
rtmp://127.0.0.1:1935/live/test
用 ffmpeg 推流:
ffmpeg -re -i sample.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/test
用播放器拉流:
ffplay -i rtmp://127.0.0.1:1935/live/test
Nginx RTMP 本身不能直接接收 WebRTC 推流,它只负责 RTMP 一侧。如果你需要把 WebRTC 流推到 Nginx RTMP,前面仍然要有一个协议转换层,比如 SRS 或 ZLMediaKit,先把 WebRTC 转成 RTMP 再推到 Nginx RTMP。
5.2 Node Media Server 搭建 RTMP 服务
Node Media Server 是一个基于 Node.js 的开源流媒体服务器,支持 RTMP、HTTP-FLV、HLS,也能通过插件实现 WebRTC 播放。它的特点是安装简单,适合快速验证。
创建测试目录:
mkdir -p ~/nms-test
cd ~/nms-test
npm init -y
npm install node-media-server
创建
app.js
:
const NodeMediaServer = require('node-media-server');
const config = {
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 30,
ping_timeout: 60
},
http: {
port: 8000,
mediaroot: './media',
allow_origin: '*'
},
auth: {
play: false,
publish: false
}
};
const nms = new NodeMediaServer(config);
nms.run();
启动:
node app.js
然后同样用 ffmpeg 推流测试,RTMP 测试地址仍然是:
rtmp://127.0.0.1:1935/live/test
Node Media Server 更适合快速搭一个 RTMP 服务来模拟下游接收端,但它的 WebRTC 推流原生支持有限,所以不推荐把它作为 webrtc2rtmp 的转换主力。
5.3 如何选择
如果你需要一条链路同时支持 WebRTC 推流和 RTMP 输出,最推荐 SRS 或 ZLMediaKit。如果你已经有一个 RTMP 接收端,只是想验证推流地址通不通,那么 Nginx RTMP 或 Node Media Server 就够了。
测试环境的搭建目标不是“用最炫的架构”,而是用最小成本把链路验证清楚。因此建议先跑通 SRS 方案,再按需引入 Nginx RTMP 或 Node Media Server。
6. 常见问题与排查思路
6.1 问题排查表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 浏览器一直 connecting,推不上流 | UDP 8000 端口不通 | 检查防火墙、安全组,确认 UDP 端口开放 |
| 本机可以推流,局域网其他机器不行 | CANDIDATE 配置成了 127.0.0.1 | 改为服务器实际局域网 IP |
| 页面打不开摄像头 | 使用了非 HTTPS 环境访问 | 使用 localhost 或配置 HTTPS |
| 画面正常但没有声音 | WebRTC 使用 Opus,RTMP 常用 AAC | 推流端改用 AAC 或增加音频转码 |
| ffplay 拉流黑屏 | RTMP 端口未通或流名不匹配 | 确认流名与推流时一致,检查 1935 端口 |
| 推流结束后播放端有缓存画面 | 启用了 GOP cache | 测试环境可关闭 gop_cache,观察效果 |
6.2 推流失败排查思路
如果你遇到 WebRTC 推流失败,可以按下面的顺序排查:
-
先确认浏览器控制台是否有
ICE相关报错,如果出现ice connection failed,说明浏览器到服务器之间 UDP 不通。 - 在服务器上执行命令,确认 SRS 容器是否正常运行,1985 端口是否能返回版本信息。
-
检查防火墙是否放行了 UDP 8000 端口:
sudo ufw status sudo iptables -L -n | grep 8000 -
检查
CANDIDATE环境变量是否设置为浏览器能够访问到的 IP。本机测试用127.0.0.1,局域网测试用局域网 IP,公网测试用公网 IP。
6.3 声音问题的处理思路
如果你的业务对声音有强需求,建议在一开始就明确音频编码。WebRTC 默认优先使用 Opus 音频编码,而很多 RTMP 服务端和播放器更熟悉 AAC。SRS 在转封装时如果遇到 Opus 音频,可能需要额外的转码链路支持,否则可能出现无声或者播放器不兼容。
在测试环境中,可以先用视频流验证整体链路,确认视频通路正常后,再单独排查音频问题。如果音频始终有问题,可以考虑在推流端配置浏览器优先使用 AAC 音频,或者部署 SRS 的转码能力,把 Opus 转成 AAC。生产环境还需要根据 CDN 的音频编码要求做匹配。
6.4 弱网卡顿怎么优化
WebRTC 自带拥塞控制和弱网对抗机制,包括 FEC 前向纠错、NACK 丢包重传、码率自适应等。在 webrtc2rtmp 测试环境里,如果遇到弱网卡顿,可以从以下几个方面调整:
- 限制 WebRTC 发送码率上限,避免上行带宽被占满;
- 调整分辨率与帧率,降低带宽压力;
- 在浏览器端设置合理的码率控制参数;
- 如果是 Wi-Fi 环境,尽量使用 5GHz 频段或者有线网络;
-
用 Linux
tc命令或 Windows Clumsy 工具模拟弱网,验证卡顿在哪个环节发生。
需要明确的是,WebRTC 推流侧的弱网优化只能改善浏览器到媒体服务器这一段,RTMP 下行到播放器的卡顿需要依靠 CDN 和播放器缓冲策略来解决。因此在联调时,要分清卡顿发生在推流段还是拉流段。
7. 最佳实践与工程建议
7.1 端口最小化开放
测试环境虽然可以放开所有端口,但建议仍然遵循最小开放原则。只开放必要的 TCP 1935、1985、8080 和 UDP 8000,其他端口一律不开放。特别是不要让 SSH、数据库等端口暴露到无约束网络,避免安全隐患。
7.2 配置统一且可回滚
把 SRS 的启动参数、配置文件、Docker Compose 文件统一纳入代码仓库,标注清楚测试环境地址和端口。当配置变更后,保留历史版本,方便快速回滚。避免在服务器上手工改文件导致环境不可复现。
7.3 HTTPS 尽早纳入测试范围
浏览器 WebRTC 权限对 HTTPS 有硬性要求。如果你的测试环境最终要面向局域网或公网用户,建议尽早把 HTTPS 纳入测试范围。可以使用自签名证书或者内网 CA,只要能模拟正式环境的安全策略即可。否则到了联调阶段才发现权限问题,会浪费不少时间。
7.4 日志与监控
启动 SRS 容器时,尽量把日志输出到控制台或者按天分割的日志文件。出现推流失败时,日志能帮助你快速定位 ICE 协商、RTMP 发布等环节的问题。如果团队成员较多,还可以为测试环境加一个简单的统一日志查看入口。
7.5 明确转封装与转码的成本边界
很多刚接触流媒体的人会把 webrtc2rtmp 理解成“转码”,实际上视频轨道大概率不需要转码,只需要转封装。转封装是轻量操作,CPU 消耗低。但如果真的遇到编码格式不匹配,比如 H.265 视频或者 Opus 音频需要转成 H.264/AAC,那就变成了转码,CPU 和延迟都会明显上升。在测试环境里提前确认编码格式,能帮助你在生产方案选型时避开不必要的转码开销。
7.6 利用测试环境模拟下游 CDN
测试环境不只是用来验证本地播放器,也可以用来模拟 CDN 链路的多个环节。例如先让 SRS 推到 Nginx RTMP,再从 Nginx RTMP 拉流验证,模拟“WebRTC 推流 -> 中间转换 -> 边缘节点 -> 播放器”的完整链路。这样做可以在上线前发现很多架构层面潜在问题。
8. 总结与下一步学习建议
到这里,你的本机 or 局域网测试机上已经有了一个可运行的 webrtc2rtmp 测试链路:浏览器通过 WebRTC 推流到 SRS,SRS 转封装为 RTMP 后由播放器拉流验证。核心步骤概括下来就是:规划端口、启动 SRS、配置正确的 CANDIDATE、浏览器推流、播放器验证 RTMP。
后续想深入的话,可以沿着几个方向继续学习:一是理解 WHIP 这类 WebRTC 推流标准协议,了解它和传统 WebRTC 信令的区别;二是研究 SRS 的转码能力,掌握 Opus 转 AAC、H.265 转 H.264 等场景下的配置方法;三是尝试把测试链路的 SRS 输出接入真实 CDN 或云直播平台,并在生产环境里验证鉴权、断流重推、延迟监控等细节。
建议你先把本文的流程在自己的测试机上完整跑一遍,再换真实 IP 和 HTTPS 环境验证一次。只有亲手解决了 ICE 协商、UDP 端口、音频编码这几个典型问题,后续做正式直播项目时才会更从容。
火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)