FFmpeg推流遇invalid dropping st:0故障及延迟推流方案咨询
解决方案:FFmpeg抓取FLV/M3U8流转推YouTube的问题修复与功能实现
核心问题修复:解决"invalid dropping st:0"流中断报错
该报错源于输入流丢帧导致FFmpeg强制终止,先通过参数配置优先维持流运行:
- 添加
-fflags +igndts+discardcorrupt:忽略无效时间戳、丢弃损坏帧,避免流中断 - 添加
-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5:自动重连不稳定的输入流 - 添加
-use_wallclock_as_timestamps 1:用系统时钟替代流时间戳,避免时间戳混乱 - 可选兜底:添加
-vf "drawbox=x=0:y=0:w=iw:h=ih:color=black:t=fill",无有效帧时自动生成黑屏填充
功能实现:满足三个需求
1. 丢帧时自动重启进程
通过监控FFmpeg输出日志中的丢帧关键词,触发进程重启。可将日志输出到管道,实时检查异常。
2. 小体积FLV本地保存+1分钟延迟转推
采用双FFmpeg进程配合:先将源流保存为小体积本地文件,再延迟60秒读取文件转推至YouTube,既实现本地备份,又满足延迟需求。
3. 优先维持流运行
结合上述参数让FFmpeg自动处理丢帧,再配合自动重启作为兜底机制,最大化保障流的连续性。
完整修改后的脚本
#!/bin/bash INPUT_URL="https://pull-flv-l11-va01.xxxxxxxx.com/stage/stream-2995889464288477225_ld.flv" YOUTUBE_RTMP="rtmp://a.rtmp.youtube.com/live2/zzzzz-zzzzz-zzzzz-zzzzz" LOCAL_SAVE_PATH="./live_stream_%Y%m%d_%H%M%S.flv" DELAY_SECONDS=60 # 1分钟延迟 # 捕获中断信号,清理子进程 trap 'kill $(jobs -p); echo "直播转推已终止"; exit' SIGINT SIGTERM # 监控异常并重启流处理流程 stream_process() { while true; do echo "[$(date '+%Y-%m-%d %H:%M:%S')] 启动流处理..." # 第一步:保存源流为小体积FLV文件 ffmpeg -i "$INPUT_URL" \ -fflags +igndts+discardcorrupt -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 \ -c:v libx264 -preset veryfast -crf 30 -profile:v high -pix_fmt yuv420p \ -c:a aac -b:a 128k -ac 2 \ -f flv -strftime 1 "$LOCAL_SAVE_PATH" 2>&1 | tee -a ffmpeg_local.log & # 等待1分钟后启动转推 sleep $DELAY_SECONDS # 第二步:延迟读取本地文件转推至YouTube ffmpeg -re -i "$LOCAL_SAVE_PATH" \ -fflags +igndts+discardcorrupt -use_wallclock_as_timestamps 1 \ -c:v libx264 -preset slow -crf 28 -profile:v high -bf 2 -pix_fmt yuv420p \ -c:a aac -b:a 384k -ac 2 \ -maxrate 5M -bufsize 10M -r 30 -g 60 -coder 1 \ -f flv "$YOUTUBE_RTMP" 2>&1 | tee -a ffmpeg_youtube.log & # 监控子进程,任意进程退出则重启 wait -n echo "[$(date '+%Y-%m-%d %H:%M:%S')] 检测到流异常,重启中..." kill $(jobs -p) sleep 2 done } # 启动主流程 stream_process
脚本细节说明
- 本地保存优化:用
-strftime按时间戳生成文件名,preset veryfast+crf 30平衡体积与编码速度 - 精准丢帧监控(可选):如果需要仅在出现指定报错时重启,可将FFmpeg日志输出改为管道过滤:
ffmpeg ... 2>&1 | while read line; do echo "$line" >> ffmpeg_local.log if echo "$line" | grep -q "invalid dropping st:0\|frame drop"; then kill $(jobs -p) break fi done
内容的提问来源于stack exchange,提问作者sazer kpla
相关产品推荐
相关产品推荐

