1

私はこれに1週間苦労しており、オンラインで見つけたすべての方法とオプションを使い果たしました. ここの誰かが私を助けてくれることを願っています。

powershell を使用して 8 つのジョブを開始しています。各ジョブは FFmpeg を実行して、7 分間のファイルをリモート RTMP サーバーにストリーミングしています。これはディスク上のファイルからプルしており、各ジョブは異なるファイルを使用します。コマンドは do while ループ内にあるため、常に再ストリーミングされます。

これにより、ジョブを起動したシェルが大量のメモリを蓄積し、可能な限り消費します。24 時間で、サーバーの 32 GB のうち 30 GB が消費されました。

これが私の起動コードです。助けていただければ幸いです。

start-job -Name v6 -scriptblock {
do { $d = $true; $f = Invoke-Expression -Command "ffmpeg -re -i `"C:\Shares\Matthew\180p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"; $f = $null }
while ($d = $true)

}

ジョブを受け取って out-null にパイプしようとしました。do while ループを開始する前に $f を $null に設定しようとしましたが、オンラインで見つけた他のものも役に立ちませんでした。お時間をいただきありがとうございました!

4

2 に答える 2

4

私が推測するよりも遅いほうがいい。Powershell ジョブで ffmpeg を実行すると、大量のメモリが消費されるという同じ問題が発生しました。問題の核心は、Powershell ジョブが任意/すべての出力をメモリに保存することであり、ffmpeg は出力を標準出力と標準エラーストリームの両方に記録できることを非常に喜んでいます。

私の解決策は、パラメーター「-loglevel quiet」をffmpegに追加することでした。または、標準ストリームとエラー ストリームの両方を null にリダイレクトすることもできます (標準ストリームだけをリダイレクトするだけでは不十分です)。標準ストリームをリダイレクトする方法の詳細については、次の質問を参照してください: Redirection of standard and error output appending to same log-file

于 2016-07-14T13:53:05.137 に答える
2

PowerShell スクリプトまたは式を呼び出す方法は多数あります。

私のお気に入りの 1 つは、RunspacePool を使用することです。RunspacePool では、各タスクが新しい実行空間で開始されます。タスクが完了すると、実行空間は破棄されます。これにより、メモリ消費量がかなり一定に保たれます。これは理解を深めるのに最も簡単な方法ではありませんが、役に立つかもしれない最低限の例を次に示します。

$Throttle = 10 # Maximum jobs that can run simultaneously in a runpool
$maxjobs = 8 # Maximum jobs that will run simultaneously
[System.Collections.ArrayList]$jobs = @()
$script:currentjobs = 0
$jobindex = 0
$jobaction = "ffmpeg -re -i `"C:\Shares\Matthew\180p_3000k.mp4`" -vcodec copy -acodec copy -f flv -y rtmp://<ip>/<appName>/<streamName>"

$sessionstate = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$runspace = [runspacefactory]::CreateRunspacePool(1, $Throttle, $sessionstate, $Host)
$runspace.Open()


function QueueJob{
    param($jobindex)
    $job = "" | Select-Object JobID,Script,Errors,PS,Runspace,Handle
    $job.JobID = $jobindex
    $job.Script = $jobaction
    $job.PS = [System.Management.Automation.PowerShell]::create()
    $job.PS.RunspacePool = $runspace
    [void]$job.PS.AddScript($job.Script)
    $job.Runspace = $job.PS.BeginInvoke()
    $job.Handle = $job.Runspace.AsyncWaitHandle
    Write-Host "----------------- Starting Job: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Blue
    $jobs.add($job)
    $script:currentjobs++
}

Function ServiceJobs{
    foreach($job in $Jobs){
        If ($job.Runspace.isCompleted) {
            $result = $job.PS.EndInvoke($job.Runspace)
            $job.PS.dispose()
            $job.Runspace = $null
            $job.PS = $null
            $script:currentjobs--
            Write-Host "----------------- Job Completed: $("{0:D4}" -f $job.JobID) --------------------" -ForegroundColor Yellow
            Write-Host $result
            $Jobs.Remove($job)
            return
        }
    }
}

while ($true) {
    While ($script:currentjobs -le $maxjobs){
        QueueJob $jobindex
        $jobindex++
    }
    ServiceJobs
    Start-Sleep 1
}

$runspace.Close()
[gc]::Collect() 

適切に終了せずに無限ループを使用しており、エラー チェックがまったく行われていませんが、テクニックを示すには十分です。

于 2015-04-01T00:49:04.543 に答える