2016-10-14 3 views
1

В руководстве Blender 2.6 имеется этот небольшой скрипт sh для кодирования видео с сервера блоков Blender через ffmpeg. Он отлично работает на Windows с Cygwin, но только без аппаратного ускорения флаг.Как передать данные ppm в ffmpeg из блока blender frameserver с циклом while в PowerShell

#!/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 

Я хотел бы кодировать мои видео из Блендер в Windows, с -hwaccel dxva2, который работает с PowerShell. Я начал конвертировать скрипт в 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; 

Это часть, с которой у меня возникают проблемы. Я не совсем уверен, что правильный синтаксис заключается в том, чтобы передавать данные в команду ffmpeg так же, как и в сценарии bash выше.

(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; 

Вот результат:

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() {сохраните результаты в переменной} , а затем сделайте свой материал; , потому что пока не будет работать внутри() – 4c74356b41

+0

Я не уверен, что происходит в скрипте bash с его конвейером, но он не загружает все 50 000 + ppm кадров в один объект, а затем запускает ffmpeg. Он просто загружает первый, затем ffmpeg запускает кодировку. –

ответ

0

Ваш (PowerShell) while цикл ничего не подается в ffmpeg, потому что вы подавляете регулярный вывод, перенаправив его в $null.

Если сравнить тело этого цикла

$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)) 

вы заметите, что версия Баш перенаправляет только выход STDERR (2>/dev/null), а не выход STDOUT. Также (), который вы размещаете вокруг цикла (PowerShell) while, работает только для простых выражений. Для сложных выражений вам необходимо использовать subexpression operator ($()).

Чтобы исправить это, просто удалите перенаправление из инструкций PowerShell и используйте $(...) вместо (...).

С учетом сказанного, есть некоторые другие улучшения, которые необходимо внести в остальную часть вашего кода. С одной стороны, info.txt скачать и Хеш создание можно было бы упростить следующим образом:

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

Ваш второй цикл будет работать лучше, как ForEach-Object цикла, с вводом выручено оператором диапазона (..):

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

 Смежные вопросы

  • Нет связанных вопросов^_^