4、RTSP服务器搭建:使用Live555搭建RTSP服务器、配置与测试、常见问题排查

好,这一章我们动手搭一个真正的RTSP服务器。我选Live555,原因很简单——它轻量、稳定,而且几乎所有RTSP客户端都能跟它对接。你在网上看到的很多IP摄像头演示,背后跑的就是它。

说白了,Live555就是一个C++写的流媒体服务库。它把RTSP协议、RTP打包、媒体文件解析这些脏活都干了。我们只需要告诉它:媒体文件在哪,端口开多少,剩下的它自己搞定。

核心思路: Live555作为RTSP Server,接收客户端的DESCRIBE/SETUP/PLAY请求,然后通过RTP把H.264或AAC数据推给客户端。WebRTC要跟它融合,第一步就是让Live555先把流发出来。

Live555 RTSP 服务器架构 媒体文件 .264 / .aac / .mp3 解复用器 MPEG2TransportStreamFramer RTSP Server核心 RTSPServer / ServerMediaSession RTSPClientConnection RTP over UDP/TCP 端口 5000-5050 / 554 RTSP客户端 关键流程 1. 客户端发送OPTIONS 2. 服务端回复支持的指令 3. DESCRIBE → SETUP → PLAY

4.1 编译与安装Live555

我习惯直接从源码编译。别怕,步骤很简单。Live555的源码包在官网就能下,或者用git拉一份。

# 下载源码
wget http://www.live555.com/liveMedia/public/live555-latest.tar.gz
tar -xzf live555-latest.tar.gz
cd live

# 编译
./genMakefiles linux
make -j$(nproc)

# 安装(可选,我一般直接用编译目录)
sudo make install

编译完你会看到几个可执行文件:live555MediaServer、testRTSPClient、testH264VideoStreamer 等等。我们主要用 live555MediaServer 和 testH264VideoStreamer。

我的习惯: 不执行 make install,直接在编译目录里跑。这样换版本方便,删掉目录重新编译就行,不会污染系统。

4.2 快速启动一个RTSP流

Live555自带了一个媒体服务器,你只需要把媒体文件丢进去,它自动就能提供服务。

# 把H.264文件放到当前目录
cp test.264 ./

# 启动服务器
./live555MediaServer

# 默认监听端口 8554
# 访问地址:rtsp://192.168.1.100:8554/test.264

就这么简单。服务器启动后,它会扫描当前目录下的媒体文件,自动创建对应的RTSP URL。客户端连上来,它就开始推流。

但说实话,live555MediaServer 功能有限。它只能播文件,不能处理实时流。如果你需要把摄像头或编码器的实时数据推出去,得用 testH264VideoStreamer 这类程序。

4.3 自定义推流:testH264VideoStreamer

这个程序可以从文件读取H.264数据,然后通过RTSP推出去。它的源码在 testProgs/ 目录下,你可以直接改。

# 用法
./testH264VideoStreamer <H264文件> <端口号>

# 示例:推流 test.264,端口 8554
./testH264VideoStreamer test.264 8554

# 客户端访问
ffplay rtsp://192.168.1.100:8554/h264ESVideoTest

这里有个坑——h264ESVideoTest 是程序里硬编码的流名称。如果你想改,得改源码重新编译。

注意: testH264VideoStreamer 默认只支持H.264裸流(Annex B格式)。如果你的文件是MP4或TS封装,需要先解封装。我遇到过有人拿MP4直接喂进去,结果花屏——因为MP4里的H.264有起始码偏移。

4.4 配置参数详解

Live555的配置主要通过源码里的 config.* 文件。但日常使用,我们更关心运行时参数。

参数 默认值 说明
RTSP端口 8554 主端口,客户端连接用
RTP起始端口 5000 每个流占用两个端口(RTP+RTCP)
RTP端口范围 5000-5050 最多支持25个并发流
HTTP隧道端口 80 用于防火墙穿透
多播TTL 255 多播时有效

这些参数在 live555MediaServer 里是写死的。如果你要改,得改 DynamicRTSPServer.cpp 里的端口范围。

