使用FFmpeg转推RTMP源至YouTube时无视频流输出求助
我之前也碰到过一模一样的情况,折腾了好一阵子才搞定。这种只出音频、视频数据为0的问题,大概率是FFmpeg拉流时没正确识别视频轨道,或者源HLS流的编码不符合YouTube的要求,甚至可能是Nginx-RTMP的HLS配置本身就没生成视频切片。下面给你分步骤排查解决:
第一步:先确认源HLS流本身有没有视频
先别着急转推,先用ffprobe检查下你的Nginx-RTMP输出的.m3u8流里到底有没有视频轨道。执行这个命令:
ffprobe -v quiet -print_format json -show_streams http://你的Nginx服务器地址/你的流名称.m3u8
如果输出的JSON里只有codec_type="audio"的条目,那问题出在Nginx端——要么是推流到Nginx的源本身就没视频,要么是Nginx的HLS配置没正确生成视频切片。这时候得先排查上游推流或者Nginx配置。
如果能看到codec_type="video"的条目,那问题就出在FFmpeg转推的参数上。
第二步:用符合YouTube要求的参数强制转推
YouTube对RTMP流的编码有严格要求:视频必须是H.264(Baseline、Main或High profile),音频必须是AAC(LC profile)。哪怕源流已经是这个编码,有时候FFmpeg也会因为自动检测的问题漏掉视频流,所以最好手动指定编码参数:
试试这个转推命令:
ffmpeg -i http://你的Nginx服务器地址/你的流名称.m3u8 \ -c:v libx264 -profile:v main -level:v 4.1 \ -c:a aac -b:a 128k \ -f flv rtmp://a.rtmp.youtube.com/live2/你的YouTube推流密钥
如果源流的视频已经是符合要求的H.264,你可以把-c:v libx264改成-c:v copy来直接复制视频流,节省CPU资源,但前提是源视频的profile和level也符合YouTube标准。
第三步:排查Nginx-RTMP的HLS配置
如果第一步发现源HLS没有视频,那得检查Nginx的rtmp配置。确保你的hls配置块里开启了正确的切片规则,比如这样:
rtmp { server { listen 1935; application live { live on; hls on; hls_path /tmp/hls; # 这个目录要存在且有读写权限 hls_fragment 5s; hls_type live; # 可选:生成不同码率的变体流,确保视频被正确处理 hls_variant _low BANDWIDTH=500000; hls_variant _mid BANDWIDTH=1000000; hls_variant _high BANDWIDTH=2000000; } } }
另外还要确认推流到Nginx的源(比如OBS、FFmpeg推流)本身是带有视频的,有时候推流端不小心只开了音频,那Nginx自然输出不了视频流。
第四步:查看FFmpeg的详细日志定位问题
如果上面的步骤都没解决,就在转推命令里加上-v debug参数,看看FFmpeg在拉流、转码过程中有没有报错:
ffmpeg -v debug -i http://你的Nginx服务器地址/你的流名称.m3u8 -c:v libx264 -c:a aac -f flv rtmp://a.rtmp.youtube.com/live2/你的YouTube推流密钥
日志里如果出现类似“Could not find codec parameters for stream 0 (Video: h264, none): unspecified size”或者“Invalid frame dimensions”的错误,就说明FFmpeg没法正确解析源视频流,这时候可能需要在命令里手动指定视频分辨率,比如加上-s 1920x1080(根据你的源流分辨率调整)。
一般按照这个流程排查,基本都能解决视频流丢失的问题。
内容的提问来源于stack exchange,提问作者Mike Miller

