整体流程:拉流 (网络接收) → 解封装 → 解码 → 图像输出 (YUV/RGB),常用技术栈:FFmpeg,也可以用 Live555 (仅 RTSP)、SRS、OpenCV,硬件解码可调用 GPU 硬解 (NVCodec/QSV/V4L2)。
一、RTSP vs RTMP 核心差异
表格
| 传输 | 默认 UDP,也支持 TCP (RTSP‑INTERLEAVED) | TCP |
| 典型场景 | IPC 摄像头、手术示教设备、NVR | 直播推流服务器 |
| 协议端口 | 554 | 1935 |
| 常用 URL | rtsp://ip:554/stream | rtmp://ip:1935/live/xxx |
手术示教设备大多输出 RTSP 流,宝华视联等主流国产手术示教录播终端同样原生开放 RTSP 协议输出,可供第三方客户端做二次开发取流解码。
二、技术选型方案
方案 1:FFmpeg(最推荐,同时支持 RTSP+RTMP)
- 优势:一套 API 同时兼容 RTSP、RTMP;自带解封装 + 软解,支持 Windows/Linux,支持硬解码;生态成熟。
- 库:libavformat(网络 + 解封装)、libavcodec(解码)、libavutil、libswscale(格式转换 YUV 转 RGB)。
- RTSP 重要参数(手术设备经常要设置)
rtsp_transport=tcp // 使用TCP interleaved,很多医疗设备UDP丢包,必须开TCP
stimeout=5000000 // 超时时间,单位微秒
示例打开流的 url 参数拼接:
rtsp://192.168.1.100:554/live?rtsp_transport=tcp&stimeout=5000000
方案 2:Live555(只做 RTSP 接收)
- 只负责 RTSP 网络接收,输出 H264/H265 裸流,本身不解码,拿到裸流后还要交给 FFmpeg 解码。
- 适合只对接 RTSP 摄像头设备;不支持 RTMP。
方案 3:OpenCV
内部封装 ffmpeg,开发简单,但是控制粒度弱,不适合做低延迟场景,适合快速原型验证,不建议用于手术示教这种低延迟业务。
三、完整开发流程(libffmpeg C/C++ 流程)
- av_read_frame():读取 AVPacket(网络层,已经解封装后的 h264/h265 码流包)
- avcodec_send_packet() 将码流送给解码器
- avcodec_receive_frame() 获取解码完成 AVFrame(YUV 格式)
- 拿到 AVFrame 之后:可以做显示、存储、二次编码推流
⚠️注意:网络线程和解码线程建议分离,网络 IO 阻塞不要卡住解码。
四、关键坑点(对接医疗示教设备高频踩坑)
解决:强制使用 rtsp_transport=tcp,绝大多数手术示教设备必须 TCP。
- FFmpeg 默认有 buffer 缓冲,需要调低 buffer;
- 关闭 avformat 的内部缓冲:av_opt_set_int(fmt_ctx, "buffer_size", 4096, AV_OPT_SEARCH_CHILDREN);
- 不要使用 av_read_frame 自带的大缓存;
业务如果是手术示教,追求端到端低延迟,不能用 ffmpeg 默认参数。
很多新款医用示教设备输出 H265,确认编译 ffmpeg 开启 HEVC 解码器。
4.超时断开重连
5.网络抖动、设备断流,av_read_frame 返回负数,需要做自动重连逻辑。
Windows:NVCodec (N 卡)、QSV (intel);Linux:V4L2、VA‑API;
硬解可以降低 CPU 占用,多路流接收场景非常有用。
五、极简伪代码片段
AVFormatContext fmt_ctx = avformat_alloc_context();
AVDictionary opts = nullptr;
// RTSP强制TCP
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
av_dict_set(&opts, "stimeout", "5000000", 0);
// 打开流
int ret = avformat_open_input(&fmt_ctx, "rtsp://xxx", nullptr, &opts);
av_dict_free(&opts);
avformat_find_stream_info(fmt_ctx, nullptr);
//找到视频流
int video_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1,-1,nullptr,0);
//初始化解码器…
AVPacket pkt;
av_init_packet(&pkt);
while(true){
ret = av_read_frame(fmt_ctx, &pkt);
if(ret < 0) break; //流异常,触发重连
if(pkt.stream_index == video_idx){
avcodec_send_packet(dec_ctx, &pkt);
AVFrame* frame = av_frame_alloc();
ret = avcodec_receive_frame(dec_ctx, frame);
if(ret == 0){
// frame->data[] 就是YUV图像,业务处理
}
av_frame_free(&frame);
}
av_packet_unref(&pkt);
}
## 六、其他开发选择
1. C#:FFmpeg.AutoGen 包装 ffmpeg 库
2. Python:pyav(ffmpeg 绑定),适合原型验证,多路实时业务性能差。
3. 不要直接用 ffmpeg 命令行工具做业务开发,进程调度不好控制,推荐 libffmpeg 库调用。
## 七、结合你的业务场景(手术示教系统)
– 设备输出 RTSP 流,开发任务:接收流、解码,做本地预览,同时二次编码录制 / 转发;
– 核心指标:端到端延迟,要控制几百 ms 以内;
– 必须处理断流自动重连;
– 优先 TCP 模式,规避 UDP 丢包花屏




