*Workaround found* Parsing variables to FFMPEG using powershell

Questions involving a Windows version of FFmpeg.
Post Reply
PieCaptain
Posts: 8
Joined: Thu Oct 13, 2016 9:46 am

*Workaround found* Parsing variables to FFMPEG using powershell

Post by PieCaptain » Sun Jun 25, 2017 10:54 am

:?: Hi!

I'm trying to construct an input string using Powershell, however, it doesn't seem to parse correctly

If I use:

Code: Select all

&$ffmpeg -i $VideoInputMap -i $AudioInputMap $VideoOutput
Everything works fine, however, if I use:

Code: Select all

$VideoInputMap = " -i " +$VideoInputMap
$AudioInputMap = " -i " +$AudioInputMap
$InputMap = $VideoInputMap + $AudioInputMap
&$ffmpeg $InputMap $VideoOutput
so that $InputMap = -i D:\VideoInput\VideoInput.mkv -i D:\VideoInput\AudioInput.mkv

I get the Error
Output #0, matroska, to ' -i D:\VideoInput\VideoInput.mkv -i D:\VideoInput\AudioInput.mkv':
Output file #0 does not contain any stream
if I then use :

Code: Select all

$VideoInputMap = " -i " + "`"$VideoInputMap`""
$AudioInputMap = " -i " + "`"$AudioInputMap`""
$InputMap = $VideoInputMap + $AudioInputMap
&$ffmpeg $InputMap $VideoOutput
so that $InputMap = -i "D:\VideoInput\VideoInput.mkv" -i "D:\VideoInput\AudioInput.mkv"

but still get the same error

where:

Code: Select all

$VideoInputMap = "D:\VideoInput\VideoInput.mkv"
$AudioInputMap = "D:\VideoInput\AudioInput.mkv"
$VideoOutput = "C:\Video Output\VideoOutput.mkv"
I should probably add that the reason i'm doing it like this is that i want the option to have a Subtitlemap variable used in constructing the Input map, which if blank just becomes a blank space rather than having to have separate lines of the FFMPEG command for with and without subtitles

Where the final command would look like:

Code: Select all

&$ffmpeg $InputMap  $VideoTrackMap $AudioTrackMap $SubtitleTrackMap -metadata title=$VideoName -acodec $AudioCodec -vcodec $VideoCodec $VideoOutput
Where:

Code: Select all

$VideoTrackMap  = -map 0:v:$VideoTrackID
$AudioTrackMap = -map 1:a:$AudioTrackID
$AudioTrackMap = -map 2:s:$SubtitleTrackID
$InputMap = $VideoInputMap + $AudioInputMap + $SubtitleInputMap
ffmpeg version N-81784-g92de2c2

Powershell V5 Build 10240 Revision 17443

Thanks in advance!
Paul
Last edited by PieCaptain on Tue Jun 27, 2017 9:23 am, edited 1 time in total.

PieCaptain
Posts: 8
Joined: Thu Oct 13, 2016 9:46 am

Re: Parsing variables to FFMPEG using powershell

Post by PieCaptain » Tue Jun 27, 2017 9:22 am

In the meantime, I've cheated by parsing it through "CMD /C"

Code: Select all

cmd.exe /c "$ffmpegcmd $InputFiles $InputStreams -metadata title=$VideoName $OutputCodecs $VideoOutput"
Where:

Code: Select all

$VideoFileInputMap = " -i " + '"'+ $BestVideo.VideoPath + '"'
$AudioFileInputMap = " -i " + '"'+ $BestAudio.VideoPath + '"'
$SubtitleFileInputMap = " -i " + '"'+ $BestSubtitle.VideoPath + '"' 
$InputFiles = $VideoFileInputMap + $AudioFileInputMap + $SubtitleFileInputMap
$VideoStreamInputMap = " -map 0:v:" + $BestVideo.VideoTrackID
$AudioStreamInputMap = " -map 1:a:" + $BestAudio.AudioTrackID
$SubtitleStreamInputMap= " -map 2:s:" + $BestSubtitle.AudioTrackID
$InputStreams = $VideoStreamInputMap + $AudioStreamInputMap + $SubtitleStreamInputMap
$OutputCodecs = "-acodec $OutPutAudioCodec -vcodec $OutPutVideoCodec"

pepoluan
Posts: 4
Joined: Sun Aug 27, 2017 6:02 am

Re: *Workaround found* Parsing variables to FFMPEG using powershell

Post by pepoluan » Mon Sep 25, 2017 4:39 pm

The problem is that PowerShell has a "programming" concept instead of a "command line" concept.

The line:

Code: Select all

ffmpeg -i $VideoInputMap -i $AudioInputMap $VideoOutput
has 1 command, and a ParameterArray containing 5 elements: ( "-i", $VideoInputMap, "-i", $AudioInputMap, $VideoOutput )

However, when you mash together the parameters:

Code: Select all

ffmpeg $InputMap $VideoOutput
now you have 1 command, and a ParameterArray containing 2 elements: ("-i D:\VideoInput\VideoInput.mkv -i D:\VideoInput\AudioInput.mkv", $VideoOutput)

So, the 1st parameter is no longer "-i", but a long string of "-i D:\VideoInput\VideoInput.mkv -i D:\VideoInput\AudioInput.mkv".

Now the way ffmpeg -- and ALL programs invoked programatically as a function -- parses arguments is to loop over the elements of the ParamArray. It looks for a string parameter "-i" (that is, exact match) but never found one. So, it never found an input file in your case. In addition, it assumes that "-i D:\VideoInput\VideoInput.mkv -i D:\VideoInput\AudioInput.mkv" (which is, I have to point out, is NOT equal to "-i") is the name of the output file.

The solution to your problem would be to cast $VideoInputMap (and other similar variables) as ArrayList, like such:

Code: Select all

$VideoInputMap = [System.Collections.ArrayList]@()

$VideoInputMap.Add("-i")
$VideoInputMap.Add("D:\VideoInput\VideoInput.mkv")
$VideoInputMap.Add("-i")
$VideoInputMap.Add("D:\VideoInput\AudioInput.mkv")

$VideoOutput = "D:\VideoOutput\Output.mkv"

D:\Progs\ffmpeg\bin\ffmpeg.exe @VideoInputMap $VideoOutput
The "@" symbol is a "splat" symbol, meaning that the elements of VideoInputMap should each be passed as separate parameters to the ffmpeg.exe program, instead of as a single parameter.

Post Reply
'