Search code examples
powershellffmpegparameter-passingbatch-processing

problem passing parameters from PowerShell to FFMPEG for batch video conversion


I want to convert videos from one format to another using the ffmpeg and have some "flexibility" in being able to have a set of pre-defined conversion settings. However, it doesn't work if I'm passing parameters as array or variables from PowerShell.

The structure of the project folder is:

- main folder
-- input <-folder
-- output <-folder
-- convert.ps1 <- script to launch batch conversion

My code is:

# this is content of convert.ps1
$VideoFileTypes = '*.mkv', '*.mp4', '*.webm', '*.mov'

$VideoInputFolderNamee = 'input'
$VideoOutputFolderName = 'output'

$VideoInputFolder = Join-Path -Path $PSScriptRoot -ChildPath $VideoInputFolderName
$VideoOutputFolder = Join-Path -Path $PSScriptRoot -ChildPath $VideoOutputFolderName

# FFMPEG convertion parameters ----------------------------------------------
[array]$h265 = '-c:v libx265', '-crf 22', '-c:a opus', '-b:a 128k'
$h264 = '-c:v libx264 -preset veryslow -crf 22 -c:a aac'
[array]$h264_2 = "-c:v libx264", "-preset veryslow", "-crf 22", "-c:a aac"
# ---------------------------------------------------------------------------

Get-ChildItem -Path $VideoInputFolder -Recurse -File -Include $VideoFileTypes | Foreach-Object {
    $OutputFileName = $_.BaseName + ".mkv"
    $OutputFilePath = Join-Path -Path $VideoOutputFolder -ChildPath $OutputFileName

    Write-Output $_.FullName
    Write-Output $OutputFilePath

    # reference to one of existing configurations (specified above)
    $parameters = $h265 
    # actuall call for conversion
    & ffmpeg -i $_.FullName $parameters -y $OutputFilePath  
}

If the set of parameters is defined as an array with single quotes, like $h265, then I receive the error:

Invalid stream specifier: v libx265.

If the set of parameters is defined as an array with double quotes, like $h264_2, then I receive the error:

Unrecognized option 'crf 22'.
Error splitting the argument list: Option not found

If the set of parameters is defined as string, like $h264, than error is:

Invalid stream specifier: v libx264 -preset veryslow -crf 22 -c:a aac.

For a while, I thought that there is something wrong with ffmpeg setup itself, as mentioned here. But, I don't think so, since direct specifying of parameters works totaly fine:

& ffmpeg -i $_.FullName -c:v libx264 -preset veryslow -crf 22 -c:a aac -y $OutputFilePath

or

& ffmpeg -i $_.FullName -c:v libx265 -crf 28 -c:a opus -b:a 128k -y $OutputFilePath

Please, help to resolve this issue.

[SOLUTION]:

(1): use each part of array:

...
$h265 = '-c:v', 'libx265', '-crf', '28', '-c:a', 'aac', '-b:a', '128k'
...
$parameters = $h265
& ffmpeg -i $_.FullName $parameters -y $OutputFilePath
...

(2) use the string and split

...
$h265 = '-c:v libx265 -crf 28 -c:a aac -b:a 128k'
...
$parameters = $h265
$parameters = $parameters.Split(" ")
& ffmpeg -i $_.FullName $parameters -y $OutputFilePath
...

Solution

  • The option name and value should be sent as separate strings, so '-crf', '22' instead of '-crf 22'