推流前必须确认三件事:一是ffmpeg命令行能否成功推流,排查网络、权限、服务器地址及鉴权问题;二是编译是否启用librtmp,用ffmpeg -protocols检查rtmp协议是否存在;三是MP4是否含B帧或时间戳异常,用ffprobe验证pts/dts单调性。

推流前必须确认的三件事
FFmpeg 本身不直接提供 C++ API 推流逻辑,而是通过 libavformat、libavcodec 等底层库实现。你写的 C++ 代码本质是调用这些库完成「读取 MP4 → 解码/重封装 → 编码(可选)→ RTMP 封装 → 发送」。很多人卡在第一步就失败,不是代码问题,而是没确认:
ffmpeg命令行能否成功推流:ffmpeg -re -i input.mp4 -c copy -f flv rtmp://server/live/stream
如果这条命令失败,C++ 代码一定也失败,先解决网络、权限、服务器地址、鉴权(如rtmp://server/live/stream?token=xxx)问题。编译时是否启用了
librtmp:用ffmpeg -protocols查看输出里有没有rtmp。若没有,说明 FFmpeg 编译时没链接 librtmp 或没开启协议支持。MP4 是否含 B-frame 或时间戳异常:某些 MP4 的
moov在末尾,或pts/dts不单调,会导致推流卡住或花屏。可用ffprobe -show_packets input.mp4检查前几帧的pts_time和dts_time是否递增。
关键步骤:打开输入、配置输出、循环送包
核心流程不是“播放”,而是“复用(mux)”——把 MP4 里的音视频包原样(或转码后)喂给 RTMP muxer。重点不在解码再编码,而在正确处理时间基转换和包标记:
立即学习“C++免费学习笔记(深入)”;
输入上下文用
avformat_open_input()打开 MP4,务必调用avformat_find_stream_info()获取流参数输出上下文用
avformat_alloc_output_context2()创建,格式强制指定为"flv"(RTMP 只接受 FLV 封装),不能依赖自动探测每个输入流要创建对应的输出流(
avformat_new_stream()),并用avcodec_parameters_copy()复制参数(不是赋值指针)最关键的坑:MP4 的
time_base通常是1/1000或1/90000,而 RTMP 要求所有包的pts/dts以1/1000为单位(毫秒)。必须用av_rescale_q()转换:
pkt.pts = av_rescale_q(pkt.pts, in_stream->time_base, out_stream->time_base); pkt.dts = av_rescale_q(pkt.dts, in_stream->time_base, out_stream->time_base); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
- 写包前记得设置
pkt.stream_index为对应输出流索引,否则av_interleaved_write_frame()会返回-EINVAL
为什么用 -re 模式?如何在 C++ 中模拟
命令行的 -re 表示“按原始帧率读取”,防止把整个 MP4 一口气读完再狂发,导致服务器缓冲炸掉或客户端卡顿。C++ 中没有开关,得自己控制节奏:
读到每个
AVPacket后,计算它本该在什么时间点发出:real_time = start_time + pkt.pts × av_q2d(in_stream->time_base)用
av_gettime_relative()获取当前相对时间,若未到real_time,则usleep()等待(注意单位是微秒)不要用
sleep()或固定延时(如每帧睡 40ms),因为 MP4 可能含 VFR(可变帧率)或音频/视频时间轴不齐若跳过等待(比如做快放或调试),RTMP 服务器通常会丢包或断连,现象是日志出现
NetStream.Play.StreamNotFound或推流端收到Broken pipe
常见错误与绕不过去的细节
Invalid data found when processing input:MP4 文件损坏,或路径含中文/空格且没做 avformat_open_input() 前的 UTF-8 转义(Windows 下尤其明显)
Unable to open output:输出 URL 错误,或 avformat_write_header() 失败(常因缺少关键流参数,比如 H.264 的 SPS/PPS 没写进 AVCodecParameters)
视频能播、音频无声:MP4 音频可能是 AAC-LC,但 RTMP 要求 AAC 是 ADTS 封装且 profile 为 LC;需确保 codecpar->profile 设为 FF_PROFILE_AAC_LOW,并在写头前调用 avformat_write_header()
推流中途断开:没处理 AVPacket 的引用计数,重复 av_packet_unref() 或忘了 av_packet_ref() 导致内存踩踏;RTMP 对包顺序敏感,乱序必断
Invalid data found when processing input:MP4 文件损坏,或路径含中文/空格且没做 avformat_open_input() 前的 UTF-8 转义(Windows 下尤其明显)
Unable to open output:输出 URL 错误,或 avformat_write_header() 失败(常因缺少关键流参数,比如 H.264 的 SPS/PPS 没写进 AVCodecParameters)
视频能播、音频无声:MP4 音频可能是 AAC-LC,但 RTMP 要求 AAC 是 ADTS 封装且 profile 为 LC;需确保 codecpar->profile 设为 FF_PROFILE_AAC_LOW,并在写头前调用 avformat_write_header()
推流中途断开:没处理 AVPacket 的引用计数,重复 av_packet_unref() 或忘了 av_packet_ref() 导致内存踩踏;RTMP 对包顺序敏感,乱序必断
真正难的不是写通,而是让时间戳稳、首帧快、断线可恢复。大部分崩溃都发生在 av_interleaved_write_frame() 返回负值后没检查就继续循环——这里必须 break 并清理。


















