ffmpeg可以显示进度条吗?

83

我正在使用ffmpeg将.avi文件转换为.flv文件。由于转换文件需要很长时间,因此我想显示进度条。请问有人能指导我如何做到这一点吗?

我知道ffmpeg必须以某种方式将进度输出到文本文件,并且我必须使用ajax调用来读取它。但是我该如何让ffmpeg将进度输出到文本文件中呢?

18个回答

2
通过从链接中获取进度条,我创建了一个简单的脚本,它显示正在编码的视频的实际帧,并在其底部显示进度条……当然,ffmpeg同时也在编码视频。

enter image description here

首先,我们需要从视频中获取持续时间、宽度和高度,以创建进度条。但是,由于color过滤器无法从文件中获取这些信息,因此我们必须首先使用ffprobe获取它们。然后,我们再将它们与ffmpeg一起使用。
#!/bin/bash

video_duration=`ffprobe -v quiet -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$1"`
video_width=`ffprobe -v quiet -select_streams v -show_entries stream=width    -of csv=p=0:s=x "$1"`
video_height=`ffprobe -v quiet -select_streams v -show_entries stream=height   -of csv=p=0:s=x "$1"`
five_percent=`expr $video_height / 20`

#echo $video_duration
#echo $video_width
#echo $video_height
#echo $five_percent

ffmpeg -i "$1" -filter_complex "color=c=red:s='$video_width'x$five_percent[bar];[0][bar]overlay=-w+(w/$video_duration)*t:H-h:shortest=1[bar]" "$2" -map [bar] -f xv display

然后,使用以下脚本:
sh encode_with_bar.sh video_in.mkv video_out.mp4

表现:使用的过滤器非常简单...但每添加一项会消耗额外的 CPU。在我的电脑上测试一个 10MB 的视频文件,这是差异:

  • 没有脚本:14.46 秒
  • 有脚本:17.05 秒(增加了 18%)

是的,几乎增加了 20%。对于短视频来说还不错,但对于较大的文件来说,可能不是一个好主意。


2

这些使用多个工具/控制台的答案使事情变得过于复杂。
pv 是一个不错的选择,但它有缺点,无法处理非连续数据。
只需使用 progress 实用程序:正常运行 ffmpeg,然后在另一个控制台中使用 progress -m -c ffmpeg 进行监视。


1

调用php的system函数会阻塞该线程,因此您需要生成1个HTTP请求来执行转换,以及另一个轮询请求来读取正在生成的txt文件。

或者更好的方法是,客户端提交视频进行转换,然后另一个进程负责执行转换。这样,客户端的连接在等待系统调用终止时不会超时。轮询与上述方式相同。


3
为什么要使用文本文件?一定有更好的方法。每次上传难道不需要创建新的文本文件吗? - Scarface

1
这是我的解决方案:
我使用ffpb和Python子进程来跟踪FFmpeg的进度。然后,我将状态推送到数据库(例如:Redis),以便在网站上显示进度条。
import subprocess

cmd = 'ffpb -i 400MB.mp4 400MB.avi'

process = subprocess.Popen(
    cmd,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT,
    shell=True,
    encoding='utf-8',
    errors='replace'
)

while True:
    realtime_output = process.stdout.readline()

    if realtime_output == '' and process.poll() is not None:
        break

    if realtime_output:
        print(realtime_output.strip(), flush=True)
        print('Push status to Redis...')

0

保持简单与清晰...这里简要介绍使用进度条的可能性。

使用 pvistefani的建议)转换例如 YouTube 视频完全没有问题。但对于从 Odysee 下载的视频则不起作用。我收到了以下错误信息:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fee39005400] stream 0, offset 0x30: partial file [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7fee39005400] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none(tv, bt709), 1280x720, 604 kb/s): unspecified pixel format Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options

我最终使用了ffpb,对我来说仍然非常好用;到目前为止没有任何问题。

使用progress -m -c ffmpeg …很有趣,但是需要在第一个控制台执行正常的ffmpeg命令后打开另一个控制台来运行它(如果从shell脚本中运行不方便)。

ffmpeg-progress-yield似乎是ffpb的一个很好的替代品,但是(至少对我来说)它不显示正在转换的视频名称;它显示“test”而不是实际的文件名。

最后,ffmpeg-progressbar-cliffpbffmpeg-progress-yield非常相似,但显然已经不再维护;我还没有尝试过。


0

经过对这个库的一些调查,我发现实现应该按照以下步骤进行:

  1. 计算结果持续时间。例如获取初始持续时间(如有必要,则减去任何修剪秒):
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mkv

结果必须被解析为浮点数并存储,例如在JavaScript中:

const duration = parseFloat(result);

在任务中 - 指定额外的标志,这样ffmpeg将输出处理后的持续时间:
ffmpeg -i input.mkv -progress pipe:1 ... 

或者相同的内容,但将其管道输出到stderr:

ffmpeg -i input.mkv -progress pipe:2 ... 
  1. 提取已处理的持续时间(从stdout或stderr中),例如在JavaScript中:
const matchedResult = chunkResult.match(/out_time_ms=(\d+)/);
if (Array.isArray(matchedResult)) {
  const currentTimeMs = Math.round(Number(matchedResult[1]) / 1000000);
}
  1. 将处理时间与总时间进行比较
currentTimeMs/duration

0

Docker

为了将WMA/MP3文件转换为静态电影(以便上传到YouTube),我尝试使用docker jrottenberg/ffmpeg。起初似乎以上解决方案都不起作用,但当我使用run而不是up运行docker compose时,Geograph的解决方案就起作用了 :)

version: '3.7'

services:
    musicToVideo:
        image: jrottenberg/ffmpeg
        volumes:
            - ./music:/data
        command: ' -loop 1 -framerate 2 -i "/data/image.jpeg" -i "/data/myAudio.WMA" -preset medium -tune stillimage -crf 18 -c:a aac -b:a 128k -shortest -pix_fmt yuv420p "/data/myVideo.mp4" -stats'
        # command: ' -loop 1 -framerate 2 -i "/data/image.jpeg" -i "/data/myAudio.mp3" -c:v libx264 -preset medium -tune stillimage -crf 18 -c:a copy -shortest -pix_fmt yuv420p "/data/myVideo.mp4" -stats'


我留下了我的工作docker-dompose.yml文件,供未来使用Docker的读者使用 - 只需通过docker compose run musicToVideo运行即可(我假设目录./music与上面的.yml文件在同一目录中,并且它包含WMA / MP3文件和image.jpeg)(对于mp3,请将“command”注释为WMA并取消注释为mp3)


0

FFMPEG.WASM的解决方案

这段代码可以放在加载ffmpeg之后

源代码

ffmpeg.setProgress(({ ratio }) => {
//ratio is a float number between 0 to 1.

const progress = Math.round(ratio * 100);
// Update your progress indicator here
console.log(`Progress: ${progress}%`);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接