ffmpeg打开rtsp流卡住主因是默认行为在弱网或ipc设备上易阻塞,需显式设rtsp_transport为tcp、stimeout为5秒、probesize和analyzeduration限制探测;转封装时须avcc转annex b、校正时间戳、正确映射stream_index。

FFmpeg C++ 里用 avformat_open_input 打开 RTSP 流时,为什么老卡住或超时?
RTSP 是基于 TCP/UDP 的实时协议,FFmpeg 默认会尝试 TCP 回退、重连、OPTIONS 探测,容易在弱网或某些 IPC 设备上卡死。必须显式控制超时和传输方式。
- 设置
rtsp_transport为tcp(避免 UDP 丢包导致解析失败):在AVDictionary **options中加av_dict_set(options, "rtsp_transport", "tcp", 0) - 强制超时:加
av_dict_set(options, "stimeout", "5000000", 0)(单位微秒,即 5 秒),否则默认可能等几十秒 - 禁用自动探测关键帧(对纯流无意义):
av_dict_set(options, "probesize", "32768", 0)和av_dict_set(options, "analyzeduration", "2000000", 0),避免卡在avformat_find_stream_info
转封装(remuxing)必须绕过解码+编码,直接拷贝 packet
“无损”在这里指不触发 avcodec_send_packet/avcodec_receive_frame 和任何 sws_scale 或 swr_convert,否则就不是封装转换,而是重新编解码——画质/时间戳/关键帧位置全变。
- 只调用
av_read_frame读原始 packet,不做avcodec_send_packet - 输出 FLV 时,所有 stream 必须用
AVStream::codecpar(而非已废弃的codec)复制参数:avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar) - 关键:packet 的
dts和pts不能直接写入 FLV,需用av_rescale_q转换时间基——RTSP 流常用1/90000,FLV 容器要求1/1000(毫秒级)
FLV 封装对 H.264/H.265 的特殊要求:AVCC → Annex B 转换必须跳过
FLV 只接受 Annex B 格式(start code: 0x00000001)的视频数据,但大多数 RTSP 源(尤其海康、大华)发的是 AVCC(length-prefixed)格式。直接拷贝 packet 会导致 FLV 播放器解析失败,画面黑或报错 Invalid data found when processing input。
- 检测是否为 AVCC:查
in_stream->codecpar->extradata[0] == 1(AVCC header),此时必须转换 - 转换不能靠 FFmpeg 自动做(
AVFMT_NOFILE容器不支持),得手写:遍历packet->data,把每个 NALU 长度字段替换成0x00000001前缀 - 音频同理:AAC 必须带 ADTS 头,若源是
codecpar->extradata描述的 raw AAC,则需手动拼 ADTS —— 但多数 RTSP 流音频已是 ADTS 格式,先用av_packet_is_keyframe和 hex dump 验证再决定是否处理
时间戳对齐和起始 DTS 处理不当,会导致 FLV 开头花屏或跳帧
RTSP 流的初始 dts 常为负值或极大(如 900000),而 FLV 规范要求第一帧 dts 从 0 开始递增。不做偏移校正,VLC/ffplay 会拒播或解码异常。
- 记录第一个 video packet 的
dts(按AV_TIME_BASE_Q时间基),后续所有 packet 的dts/pts减去它 - FLV 不支持负时间戳,所以校正后若仍为负,需设为 0 并调整后续差值
- 务必调用
av_write_frame前检查packet->stream_index是否映射正确(输入/输出 stream 索引不同),否则 packet 写到错误轨道,音画不同步
ffprobe -v trace 看原始 packet 结构,比硬写逻辑更省时间。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











