Хорошо, понял это, особенно из PoV экс-БАШЕРА. Итак, BASH ДЕЙСТВИТЕЛЬНО свободен в отношении экранирования аргументов и того, как работают пробелы, общая идиома в bash состоит в том, чтобы создавать команды как: mv "$src" "$dest"
, на случай, если $src
или $dest
содержат пробелы. zsh и подобные им справляются с этим, но BASH нет. Вот как я писал сценарии оболочки.
Это не то, как Windows PowerShell работает (очевидно). PS делает действительно хорошую работу, полностью скрывая свои переменные и параметры команд. Со мной здесь происходило следующее: когда я устанавливал var: $timeFlag2 = "-ss 1"
и передавал это, PS буквально передавал: "-ss 1"
базовой команде, независимо от того, как я от нее ускользнул или что я сделал. Это не сразу очевидно с ошибками, которые вы получаете обратно, если вы не понимаете, какие ошибки команды экранирования могут привести к (Invalid flag with name: "$THIS_IS_CLEARLY_A_VALID_FLAG"
), а какие нет.
Правильный способ сделать это - разделить флаги объединяются в две переменные: $timePiece1 = "-ss"
и $timePiece2 = "1"
, а затем вызывают команду, используя обе. Еще лучше splatting , который похож на расширение пространства BASH, но НАМНОГО умнее. Вот чем закончилось основное исправление:
$FFMPEG_PARAMS = @(
"-ss",
$time,
"-i",
$_input,
$time2Flag,
$time2Val,
"-filter_complex",
"[0:a:0]volume=0.6[l];[0:a:1]volume=1.2[k];[k][l]amerge=inputs=2[a]",
"-map",
"0:v:0",
"-map",
"[a]",
"-c:v",
"copy",
"-c:a",
"libmp3lame",
"-q:a",
"3",
"-ac",
"2",
$d,
$duration,
"output-muxxed.mp4"
)
C:\ffmpeg.exe @FFMPEG_PARAMS
Разрушение параметров и использование splatting решило эту проблему! Вот полный сценарий для справки:
function IsNull($objectToCheck) {
if ($objectToCheck -eq $null) {
return $true
}
if ($objectToCheck -is [String] -and $objectToCheck -eq [String]::Empty) {
return $true
}
if ($objectToCheck -is [DBNull] -or $objectToCheck -is [System.Management.Automation.Language.NullString]) {
return $true
}
return $false
}
$_input = [Management.Automation.WildcardPattern]::Escape($args[0])
$time = $args[1]
$duration = $args[2]
if ($time -match ":") {
$_matches = ($time | Select-String ":" -AllMatches).Matches
$seconds = $time.Substring($_matches[$_matches.Count - 1].Index + 1, 2) -as [int]
$finalSeconds = $seconds - 1
$time2Flag = "-ss"
$time2Val = "1"
$time = $time.Substring(0, $_matches[$_matches.Count - 1].Index) + (":{0:d2}" -f $finalSeconds)
}
else {
$time2Flag = ""
$time2Val = ""
}
if (-not (IsNull($duration))) {
$d = "-t"
}
else {
$d = ""
}
$FFMPEG_PARAMS = @(
"-ss",
$time,
"-i",
$_input,
$time2Flag,
$time2Val,
"-filter_complex",
"[0:a:0]volume=0.6[l];[0:a:1]volume=1.2[k];[k][l]amerge=inputs=2[a]",
"-map",
"0:v:0",
"-map",
"[a]",
"-c:v",
"copy",
"-c:a",
"libmp3lame",
"-q:a",
"3",
"-ac",
"2",
$d,
$duration,
"output-muxxed.mp4"
)
Write-Verbose "C:\ffmpeg.exe -ss $time -i $_input $time2Flag $time2Val -filter_complex '[0:a:0]volume=0.6[l];[0:a:1]volume=1.2[k];[k][l]amerge=inputs=2[a]' -map '0:v:0' -map '[a]' -c:v copy -c:a libmp3lame -q:a 3 -ac 2 $d $duration 'output-muxxed.mp4'" -Verbose
C:\ffmpeg.exe @FFMPEG_PARAMS
Сегодня я выучил ценный урок PS.