begin { $nProcs = 2 $PIDs = @() $WMI_PROC = [WMICLASS]"root¥cimv2:Win32_Process" $pwd = pwd; $pwd = $pwd.Path } process { # Watch the process while($true) { if( $PIDs.Count -eq 0 ) { break } $subsql = @() foreach($aPID in $PIDs) { $subsql += "ProcessID="+$aPID } # Update PID list $sql = "SELECT ProcessID FROM Win32_Process WHERE "+[System.String]::Join(" OR ", $subsql) $procs = Get-WmiObject -Query $sql $PIDs = @() foreach( $aProc in $procs ) { $PIDs += $aProc.ProcessID } if( $PIDs.Count -lt $nProcs){ break } # Number of threads is equal or more than $nProcs. [System.Threading.Thread]::Sleep(5000) } # Launch ffmpeg $base = [System.IO.Path]::GetFileNameWithoutExtension($_.Name) $ffmpeg = [System.String]::Format( "start /b /belownormal /wait ffmpeg -i {0} -f psp -s 480x272 (other options) {1}", $_.FullName, [System.IO.Path]::Combine($pwd, "$base.mp4") $newProc = $WMI_PROC.Create("cmd.exe /c `"$ffmpeg`"", $pwd) $PIDs += ($newProc.ProcessId) }'start /b /belownormal /wait'の部分は処理優先度を下げるためのものですので、通常優先度で良いなら省略可能。dirコマンドなどが出力するFileInfoクラスの配列を入力ファイルとしてパイプから受け取る設計になってまして、
dir *.mpg | .¥ffmpeg.ps1のように使います。こうしておくと、ワイルドカードで指定できない条件でファイルを選択する ことができて便利。中身の動作は
- 保存しているプロセスIDのプログラムがまだ走っているかを確認、終了した場合はリストから削除。
- 保存プロセスIDの数が$nProcsに対して
- 同じもしくは超えているなら、5秒待って最初に戻る(つまり何もせずに待つ)
- 小さいなら、次へ
- WMIのWin32_Processを使って別プロセスでコマンドプロンプトを起動、プロセスIDを保存。
- 最初に戻る。
[参考]
Comments