我正在使用ffmpeg将.avi文件转换为.flv文件。由于转换文件需要很长时间,因此我想显示进度条。请问有人能指导我如何做到这一点吗?
我知道ffmpeg必须以某种方式将进度输出到文本文件,并且我必须使用ajax调用来读取它。但是我该如何让ffmpeg将进度输出到文本文件中呢?
我正在使用ffmpeg将.avi文件转换为.flv文件。由于转换文件需要很长时间,因此我想显示进度条。请问有人能指导我如何做到这一点吗?
我知道ffmpeg必须以某种方式将进度输出到文本文件,并且我必须使用ajax调用来读取它。但是我该如何让ffmpeg将进度输出到文本文件中呢?
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
是的,几乎增加了 20%。对于短视频来说还不错,但对于较大的文件来说,可能不是一个好主意。
这些使用多个工具/控制台的答案使事情变得过于复杂。
pv
是一个不错的选择,但它有缺点,无法处理非连续数据。
只需使用 progress
实用程序:正常运行 ffmpeg,然后在另一个控制台中使用 progress -m -c ffmpeg
进行监视。
调用php的system函数会阻塞该线程,因此您需要生成1个HTTP请求来执行转换,以及另一个轮询请求来读取正在生成的txt文件。
或者更好的方法是,客户端提交视频进行转换,然后另一个进程负责执行转换。这样,客户端的连接在等待系统调用终止时不会超时。轮询与上述方式相同。
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...')
保持简单与清晰...这里简要介绍使用进度条的可能性。
使用 pv(istefani的建议)转换例如 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-cli与ffpb和ffmpeg-progress-yield非常相似,但显然已经不再维护;我还没有尝试过。
经过对这个库的一些调查,我发现实现应该按照以下步骤进行:
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mkv
结果必须被解析为浮点数并存储,例如在JavaScript中:
const duration = parseFloat(result);
ffmpeg -i input.mkv -progress pipe:1 ...
或者相同的内容,但将其管道输出到stderr:
ffmpeg -i input.mkv -progress pipe:2 ...
const matchedResult = chunkResult.match(/out_time_ms=(\d+)/);
if (Array.isArray(matchedResult)) {
const currentTimeMs = Math.round(Number(matchedResult[1]) / 1000000);
}
currentTimeMs/duration
为了将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)
这段代码可以放在加载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}%`);
});