2016-10-14 4 views
1

Blender 2.6マニュアルには、ffmpegでBlenderフレームサーバーのビデオをエンコードするためのこの小さなshスクリプトが用意されています。 Cygwinを使ってWindows上ではうまく動作しますが、-hwaccelハードウェアアクセラレーションフラグがない場合にのみ有効です。PowerShellのwhileループでblender frameserverからppmデータをffmpegにパイプする方法

#!/bin/sh 
BLENDER=http://localhost:8080 
OUTPUT=/tmp/output.ogv 
eval `wget ${BLENDER}/info.txt -O - 2>/dev/null | 
    while read key val ; do 
     echo R_$key=$val 
    done` 
i=$R_start 
{ 
    while [ $i -le $R_end ] ; do 
     wget ${BLENDER}/images/ppm/$i.ppm -O - 2>/dev/null 
     i=$(($i+1)) 
    done 
} | ffmpeg -vcodec ppm -f image2pipe -r $R_rate -i pipe:0 -b 6000k -vcodec libtheora $OUTPUT 
wget ${BLENDER}/close.txt -O - 2>/dev/null >/dev/null 

私はPowerShellのと連携-hwaccel dxva2とWindowsでBlenderのから自分の動画をエンコードしたいと思います。私はスクリプトをPowerShellに変換し始めましたが、私は最後の問題に直面しました。私はPowerShellのスクリプトのこの部分を複製するのが難しいです。

i=$R_start 
{ 
    while [ $i -le $R_end ] ; do 
     wget ${BLENDER}/images/ppm/$i.ppm -O - 2>/dev/null 
     i=$(($i+1)) 
    done 
} | ffmpeg -vcodec ppm -f image2pipe -r $R_rate -i pipe:0 -b 6000k -vcodec libtheora $OUTPUT 

以下は私のPowerShellへの変換です。

echo "gathering data"; 
$blender = "http://localhost:8080"; 
$output = "C:\Users\joel\Desktop\output.mp4"; 
$webobj = wget $blender"/info.txt"; 
$lines = $webobj.Content -split('[\r\n]') | ? {$_}; 
$info = @{}; 
foreach ($line in $lines) { 
    $lineinfo = $line -split('[\s]') | ? {$_}; 
    $info[$lineinfo[0]] = $lineinfo[1]; 
} 
echo $info; 
[int]$end = [convert]::ToInt32($info['end'],10); 
[int]$i = [convert]::ToInt32($info['start'],10); 
$video=""; 
(while ($i -le $end) { 
    $frame = wget $blender"/images/ppm/"$i".ppm" > $null; 
    echo $frame.Content > $null; 
    $i++; 
}) | ffmpeg -hwaccel dxva2 -vcodec ppm -f image2pipe -r $info['rate'] -i pipe:0 -b 6000k -vcodec libx264 $output; 

これは私が問題を抱えている部分です。上記のbashスクリプトと同じ方法で、データをffmpegコマンドにパイプするのが正しい構文であるかどうかはわかりません。ここで

(while($i -le $end) { 
    $frame = wget $blender"/images/ppm/"$i".ppm" > $null; 
    echo $frame.Content > $null; 
    $i++; 
}) | ffmpeg -hwaccel dxva2 -vcodec ppm -f image2pipe -r $info['rate'] -i pipe:0 -b 6000k -vcodec libx264 $output; 

が出力されます:あなたは$nullにそれをリダイレクトすることで、通常の出力を抑制しているため

PS C:\Users\joel\Desktop> .\encode.ps1 
gathering data 

Name       Value 
----       ----- 
rate       30 
height       720 
ratescale      1 
end       57000 
width       1280 
start       1 
while : The term 'while' is not recognized as the name of a cmdlet, function, 
script file, or operable program. Check the spelling of the name, or if a path 
was included, verify that the path is correct and try again. 
At C:\Users\joel\Desktop\encode.ps1:15 char:3 
+ (while ($i -le $end) { 
+ ~~~~~ 
    + CategoryInfo   : ObjectNotFound: (while:String) [], CommandNotFoundException 
    + FullyQualifiedErrorId : CommandNotFoundException
+0

なぜパイプが必要なのか分かりません。ちょうど: while(){結果を変数に保存} し、あなたのものをしてください。 while()内で動作しないため – 4c74356b41

+0

パイプループでbashスクリプトで何が起こっているのかよく分かりませんが、50,000+ppmのフレームをすべて1つのオブジェクトにダウンロードしてffmpegを開始するわけではありません。最初のものをロードするだけで、ffmpegがエンコードを開始します。 –

答えて

0

あなたの(PowerShellの)whileループはffmpegに何も供給していません。

あなたは第二(bashの)の身体にそのループの本体

$frame = wget $blender"/images/ppm/"$i".ppm" > $null; 
echo $frame.Content > $null; 
$i++; 

を比較するとwhileループ

wget ${BLENDER}/images/ppm/$i.ppm -O - 2>/dev/null 
i=$(($i+1)) 

あなたはbashのバージョンのみ(STDERR出力をリダイレクトすることがわかります2>/dev/null)、STDOUT出力ではありません。また、(PowerShell)whileループの周りに置く()も、単純な式でしか動作しません。複雑な式の場合は、subexpression operator$())を使用する必要があります。

これを修正するには、PowerShellステートメントからリダイレクトを削除し、(...)の代わりに$(...)を使用します。

これまで述べてきたように、残りのコードには他にもいくつか改善が加えられています。一つは、info.txtダウンロードおよびハッシュテーブルの作成は、次のように合理化することができます

$start = [int]$info['start'] 
$end = [int]$info['end'] 
$start..$end | ForEach-Object { 
    (wget "$blender/images/ppm/$_.ppm").Content 
} | ffmpeg ... 

$info = @{} 
(wget "$blender/info.txt").Content -split '[\r\n]+' | 
    Where-Object { $_ } | 
    ForEach-Object { 
     $key, $val = $_ -split '\s', 2 
     $info[$key] = $val 
    } 

あなたの第二のループはまた、範囲演算子(..)を介して生成された入力と、より良いForEach-Objectループとして働くだろう

関連する問題