问题
使用ffmpeg把一个视频文件发布成一个rtmp流,并设置成循环推流,此时需要使用参数stream_loop,命令如下:
ffmpeg.exe -stream_loop -1 -re -i D:\tools\ffmpeg-5.1.2\bin\sei.h264 -c copy -f flv -safe 0 rtmp://localhost:1935/live/test
但是发现一个问题,stream_loop参数没有生效,循环推流失败,报错如下:
[flv @ 0000024c65c266c0] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
Seek to start failed.=-1.0 size= 21954kB time=00:00:46.38 bitrate=3877.7kbits/s speed= 1x
D:\tools\ffmpeg-5.1.2-full_build\bin\sei.h264: Operation not permitted
[flv @ 0000024c65c266c0] Failed to update header with correct duration.
[flv @ 0000024c65c266c0] Failed to update header with correct filesize.
frame= 1116 fps= 24 q=-1.0 Lsize= 21954kB time=00:00:46.50 bitrate=3867.3kbits/s speed=0.999x
video:21932kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.100925%
截图:
解决
通过分析日志可以发现,报错前出现了一个报警信息:Seek to start failed. 个人猜测循环推流没有成功就是因为Seek操作失败了,首先看一下ffmpeg源码:
if (ret < 0 && ifile->loop) {AVCodecContext *avctx;for (i = 0; i < ifile->nb_streams; i++) {ist = input_streams[ifile->ist_index + i];avctx = ist->dec_ctx;if (ist->processing_needed) {ret = process_input_packet(ist, NULL, 1);if (ret>0)return 0;if (ist->decoding_needed)avcodec_flush_buffers(avctx);}}
#if HAVE_THREADSfree_input_thread(file_index);
#endifret = seek_to_start(ifile, is);
#if HAVE_THREADSthread_ret = init_input_thread(file_index);if (thread_ret < 0)return thread_ret;
#endifif (ret < 0)av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");elseret = get_input_packet(ifile, &pkt);if (ret == AVERROR(EAGAIN)) {ifile->eagain = 1;return ret;}}
报警是seek_too_start方法触发的,传入的参数是文件名,同时,接下来的报错又是文件读取没有权限:Operation not permitted。所以自己大胆猜测可能是文件格式不支持。
于是,自己又将sei.h264封装成mp4,命令如下:
ffmpeg.exe -i sei.h264 -c copy sei.mp4
然后再次执行本文开头的推流命令,发现循环推流成功了。
最后,发现循环推流两个多小时,没有任何问题。之后手动停止推流,截图如下: