PowerShell进度条赢得';t显示

PowerShell进度条赢得';t显示,powershell,ffmpeg,Powershell,Ffmpeg,我正在尝试编写我的第一个PowerShell GUI。基本上,我正在尝试运行一个ffmpeg命令,该命令很好并且可以工作,但是我无法运行进度条。(我是个新手。)这是我的尝试 cd C:\Users\brett\Documents\convert $cmd = 'ffmpeg.exe' $arg0 = '-i' $arg1 = 'MASH_01.ts' $arg2 = '-c:v' $arg3 = '-c:a' $arg4 = 'MASH_01.mp4' $cf = 'copy' $isFile

我正在尝试编写我的第一个PowerShell GUI。基本上,我正在尝试运行一个
ffmpeg
命令,该命令很好并且可以工作,但是我无法运行进度条。(我是个新手。)这是我的尝试

cd C:\Users\brett\Documents\convert
$cmd = 'ffmpeg.exe'
$arg0 = '-i'
$arg1 = 'MASH_01.ts'
$arg2 = '-c:v'
$arg3 = '-c:a'
$arg4 = 'MASH_01.mp4'
$cf = 'copy'
$isFile = 'MASH_01.mp4'
if (-not(Test-Path -Path $isFile) -eq $false) {
  echo "Shit Go"
  del $isFile

      & $cmd $arg0 $arg1 $arg2 $cf $arg3 $cf $arg4
    for ($i = 1; $i -le 100; $i++) {
    Start-Sleep -m 100
    Write-Progress -Activity 'Progress Of The Coversion' -Status "$i Percent Complete" -PercentComplete $i;
    }
} else {
& $cmd $arg0 $arg1 $arg2 $cf $arg3 $cf $arg4
    for ($i = 1; $i -le 100; $i++) {
    Start-Sleep -m 100
    Write-Progress -Activity 'Progress Of The Coversion' -Status "$i Percent Complete" -PercentComplete $i;
    }
}
更新:我看不到任何错误输出,但进度条在文件处理后运行,而不是在处理过程中运行

这是我的最新尝试。。但现在我听到ffmpeg说“m”不是有效的开关

cd C:\Users\brett\Documents\convert
$oldVideo = Get-ChildItem -Include @("*.ts")
Write-Host -ForegroundColor Green -Object $ArgumentList;
# Pause the script until user hits enter
$isFile = 'MASH_01.mp4'
if( -not(Test-Path -Path $isFile) -eq $false) {
  echo "Shit Go"
  del $isFile
  }a
  $tool = ffmpeg.exe
$ArgumentList = '`-i'+' '+'MASH_01.ts'+' '+'-c:v'+' '+'copy'+' '+'-c:a'+' '+'copy'+' '+'MASH_01.mp4';
Invoke-Expression $tool $ArgumentList
for($i = 1; $i -le 100; $i++){
    ffmpeg $ArgumentList -m 100

    Write-Progress -Activity 'Progress Of The Coversion' -Status "$i Percent Complete" -PercentComplete $i 
   `-SecondsRemaining $a -CurrentOperation
   "$i% complete" `

    }

要查看运行进度,请使用:

cls
for($i =1; $i -le 100 ; $i++){
Start-Sleep -m 100
Write-Progress -Activity 'Progress Of The Conversion' -Status "$i Percent Complete" -PercentComplete $i
}
将start-sleep cmdlet替换为您自己的代码,理想情况下,在某些内容上计算百分比:

例如: 1.将命令放在一个txt文件中-每行一个-您不需要文本文件中的- 2.使用此代码运行:

    cls
    $file = get-content 'c:\yourFolder\yourTextFile.txt'

    $i = 1
    foreach($line in $file) {

      $pct = (($i / $file.count) * 100)
      Write-Progress -activity "Processing...$i" -status "Progress: $([int]$pct)%" -PercentComplete $pct

      &"$line"

      $i++

}

我知道这篇文章已经有7年多的历史了,但它仍然出现在搜索“ffmpeg显示进度条powershell”等内容的顶部附近,所以我想我可以提供一个工作示例

环境
  • ffmpeg Windows build
    2021-05-19-git-2261cc6d8a-full_build-www.gyan.dev
    from
  • Windows 10 Pro 20H2(内部版本19042.985)
  • PowerShell 7.0.3
放码过来。 让我们把它拆开 首先是一个重要的音符

