ffmpeg中stream_loop参数不生效原因分析

问题

使用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_THREADS
        free_input_thread(file_index);
#endif
        ret = seek_to_start(ifile, is);
#if HAVE_THREADS
        thread_ret = init_input_thread(file_index);
        if (thread_ret < 0)
            return thread_ret;
#endif
        if (ret < 0)
            av_log(NULL, AV_LOG_WARNING, "Seek to start failed.\n");
        else
            ret = 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

然后再次执行本文开头的推流命令,发现循环推流成功了。

最后,发现循环推流两个多小时,没有任何问题。之后手动停止推流,截图如下:

### 搭建视频采集与转发服务器 #### 安装依赖软件包 为了构建一个可以采集并转发视频的服务,首先需要安装必要的工具和服务。这包括 `FFmpeg` 和配置有 RTMP 模块支持的 `Nginx`。 对于 Ubuntu 系统而言,在终端执行如下命令来更新现有包列表以及安装 FFmpeg: ```bash sudo apt update && sudo apt install ffmpeg ``` 接着下载编译好的带有 RTMP 支持模块版本的 Nginx 或者自行编译源码加入此功能[^1]。 #### 配置 Nginx 的 RTMP 功能 编辑 `/etc/nginx/nginx.conf` 文件添加 RTMP 相关设置部分,定义直播应用名称及监听端口等参数: ```nginx rtmp { server { listen 1935; chunk_size 4096; application live { live on; record off; # 不记录视频到磁盘 } } } ``` 保存更改后的配置文件,并重启 Nginx 使新设定生效。 #### 使用 FFmpeg 进行操作 准备好要播放的内容之后就可以通过下面这条指令来进行了: ```bash ffmpeg -re -i /path/to/video/file.mp4 -c:v libx264 -preset ultrafast -maxrate 3000k \ -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 \ -f flv rtmp://localhost:1935/live/streamKey ``` 这里 `-re` 参数表示按照原始媒体的时间戳速率读取输入;而后面的 URL 则指定了目标 RTMP 地址和频道名(streamKey)[^2]。 #### 实现循环 如果希望持续不断地重复发送同一段影片,则可以在上述基础上加上额外选项实现无限次重播效果: ```bash while true ; do ffmpeg -re -stream_loop -1 -i /path/to/video/file.mp4 ... ; done & ``` 这段脚本会创建后台进程不断调用 FFmpeg 命令直到手动终止它为止[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Data-Mining

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值