2. 推流环境准备:FFmpeg编译与安装、推流工具链搭建、测试流媒体服务器部署
做推流卡顿排查,第一步不是调参数,而是先把环境搭扎实。我见过太多人花了两小时查问题,最后发现是FFmpeg版本不对,或者服务器少了个模块。嗯,这章我们就一次性把这些基础工作做干净。
本章核心目标:搭建一套可复现、可调试的推流实验环境。包括FFmpeg的定制编译、推流工具链的选型与配置、以及本地测试流媒体服务器的部署。
2.1 FFmpeg编译与安装
很多人直接apt-get install ffmpeg就完事了。但做流媒体优化,我建议你从源码编译。为什么?因为发行版自带的FFmpeg往往砍掉了调试符号、禁用了某些编码器,或者版本太老。你想想看,排查卡顿的时候连个--enable-debug都没有,那真是寸步难行。
2.1.1 为什么选择源码编译
- 精细控制模块:可以按需开启/关闭编码器、复用器、协议。比如我只用H.264和AAC,那就只编这两个,减少二进制体积和潜在的依赖冲突。
- 调试符号保留:加上
--enable-debug --disable-optimizations,出问题可以直接gdb attach上去看堆栈。 - 性能优化:可以针对当前CPU架构开启汇编优化(
--enable-x86asm),这在推流场景下能省下不少CPU。
注意:如果你只是临时测试,用静态编译版本也行。但做卡顿排查,我强烈建议你走一遍源码编译流程。我曾经在排查一个诡异的丢帧问题时,发现就是发行版FFmpeg的libx264版本太旧,导致B帧参考关系异常。换成最新源码编译后,问题直接消失。
2.1.2 编译步骤(以Ubuntu 22.04为例)
先装依赖,这一步别偷懒。少了某个库,编译出来的FFmpeg可能就缺了某个关键功能。
# 安装基础编译工具
sudo apt update
sudo apt install -y \
autoconf automake build-essential cmake git \
libass-dev libfreetype6-dev libsdl2-dev libtool \
libva-dev libvdpau-dev libvorbis-dev libxcb1-dev \
libxcb-shm0-dev libxcb-xfixes0-dev pkg-config \
texinfo wget zlib1g-dev
# 安装编码器依赖(H.264 + AAC)
sudo apt install -y libx264-dev libx265-dev libfdk-aac-dev libmp3lame-dev libopus-dev
然后拉取FFmpeg源码,我习惯用git clone,方便后续切分支或回滚。
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
git checkout release/6.0 # 选一个稳定版本
配置环节是关键。下面是我做推流测试常用的配置项:
./configure \
--prefix=/usr/local/ffmpeg \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--enable-debug=3 \
--disable-optimizations \
--enable-libx264 \
--enable-libx265 \
--enable-libfdk-aac \
--enable-libmp3lame \
--enable-libopus \
--enable-libass \
--enable-libfreetype \
--enable-ffplay \
--enable-ffprobe \
--enable-network \
--enable-protocol=tcp,udp,rtmp,http,https \
--enable-filter=aresample,scale,fps,setpts \
--enable-encoder=libx264,libx265,libfdk_aac,aac \
--enable-decoder=h264,aac,hevc \
--enable-muxer=flv,mp4,ts,mpegts \
--enable-demuxer=flv,mp4,ts,mpegts
这里我特别提一下--enable-debug=3和--disable-optimizations。调试时这两个选项能让你看到完整的变量值和函数调用链。当然,性能会差一些,但排查阶段无所谓。
编译和安装:
make -j$(nproc)
sudo make install
验证安装:
/usr/local/ffmpeg/bin/ffmpeg -version
# 输出中应包含 --enable-libx264 --enable-libfdk-aac 等字样
小技巧:把/usr/local/ffmpeg/bin加到PATH里,避免和系统自带的FFmpeg冲突。我一般在~/.bashrc里加一行export PATH=/usr/local/ffmpeg/bin:$PATH。
2.2 推流工具链搭建
光有FFmpeg还不够。推流是一个链条:采集 → 编码 → 封装 → 发送。每个环节都需要对应的工具来验证和调试。下面是我常用的工具链清单。
2.2.1 核心工具清单
| 工具 | 用途 | 安装方式 |
|---|---|---|
| FFmpeg | 推流主体,负责编码和发送 | 源码编译(见2.1节) |
| FFprobe | 分析流媒体信息,查看编码参数、帧率、码率 | 随FFmpeg一起编译 |
| FFplay | 本地播放测试流,验证推流效果 | 随FFmpeg一起编译 |
| OBS Studio | 图形化推流工具,用于对比测试 | sudo apt install obs-studio |
| tshark / Wireshark | 抓包分析网络层,排查丢包、延迟 | sudo apt install tshark |
| nload / iftop | 实时监控网卡流量,看推流带宽是否跑满 | sudo apt install nload iftop |
2.2.2 验证工具链是否就绪
写一个简单的测试脚本,确保每个工具都能正常工作:
#!/bin/bash
echo "=== 检查推流工具链 ==="
# 检查FFmpeg
ffmpeg -version &>/dev/null
if [ $? -eq 0 ]; then
echo "[OK] FFmpeg"
else
echo "[FAIL] FFmpeg"
fi
# 检查FFprobe
ffprobe -version &>/dev/null
if [ $? -eq 0 ]; then
echo "[OK] FFprobe"
else
echo "[FAIL] FFprobe"
fi
# 检查抓包工具
tshark --version &>/dev/null
if [ $? -eq 0 ]; then
echo "[OK] tshark"
else
echo "[FAIL] tshark"
fi
echo "=== 检查完成 ==="
个人习惯:我会在每台测试机上跑一遍这个脚本,确保环境一致。曾经有一次排查卡顿,折腾了半天发现是测试机A的FFmpeg版本比测试机B低了两个大版本,导致编码参数解析不一致。从那以后,我坚持用脚本统一校验环境。
2.3 测试流媒体服务器部署
推流总得有个接收端吧?本地测试我推荐用Nginx + RTMP模块,或者SRS(Simple-Rtmp-Server)。SRS功能更全,支持RTMP、HLS、SRT等多种协议,而且配置简单。
2.3.1 部署SRS(推荐)
SRS是我做推流测试的首选。它轻量、稳定,而且日志非常详细,对排查卡顿很有帮助。
# 下载SRS源码
git clone https://github.com/ossrs/srs.git
cd srs/trunk
# 编译(默认开启RTMP + HLS)
./configure
make -j$(nproc)
# 启动服务器
./objs/srs -c conf/srs.conf
启动后,SRS默认监听1935端口(RTMP)和8080端口(HTTP API)。验证是否启动成功:
curl http://localhost:8080/api/v1/versions
# 返回JSON格式的版本信息,说明服务正常
2.3.2 配置SRS用于卡顿测试
默认配置可以直接用,但为了模拟真实推流场景,我建议调整几个参数:
# conf/srs.conf 关键配置项
listen 1935;
max_connections 1000;
daemon off; # 前台运行,方便看日志
srs_log_tank console; # 日志输出到控制台
vhost __defaultVhost__ {
gop_cache off; # 关闭GOP缓存,模拟低延迟场景
hls {
enabled on;
hls_fragment 2; # 每个TS切片2秒
hls_window 6; # 窗口大小6秒
}
}
这里gop_cache off是我做卡顿测试时常用的。关闭GOP缓存后,推流端每发一个关键帧,服务器就立即转发,不会缓存等待。这样能更真实地反映网络抖动对推流的影响。
2.3.3 部署Nginx + RTMP模块(备选)
如果你更习惯Nginx,也可以用这个方案:
# 安装Nginx和RTMP模块
sudo apt install nginx libnginx-mod-rtmp
# 配置RTMP
sudo vim /etc/nginx/nginx.conf
# 在http块外面添加:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
# 重启Nginx
sudo systemctl restart nginx
避坑:Nginx的RTMP模块功能相对基础,不支持HLS切片、SRT协议等高级功能。如果你后续要做HLS卡顿排查,建议直接用SRS。我曾经在Nginx上折腾了半天HLS配置,最后发现是模块不支持,换SRS后十分钟搞定。
2.4 推流环境整体架构
下面这张图展示了我们搭建的推流测试环境全貌。你可以看到数据从采集端到播放端的完整路径,以及每个环节用到的工具。
从架构图可以看出,我们的测试环境覆盖了推流的完整链路。每个环节都有对应的调试工具,这样一旦出现卡顿,我们可以快速定位是采集端的问题、编码端的问题、网络传输的问题,还是服务器端的问题。
2.5 环境验证:跑一个简单的推流测试
环境搭好了,总得跑一下验证吧?下面这个命令会推送一个测试视频到本地SRS服务器:
# 生成一个测试视频源(10秒,30fps,彩色条纹)
ffmpeg -f lavfi -i testsrc2=size=1280x720:rate=30:duration=10 \
-f lavfi -i sine=frequency=440:duration=10 \
-c:v libx264 -preset ultrafast -b:v 2000k \
-c:a aac -b:a 128k \
-f flv rtmp://localhost:1935/live/test
然后在另一个终端用FFplay拉流播放:
ffplay rtmp://localhost:1935/live/test
如果能看到画面和声音,说明整个推流环境已经就绪。嗯,到这里,我们的测试环境就全部搭好了。
个人经验:第一次跑通推流测试时,我建议你同时打开SRS的控制台日志(srs_log_tank console),观察推流过程中的连接建立、数据接收、GOP缓存等日志信息。这些日志在后续排查卡顿时会非常有用。我曾经靠SRS日志里的一条recv timeout信息,定位到一个隐藏了很久的网卡驱动问题。