我在 Ubuntu 22.04 上使用 ffmpeg 从管道传输的 jpg 创建 1 秒的 mp4 视频。我遇到的唯一问题是,在第一组 jpg 被管道传输后,ffmpeg 停止执行。我需要 ffmpeg 持续接收 jpg,以便它可以继续创建更多 mp4。
这是最接近我想要的命令行:
ffmpeg -framerate 5 -i /tmp/ffmpeg_pipe -c:v libx264 -vf "fps=5" -f segment -segment_time 1 "output_%d.mp4"
当我输入 10 张图像时cat image_*.jpg > /tmp/ffmpeg_pipe
,我得到了 2 个预期的输出文件,但 ffmpeg 随后停止执行。
我该怎么做才能在第一组之后传输更多 jpg 而不必重新启动 ffmpeg?我想要这个是因为我有另一个程序在不断创建我想转换成视频的新 jpg。
答案1
我们必须通过添加-g 5
参数将 GOP 大小设置为 1 秒(5 帧代表 5fps 下的 1 秒):
ffmpeg -framerate 5 -i /tmp/ffmpeg_pipe -c:v libx264 -g 5 -f segment -segment_time 1 "output_%04d.mp4"
段解复用器只能使用关键帧.
添加-g 5
参数强制每 5 帧设置一个关键帧。
测试:
创建 100 张 JPEG 图像:
ffmpeg -f lavfi -i testsrc=s=192x108:r=1:d=100 image_%03d.jpg
将 JPEG 图像写入 FFmpeg 标准输入管道:
cat *.jpg | ffmpeg -framerate 5 -f image2pipe -i pipe: -c:v libx264 -g 5 -f segment -segment_time 1 "output_%04d.mp4"
输出是20个MP4视频文件。
更新:
如果我们想多次写入 FFmpeg,我们可以使用以下解决方案(见评论)。
创建命名管道:
mkfifo /tmp/ffmpeg_pipe
将命名管道重定向到 FFmpeg(添加 & 符号以便 FFmpeg 在后台运行):
ffmpeg -framerate 5 -f image2pipe -i pipe: -c:v libx264 -g 5 -f segment -segment_time 1 "output_%04d.mp4" < /tmp/ffmpeg_pipe &
重要的:打开第二个终端窗口.
从另一个终端:
打开文件描述符 3 写入(和读取)管道:
exec 3<>/tmp/ffmpeg_pipe
cat >&3 将输出重定向到文件描述符 3:
cat *.jpg >&3
写入更多图像(仅作为示例):
cat *.jpg >&3
关闭文件描述符3:
exec 3>&-
找到一种方法来关闭 FFmpeg 进程(我只是按下了 Ctrl-break)。
答案2
要使 FFmpeg 连续从流或管道读取而不中断,可以使用 -re 选项。-re 选项允许无限次重新读取输入流。这对于流式传输实时媒体或处理正在连续更新的媒体文件非常有用。
例如,要使用 FFmpeg 将实时 RTSP 流传输到互联网,您可以使用以下命令:
ffmpeg -i rtsp://example.com/live.sdp -re -f flv rtmp://example.com/live
此命令将连续读取 RTSP 流并将其流式传输到 rtmp://example.com/live 的 RTMP 服务器。
要处理不断更新的媒体文件(例如实时录制的视频文件),您可以使用以下命令:
ffmpeg -i pipe:0 -re -c:v copy -c:a 复制输出.mp4
此命令将连续读取输入管道并将视频和音频流复制到输出文件 output.mp4。-c:v copy 和 -c:a copy 选项告诉 FFmpeg 复制视频和音频流而不对其进行重新编码。
-re 选项是一个非常强大的工具,可用于实现多种任务。但需要注意的是,-re 选项可能会导致 FFmpeg 使用大量内存,因此务必谨慎使用。