4.5 测试与验证

服务器跑起来后,怎么知道它工作正常?我一般用三步验证法。

  1. telnet 测试: 先看端口通不通
  2. ffplay 播放: 直接拉流看画面
  3. Wireshark 抓包: 看RTSP交互是否完整
# 第一步:端口测试
telnet 192.168.1.100 8554
# 如果连接成功,会看到空白界面,按 Ctrl+] 退出

# 第二步:ffplay 播放
ffplay -rtsp_transport tcp rtsp://192.168.1.100:8554/h264ESVideoTest

# 第三步:抓包分析
# 在Wireshark里过滤 rtsp or rtp
# 重点关注 OPTIONS → DESCRIBE → SETUP → PLAY 的交互

如果ffplay能正常出画面,说明服务器没问题。如果卡住或花屏,八成是文件格式或编码参数不对。

我的经验: 用ffplay测试时加 -v debug 参数,能看到详细的SDP信息和RTP包序号。我曾经靠这个发现一个摄像头发的RTP时间戳是乱的——每帧时间戳都一样,导致播放器以为只有一帧。

4.6 常见问题排查

这部分我踩过的坑比较多,列几个典型的。

4.6.1 客户端连不上服务器

最常见的原因:防火墙。Live555默认用UDP端口5000-5050,很多云服务器或公司网络会封这些端口。

# 临时关闭防火墙测试
sudo ufw disable

# 或者开放端口
sudo ufw allow 8554/tcp
sudo ufw allow 5000:5050/udp

如果防火墙没问题,检查服务器是否真的在监听:

netstat -tulpn | grep 8554

4.6.2 播放花屏或绿屏

这个问题我遇到过好几次。原因通常是H.264文件的SPS/PPS信息丢失或不对。

Live555在DESCRIBE回复的SDP里会包含SPS/PPS。如果文件里没有这些信息,客户端就不知道怎么解码。

# 检查文件是否包含SPS/PPS
ffprobe -show_packets test.264 | grep -E "sps|pps"

# 如果没有,手动添加
# 用工具提取SPS/PPS,或者重新编码时加上

我曾经踩过的坑: 有一次从摄像头拿到的H.264流,SPS里把分辨率写成了1920x1080,但实际视频只有1280x720。结果播放器按1920x1080解码,画面拉伸变形。排查了半天才发现是SPS参数不对。

4.6.3 RTP时间戳不同步

如果你推的是音视频混合流,音频和视频的RTP时间戳必须基于同一个时钟。Live555默认用90000Hz作为视频时间戳基准,音频用采样率。如果两个流的时间戳基准不一致,播放器会音画不同步。

解决办法:在 StreamParser.cpp 里统一时间戳基准,或者用 gettimeofday 生成绝对时间戳。

4.6.4 多客户端并发问题

Live555默认支持最多25个并发客户端(因为RTP端口只有25对)。如果你需要更多,得改端口范围。

// 在 DynamicRTSPServer.cpp 里修改
#define RTP_PORT_MIN 5000
#define RTP_PORT_MAX 6000  // 改成1000对端口

但注意,每个客户端会占用一对UDP端口。如果客户端用TCP模式(-rtsp_transport tcp),端口占用会少一些。

4.7 性能调优建议

Live555本身性能不错,但有些场景需要调优。

场景 建议
高并发(>50路) 改用TCP模式,减少UDP端口占用
低延迟(<200ms) 减小RTP包大小(默认1400字节),降低缓冲
跨网传输 开启HTTP隧道,绕过防火墙
多码率适配 需要自己实现多码率逻辑,Live555原生不支持

嗯,说到多码率,Live555确实不支持。如果你需要自适应码率,得在应用层自己做。我们后面章节会讲怎么用WebRTC的Simulcast来实现类似效果。

总结一下: Live555搭建RTSP服务器不难,难的是把流稳定地推出去。文件格式、SPS/PPS、端口配置、时间戳同步——每个环节都可能出问题。但只要你按我上面说的步骤来,大部分坑都能避开。