默认情况下,ffmpeg将其文本输出发送到
stderr
,而不是预期的
stdout
。这是因为ffmpeg能够在
stdout
上输出流供其他消费。这是不明显的,因为大多数Shell都会以静默方式将
stderr
重定向到
stdout
,但在尝试从进程捕获输出时,这一点很重要。请注意,您可以使用
2>&1
stderr
重定向到
stdout
,但这里介绍的方法同样有效(例如捕获和读取
stderr
)。注意FFoPoT没有,当你考虑实用程序做什么时也是有意义的。 我们开始 我不想解释第一行,这让我们想到:

$frames=Invoke表达式“ffprobe.exe-v error-select_streams v:0-count_packets-show_entries stream=nb_read_packets-of csv=p=0”“$($theFile)””

由于显示进度条取决于知道要计数的最终值,因此我们得到视频中的帧数。ffmpeg在处理过程中的输出很好地满足了这一点(也可以在时间上处理持续时间,因为输出也有持续时间,并以这种方式计算,但这显然更烦人。)

$ffmpeg_params=“-i”“$($theFile)”“$($theFile)-processed.mkv”“”

这只是设置要传递给ffmpeg的参数。请注意,这组特定的参数基本上没有做任何事情,除了将.mp4转换为.mkv格式(带有默认值)进行交叉编码之外,这除了作为演示外基本上是无用的。将其替换为需要传递给ffmpeg的任何参数

写入进度-活动“ffmpeg”-状态“$theFile”-完成百分比0

这会弹出实际的进度条。按照您认为合适的方式使用
-Activity
-Status
参数

$p = New-Object System.Diagnostics.Process
$p.StartInfo.Filename = "ffmpeg.exe"
$p.StartInfo.Arguments = "$ffmpeg_params"
$p.StartInfo.UseShellExecute = $false
$p.StartInfo.RedirectStandardError = $true
$p.StartInfo.RedirectStandardOutput = $true
$p.StartInfo.CreateNoWindow = $true
$p.Start() | Out-Null
这一块相当简单;它为ffmpeg创建一个子进程,传递它的参数,并且(这里是重要的部分)设置父进程(PowerShell),以便从它将创建的子进程(ffmpeg)读取
stderr
stdout
。然后,它使用传入的参数和命令行启动该子进程

重要

上述块的一个常见问题是,您的命令(在本例中为
ffmpeg.exe
)不在您的路径中。您应该做更多的工作来确保存在
ffmpeg.exe
,并可能向其传递一个完全限定的路径

while (-not $p.HasExited) {
  if ($p.StandardError.Peek()) {
    $line = $p.StandardError.ReadLineAsync().Result
    if ($line) {
      $info = $line.Trim();
      if ($info.StartsWith("frame=")) {
        $progperc = ([int]($info.split(" fps")[0]).split("=")[1] / $frames) * 100;
        if ($progperc -gt $PrevProgress) {
          Write-Progress "ffmpeg" -Status "$theFile" -PercentComplete $progperc
          $PrevProgress = $progperc
        }
      }
    }
  }
}
while
循环正在检查运行ffmpeg的进程是否已退出。如果没有,则在StandardError流中返回“”(即,返回流中的下一个可用字符,但不使用它),以查看是否有内容。如果有,它将以异步方式读取该行(不阻塞进程),对其进行修剪,然后真正的魔术开始了

为了完整性起见,重要的是要知道ffmpeg的过程输出(一旦完成,将提供大量关于您让它做什么的信息)看起来非常像这样:

