RTMP 推流 + VLC 拉流 实践步骤
环境:Ubuntu 24.04 + Docker
测试文件:Big Buck Bunny (~/test_project/bbb_sunflower_1080p_30fps_normal.mp4)
核心流程:从视频文件抓取 → FFmpeg 推流 → VLC 拉流验证
前置环境确认
# 1. 确认 BBB 文件存在ls~/test_project/bbb_sunflower_1080p_30fps_normal.mp4# 2. 停掉旧的 SRS 容器(避免端口冲突)dockerstop srs2>/dev/nulldockerrmsrs2>/dev/nullStep 1:启动 SRS 服务
dockerrun--namesrs-d\-p1935:1935\-p1985:1985\-p8080:8080\registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5端口说明:
| 端口 | 用途 |
|---|---|
| 1935 | RTMP 推流/拉流 |
| 1985 | SRS API(调试用) |
| 8080 | HTTP-FLV / HLS 拉流 |
验证启动成功:
dockerps|grepsrs# 看到 Up 状态即正常dockerlogs srs--tail5# 看到 "SRS/5.x.x started" 即成功Step 2:FFmpeg 从 BBB 文件抓取视频,推 RTMP 流
ffmpeg-re\-i~/test_project/bbb_sunflower_1080p_30fps_normal.mp4\-map0:v:0-map0:a:0\-c:vcopy-c:acopy\-fflv\rtmp://localhost:1935/live/bbb参数速查
| 参数 | 作用 | 对应实践动作 |
|---|---|---|
-re | 按视频真实帧率读取文件 | 模拟实时采集(抓取控制) |
-i ~/test_project/bbb...mp4 | 指定要抓取的 BBB 视频文件 | 输入源 |
-map 0:v:0 -map 0:a:0 | 强制选第1个视频轨 + 第1个MP3立体声音轨 | 轨道选择(避坑 AC3) |
-c:v copy -c:a copy | 音视频不重新编码,直接抓取原始数据推送 | 编码控制 |
-f flv | RTMP 协议必须用 FLV 封装 | 输出格式 |
rtmp://localhost:1935/live/bbb | RTMP 服务器地址,bbb是自定义流名 | 推流地址 |
成功标志
终端持续刷帧,speed=1x(按1倍速实时推流):
frame= 1200 fps= 30 q=-1.0 size= 90112kB time=00:00:40.00 bitrate=18432.0kbits/s speed=1xStep 3:VLC 拉 RTMP 流播放
方式 1:VLC 命令行(最直接)
vlc rtmp://localhost:1935/live/bbb方式 2:VLC 图形化
- 打开 VLC → 「媒体」→「打开网络串流」
- 输入 RTMP 拉流地址:
rtmp://localhost:1935/live/bbb - 点击「播放」,看到 Big Buck Bunny 动画即成功
方式 3:VLC 拉 HTTP-FLV 流(备用方案)
vlc http://localhost:8080/live/bbb.flv方式 4:ffplay 快速验证(无需 VLC)
ffplay rtmp://localhost:1935/live/bbbStep 4:停止服务
# 1. 先停推流:在 FFmpeg 运行的终端按 Ctrl+C# 2. 停 SRS 容器dockerstop srs&&dockerrmsrs进阶理解
-re参数的本质:为什么 speed 必须等于 1x
-re让 FFmpeg按视频原始帧率读取文件。30fps 的视频,FFmpeg 每秒只读 30 帧推送。
没有-re会怎样?FFmpeg 会"尽可能快地"读取并推送文件,speed 可能达到几十甚至上百倍,相当于"快进推流":
| 问题 | 具体表现 |
|---|---|
| SRS 缓存被打满 | 推流速度远超播放速度,SRS 接收缓冲区瞬间堆积,触发丢包甚至断开连接 |
| 拉流端播放异常 | 数据涌入速度 > 消费速度 → 缓冲区溢出 → 卡顿、花屏 |
| 失去实时模拟意义 | 工程机械 IPC 是实时产生视频帧的,推流速度必须 = 采集帧率 |
验证方法:观察 FFmpeg 输出中的speed=1.00x指标,接近 1x 即为实时推流。
FLV 容器对音频编码的白名单限制
RTMP 推流要求-f flv,而 FLV 标准的音频编码白名单只有:AAC、MP3、PCM(μ-law/A-law)。
BBB 视频有 2 个音轨:#0:1=MP3(FLV 支持)、#0:2=AC3(FLV 不支持)。FFmpeg 默认可能选中 AC3 音轨导致Audio codec ac3 not compatible报错。-map 0:a:0强制指定第 1 个音频轨(MP3),避开 AC3。
如果要推 AC3 音轨,必须先转码:
-c:a aac(有损),不能只用-c:a copy。
故障排查方法论
| 症状 | 排查工具 | 命令示例 |
|---|---|---|
| 推流失败 | ffprobe分析源文件 | ffprobe -v error -show_streams input.mp4查看音视频轨信息 |
| 推流失败 | docker logs srs | docker logs srs --tail 50查看 SRS 是否收到连接请求 |
| 拉流黑屏 | 浏览器 SRS 控制台 | http://localhost:8080/查看流是否在线 |
| 延迟异常 | FFmpegdrawtext叠加时间戳 | -vf "drawtext=text='%{localtime}':x=10:y=10:fontcolor=white"对比推拉流两端时间 |
| 协议交互异常 | Wireshark 抓包 | 抓 1935 端口看 RTMP connect/publish/onStatus 报文 |
延迟对比测试方法
在 BBB 视频中叠加实时时间戳,对比推流端时间和拉流端显示时间的差值:
ffmpeg-re-ibbb.mp4-map0:v:0-map0:a:0\-c:vcopy-c:acopy\-vf"drawtext=text='%{localtime:%H:%M:%S}':fontsize=48:fontcolor=red:x=10:y=10"\-fflv rtmp://localhost:1935/live/bbb_delay推流端 FFmpeg 日志的时间戳 vs 拉流端 VLC/浏览器画面中显示的时间戳,差值即为端到端延迟。建议对比 RTMP、HTTP-FLV、RTSP 三种协议的延迟差异。
总结
| 项目 | 内容 |
|---|---|
| 服务器 | SRS(Docker 一键启动) |
| 推流协议 | RTMP(-f flv,端口 1935) |
| 拉流协议 | RTMP / HTTP-FLV |
| 视频处理 | 不转码(-c:v copy -c:a copy),纯复制 |
| VLC 兼容性 | ✅ RTMP 和 HTTP-FLV 均完美支持 |
RTMP 是 SRS 最成熟的协议,推流/拉流都走 TCP 单连接,最稳定、最易上手。互联网直播场景的首选。