powershell 如何捕获输出连续实时进度流(来自ffmpeg)

wh6knrhe  于 2022-12-23  发布在  Shell
关注(0)|答案(1)|浏览(215)

我无法通过脚本显示ffmpeg的进度。我将脚本编译为exe,并使用ps2exe和ffmpeg在标准错误上输出,而不是在标准输出上输出,因此我使用管道1选项
我的script.ps1现在是:

# $nb_of_frames= #some_int
& $ffmpeg_path -progress pipe:1 -i input.mp4 -c:v libx264 -pix_fmt yuv420p -crf 25 -preset fast -an output.mp4

然后我用ps2exe编译它。(要重现,您不需要编译,只需直接在cmd或PowerShell中使用上面的命令和pipe:1,您将获得相同的行为)
通常使用ffmpeg你会得到一个进度报告(这是交互式的),一行包含信息,它会作为一行不断更新,而不会用100多行来垃圾邮件控制台,它看起来像这样。

frame= 7468 fps=115 q=22.0 size=   40704kB time=00:05:10.91 bitrate=1072.5kbits/s speed= 4.8x

但是这并没有出现在我的脚本的编译版本中,所以在挖掘之后,我添加了-progress pipe:1以使进度显示在std out上
现在,我每秒都会得到一个连续输出,如下所示:

frame=778
fps=310.36
stream_0_0_q=16.0
bitrate= 855.4kbits/s
total_size=3407872
progress=continue
...
frame=1092
fps=311.04
stream_0_0_q=19.0
bitrate= 699.5kbits/s
total_size=3932160
progress=continue

我想打印一些可更新的百分比,如果我能捕获帧号,我可以很容易地计算百分比,但在这种情况下,我不知道如何捕获这样的实时输出,以及如何使我的进度报告实时更新1单行百分比(或通过符号的一些进度条),而不是在许多行上发送垃圾邮件
(or如果有一种方法可以使FFmpeg的默认进度出现在我的脚本的编译版本中,也可以工作)
编辑:基于以下答案的建议

#use the following lines instead of write-progress if using with ps2exe
            #$a=($frame * 100 / $maxFrames)
            #$str = "#"*$a
            #$str2 = "-"*(100-$a)
            #Write-Host -NoNewLine "`r$a% complete | $str $str2|"

谢啦,谢啦

nzk0hqpo

nzk0hqpo1#

以下是如何从ffmpeg输出捕获当前帧编号、计算百分比并将其传递给Write-Progress的示例:

$maxFrames = 12345

& $ffmpeg_path -progress pipe:1 -i input.mp4 -c:v libx264 -pix_fmt yuv420p -crf 25 -preset fast -an output.mp4 |
    Select-String 'frame=(\d+)' | ForEach-Object {
        $frame = [int] $_.Matches.Groups[1].Value
        Write-Progress -Activity 'ffmpeg' -Status 'Converting' -PercentComplete ($frame * 100 / $maxFrames)
    }

备注:

  • Select-String参数是一个正则表达式,它通过组(\d+)捕获帧编号(其中\d表示数字,+要求至少有一个数字)。请参见Regex101 demo
  • ForEach-ObjectSelect-String的每个匹配项运行给定的脚本块。这里$_.Matches.Groups[1].Value从第一个RegEx组中提取匹配的值。然后我们将其转换为整数以便能够用于计算。
  • 最后计算百分比并将其传递给Write-Progress

相关问题