frame=    1 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    1 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=1.9 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=1.9 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=   16 fps= 10 q=0.0 size=       5kB time=00:00:00.59 bitrate=  63.5kbits/s speed=0.379x
frame=   16 fps= 10 q=0.0 size=       5kB time=00:00:00.59 bitrate=  63.5kbits/s speed=0.379x
frame=   31 fps= 15 q=0.0 size=       5kB time=00:00:01.09 bitrate=  34.6kbits/s speed=0.528x
frame=   31 fps= 15 q=0.0 size=       5kB time=00:00:01.09 bitrate=  34.6kbits/s speed=0.528x
frame=   46 fps= 18 q=0.0 size=       5kB time=00:00:01.59 bitrate=  23.8kbits/s speed=0.616x
frame=   46 fps= 18 q=0.0 size=       5kB time=00:00:01.59 bitrate=  23.8kbits/s speed=0.616x
frame=   61 fps= 20 q=0.0 size=       5kB time=00:00:02.09 bitrate=  18.1kbits/s speed=0.678x
frame=   61 fps= 20 q=0.0 size=       5kB time=00:00:02.09 bitrate=  18.1kbits/s speed=0.678x
frame=   76 fps= 21 q=29.0 size=       5kB time=00:00:02.59 bitrate=  14.7kbits/s speed=0.718x
frame=   76 fps= 21 q=29.0 size=       5kB time=00:00:02.59 bitrate=  14.7kbits/s speed=0.718x
frame=   91 fps= 22 q=29.0 size=       5kB time=00:00:03.09 bitrate=  12.3kbits/s speed=0.75x
frame=   91 fps= 22 q=29.0 size=       5kB time=00:00:03.09 bitrate=  12.3kbits/s speed=0.75x
frame=  106 fps= 23 q=29.0 size=       5kB time=00:00:03.59 bitrate=  10.6kbits/s speed=0.775x
frame=  106 fps= 23 q=29.0 size=       5kB time=00:00:03.59 bitrate=  10.6kbits/s speed=0.775x
。。。至少在ffmpeg的最新版本中,它只在每秒一次的连续变化的单行上显示。然而,从我们的子进程的角度来看,每次更新时,它都会流化一整行,这就是我们将用来计算进度条上的进度。您可能会在行首看到重要信息:
frame=2
等等

因此,回到我们的代码;只要行输出以
frame=
开始,我们就抓住那一行,对它进行一些拆分(如果ffmpeg的输出格式发生变化,这可能是低效的,而且很容易中断;我肯定有人可以比我做得更优雅,但我所做的很有效),然后将这个数字与我们必须处理的总帧数进行比较。将这个数字乘以100得到一个百分比,我们就有了我们的进度,所以,只要当前进度大于上一个,我们就更新进度条

$p.WaitForExit()

同样,这是样板子进程内容,只需等待进程退出,然后脚本中就会发生任何其他事情

您还应该在这里进行一些验证,以查看它是否使用常规退出代码退出(
if($p.ExitCode-ne 0)
),以及一些有价值的东西

最后一行只是完成进度条,并使其离开UI

就这样!根据需要修改

信息对问题不重要,但与答案相关 ffmpeg及其同级(例如ffprobe)需要双引号(
frame=    1 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    1 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=0.0 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=1.9 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=    2 fps=1.9 q=0.0 size=       5kB time=00:00:00.00 bitrate=N/A speed=   0x
frame=   16 fps= 10 q=0.0 size=       5kB time=00:00:00.59 bitrate=  63.5kbits/s speed=0.379x
frame=   16 fps= 10 q=0.0 size=       5kB time=00:00:00.59 bitrate=  63.5kbits/s speed=0.379x
frame=   31 fps= 15 q=0.0 size=       5kB time=00:00:01.09 bitrate=  34.6kbits/s speed=0.528x
frame=   31 fps= 15 q=0.0 size=       5kB time=00:00:01.09 bitrate=  34.6kbits/s speed=0.528x
frame=   46 fps= 18 q=0.0 size=       5kB time=00:00:01.59 bitrate=  23.8kbits/s speed=0.616x
frame=   46 fps= 18 q=0.0 size=       5kB time=00:00:01.59 bitrate=  23.8kbits/s speed=0.616x
frame=   61 fps= 20 q=0.0 size=       5kB time=00:00:02.09 bitrate=  18.1kbits/s speed=0.678x
frame=   61 fps= 20 q=0.0 size=       5kB time=00:00:02.09 bitrate=  18.1kbits/s speed=0.678x
frame=   76 fps= 21 q=29.0 size=       5kB time=00:00:02.59 bitrate=  14.7kbits/s speed=0.718x
frame=   76 fps= 21 q=29.0 size=       5kB time=00:00:02.59 bitrate=  14.7kbits/s speed=0.718x
frame=   91 fps= 22 q=29.0 size=       5kB time=00:00:03.09 bitrate=  12.3kbits/s speed=0.75x
frame=   91 fps= 22 q=29.0 size=       5kB time=00:00:03.09 bitrate=  12.3kbits/s speed=0.75x
frame=  106 fps= 23 q=29.0 size=       5kB time=00:00:03.59 bitrate=  10.6kbits/s speed=0.775x
frame=  106 fps= 23 q=29.0 size=       5kB time=00:00:03.59 bitrate=  10.6kbits/s speed=0.775x