views:

555

answers:

1

Im trying to automate video conversion with powershell and ffmpeg tool. Ffmpeg have detailed output about video if called without all nessesary parameters. Usually it reports about error and display input file info if one specified. Ex I interactively executed such command:

d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv

this is powershell console output

ffmpeg.exe : FFmpeg version SVN-r20428, Copyright (c) 2000-2009 Fabrice Bellard, et al.
row:1 char:24
+ d:\video.Enc\ffmpeg.exe <<<<  -i d:\video.Enc\1.wmv
    + CategoryInfo          : NotSpecified: (FFmpeg version ...Bel 
   lard, et al.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

  built on Nov  1 2009 04:03:50 with gcc 4.2.4
  configuration: --enable-memalign-hack --prefix=/mingw --cross-pre
fix=i686-mingw32- --cc=ccache-i686-mingw32-gcc --target-os=mingw32 
--arch=i686 --cpu=i686 --enable-avisynth --enable-gpl --enable-vers
ion3 --enable-zlib --enable-bzlib --enable-libgsm --enable-libfaad 
--enable-pthreads --enable-libvorbis --enable-libtheora --enable-li
bspeex --enable-libmp3lame --enable-libopenjpeg --enable-libxvid --
enable-libschroedinger --enable-libx264 --enable-libopencore_amrwb 
--enable-libopencore_amrnb
  libavutil     50. 3. 0 / 50. 3. 0
  libavcodec    52.37. 1 / 52.37. 1
  libavformat   52.39. 2 / 52.39. 2
  libavdevice   52. 2. 0 / 52. 2. 0
  libswscale     0. 7. 1 /  0. 7. 1
[wmv3 @ 0x144dc00]Extra data: 8 bits left, value: 0

Seems stream 1 codec frame rate differs from container frame rate: 
1000.00 (1000/1) -> 15.00 (15/1)
Input #0, asf, from 'd:\video.Enc\1.wmv':
  Duration: 00:12:0
2.00, start: 5.000000, bitrate: 197 kb/s
    Stream #0.0(eng): Audio: wmav2, 44100 Hz, 1 channels, s16, 48 k
b/s
    Stream #0.1(eng): Video: wmv3, yuv420p, 1024x768, 137 kb/s, 15 tbr, 1k tbn, 1k tbc Metadata
    title           : Silverlight 2.0 Hello World Application
    author          : Sergey Pugachev
    copyright       : 
    comment         : 
    WMFSDKVersion   : 11.0.6001.7000
    WMFSDKNeeded    : 0.0.0.0000
    IsVBR           : 1
    ASFLeakyBucketPairs: 
    VBR Peak        : 715351
    Buffer Average  : 127036
At least one output file must be specified

But I cant figure how to script this and capture output to any kind of posh objects. I tried direct script, wher ps1 file contained exact expression "d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv" - it didnt work. Also i tried to do that with invoke-command and invoke expression. First one returns an exact string with command, second one - dump error to output console but not to -ErrorVariable i specified ( I did set all out variables, not only error one - all of them were empty).

Can anyone point to correct syntax for invoking console applications in posh and capturing output ?

Second one question will be about parsing that output - I'll need video resolution data to calculate correct aspect ratio for conversion. So it will be cool if anyone point how to work with captured error output and parse string like

Stream #0.1(eng): Video: wmv3, yuv420p, 1024x768,

+2  A: 

Try redirecting the error stream to stdout like so and then you should be able to capture both stdout and stderr in a single variable e.g.:

$res = d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv 2>&1

To capture the data try this:

$res | Select-String '(?ims)^Stream.*?(\d{3,4}x\d{3,4})' -all | 
    %{$_.matches} | %{$_.Groups[1].Value}

I'm not sure if $res will be one string or multiple but the above should work for both cases.

Keith Hill
Stderr to stdout work fine. Thank you.Is there any way to obtain stderr and stdout separately ?Data capturing is bit different (there is 2 or more separated streams output info - for audio and video), there will be needed backreference or exclude for "Stream" at least, but this one point I can complete myself. Appreciated for the starting points you gave me.
Alexey Shcherbak
Yeah you can capture them separately - ffmpeg.exe ... > foo.txt 2>foo.err
Keith Hill
:) i wasnt completely clear :) is there any posh-way to obtain data streams separately. Ex Invoke-Expression have keys for specifying ErrorVariable and OutVariables. is there any way to acquire output using such kind of syntax, not using temporary files ?
Alexey Shcherbak
> and 2> are Posh ways and are used far more that -ev and -ov and besides they're only available on cmdlets and not EXEs. :-) Now if you don't want to go to a file then just assigning the result of a command to a variable will capture stdout but you will still need to redirect stderr to a file (that's the easiest). `$res = ffmpeg.exe ... 2>err.txt; $err = gc err.txt` You could inspect the $error variable before and after calling ffmpeg.exe. If an error occurred (check $lastexitcode) then $error[0] should contain the stderr info.
Keith Hill