RTSP与RTMP协议深度解析 使用ffmpeg构建低延迟摄像头RTSP推流方案
1. RTSP与RTMP协议的本质区别第一次接触流媒体协议时我也曾被RTSP和RTMP搞得晕头转向。这两种协议就像快递行业的顺丰和京东虽然都能送货传输视频流但运作模式完全不同。RTSP更像是个精准控制的遥控器而RTMP则像条高速传输带。RTSP协议的工作流程特别像我们打电话先拨号建立连接DESCRIBE请求确认对方身份SETUP建立会话然后才开始正式通话PLAY播放。我在测试时发现个有趣现象用Wireshark抓包能看到RTSP的每个控制命令都是明文传输就像在聊天窗口打字一样直观。底层传输通常采用RTP over UDP这种组合就像用摩托车送快递——速度飞快但偶尔会丢件。实际项目中遇到网络抖动时确实会出现画面卡顿但很快恢复的情况。RTMP协议则像条流水线直接把视频数据切成小块传输。我最早做直播项目时RTMP的稳定性让人印象深刻。它默认使用TCP传输就像用集装箱卡车送货虽然速度不如摩托车快但保证每件货物都完好无损。测试数据显示在相同网络环境下RTMP的延迟通常在2-3秒而RTSP可以做到1秒内。不过RTMP有个致命伤——随着Flash的淘汰现在浏览器基本都不再原生支持了。2. 协议选择的实战经验去年给某工厂做安防监控时我深刻体会到协议选择不能只看技术参数。客户要求延迟必须低于500ms这直接排除了RTMP方案。但纯RTSP方案又遇到浏览器兼容问题最后我们不得不开发定制客户端。监控类项目首选RTSP这点在多次实践中得到验证。有次测试海康威视摄像头时RTSP的实时性让客户当场拍板——画面里的秒针跳动和现实完全同步。但有个坑要注意不同厂家的RTSP地址格式可能不同比如海康是rtsp://[username]:[password][ip]:[port]/...而大华则是rtsp://[ip]:[port]/cam/realmonitor?channel1subtype0。直播带货这类场景还是RTMP更合适。记得有次帮电商客户调试RTMP的稳定性完美应对了突发流量。关键技巧是搭配CDN使用我们通过设置多个边缘节点把延迟控制在可接受范围内。实测数据显示优化后的RTMP链路延迟能控制在2秒左右这对直播带货完全够用。3. FFmpeg推流全攻略第一次用FFmpeg推流摄像头时我对着黑屏折腾了一整天。后来才发现是Windows摄像头名称里有特殊符号。这里分享个实用命令可以列出所有可用摄像头ffmpeg -list_devices true -f dshow -i dummyLinux环境下更简单直接用video4linux2驱动ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -f rtsp rtsp://localhost:8554/mystream推流参数调优是个技术活。经过数十次测试我总结出这套黄金组合ffmpeg -f dshow -i videoUSB Camera -vcodec libx264 -preset ultrafast -tune zerolatency -bufsize 1000k -maxrate 1500k -g 30 -r 25 -pix_fmt yuv420p -f rtsp rtsp://server:8554/stream参数说明-preset ultrafast牺牲画质保速度-tune zerolatency关闭延迟缓冲-bufsize和-maxrate要配套设置-g设置关键帧间隔太小影响画质太大会增加延迟4. 延迟优化的血泪史刚开始做低延迟推流时14秒的延迟让我差点崩溃。经过三个月摸索终于把延迟压到800ms以内。最关键的是发现TCP协议导致的缓冲问题改用UDP后立竿见影-rtsp_transport udp但UDP在复杂网络环境会丢包我们开发了智能切换方案先用UDP探测发现丢包严重时自动切回TCP。实测数据显示在5%丢包率下UDP方案的延迟比TCP低87%。抽帧策略是另一个突破点。最初每帧都处理结果CPU直接飙满。后来改成选择性解码while True: ret cap.grab() # 只取不解码 if frame_count % 3 0: ret, frame cap.retrieve() # 真正解码 # 处理帧 frame_count 1这个改动让处理速度提升3倍延迟从3秒降到800ms。配合硬件加速效果更好用NVIDIA显卡的NVENC编码器延迟还能再降30%-vcodec h264_nvenc5. RTSP服务器搭建实战rtsp-simple-server是我用过最轻量的解决方案50MB内存就能跑起来。配置文件中这几个参数最关键rtspPort: 8554 protocols: [tcp, udp] readTimeout: 10s writeTimeout: 10s有次客户现场没外网我们直接用树莓派搭建服务端。运行命令很简单./rtsp-simple-server但要长期运行得用systemd托管[Unit] DescriptionRTSP Server Afternetwork.target [Service] ExecStart/path/to/rtsp-simple-server Restartalways [Install] WantedBymulti-user.target遇到高并发时记得调优内核参数sysctl -w net.core.rmem_max16777216 sysctl -w net.core.wmem_max167772166. 浏览器播放的终极方案RTSP在浏览器播放是个老大难问题。我们最终采用WebSocket转协议方案服务端把RTSP转成WebSocket流前端用jsmpeg播放。核心代码如下var player new JSMpeg.Player(ws://localhost:8080, { canvas: document.getElementById(video-canvas) })还有个取巧的办法是用FFmpeg转HLSffmpeg -i rtsp://server/stream -c copy -f hls -hls_time 2 -hls_list_size 5 stream.m3u8但HLS延迟通常在10秒以上。最近我们在测试WebRTC方案延迟可以压到1秒内不过实现复杂度高很多。7. 避坑指南踩过最深的坑是时间戳问题。有次客户反馈画面卡顿查了三天发现是FFmpeg命令少了-use_wallclock_as_timestamps 1参数。正确写法ffmpeg -use_wallclock_as_timestamps 1 -f dshow -i videoCamera ...音频同步也是个雷区。如果视频流不带音频必须添加空音频流-f lavfi -i anullsrc防火墙配置经常被忽略。记得开放TCP/UDP端口还有ICMP协议用于网络探测。在AWS上遇到过安全组没放行UDP端口导致连接时好时坏。