Предоставление аргументов Powershell для «запуска» нарушает команду? - PullRequest
1 голос
/ 20 февраля 2020

У меня есть сценарий PowerShell, который вызывает ffmpeg для двухпроходного кодирования всех видеофайлов .mp4 в текущей папке.

foreach ($i in Get-ChildItem . | Where { $_.extension -like ".mp4" }) {
  ffmpeg -y -i "$i" -c:v libx265 -b:v 2.2M -preset medium -x265-params pass=1 -an -f mkv NUL
  ffmpeg -i "$i" -c:v libx265 -b:v 2.2M -x265-params pass=2 -c:a libopus -ac 1 -b:a 64k -preset medium "small\$i.mkv"
}

Он отлично работает, но останавливает мою систему, когда в использовать, поэтому я хочу дать процессам ffmpeg низкий приоритет и сходство, которое позволяет им использовать только два ядра процессора. Поэтому я пытаюсь

foreach ($i in Get-ChildItem . | Where { $_.extension -like ".mp4" }) {
  start "x265ify" /wait /low /b /affinity C ffmpeg -y -i "$i" -c:v libx265 -b:v 2.1M -preset medium -x265-params pass=1 -an -f mkv NUL
  start "x265ify" /wait /low /b /affinity C ffmpeg -i "$i" -c:v libx265 -b:v 2.1M -x265-params pass=2 -c:a libopus -ac 1 -b:a 64k -preset medium "small\$i.mkv"
}

Это не работает, потому что -i считается неоднозначным. Поэтому я пытаюсь поместить всю команду ("ffmpeg -y -i..." и далее) в строку, избегая кавычек. Это не работает, потому что не может быть найден позиционный параметр, который принимает /low. Я пытаюсь пропустить это, передав команду как отдельную переменную, и все, что я пытаюсь сделать, похоже, не работает.

Тем не менее, у меня есть скрипт Ruby, вызывающий ffmpeg точно так же, как работает . На нем написано

start "x265-ifier" /wait /low /b /affinity #{AFFINITY} ffmpeg \
              -hide_banner \
              -i "#{v}" \
              -vf scale=-2:#{HEIGHT} \
              -c:a libopus \
              -b:a #{AUDIO_BITRATE}k \
              -ac 1 \
              -c:v libx265 \
              -x265-params vbv-maxrate=#{MAX_VIDEO_BITRATE}:vbv-bufsize=7000 \
              -preset #{PRESET} \
              -crf #{CRF} \
              "#{dest}" \
              -y

Так что я делаю не так? Почему PowerShell не хочет запускать эту команду, которая работает нормально, если Ruby является посредником? Почему /low не является параметром, когда он указан в документации как единое целое, и как я могу сделать -i менее двусмысленным, когда вся строка, переданная в start, должна быть командой, которую он выполняет, с -i как действительный аргумент этой команды?

1 Ответ

0 голосов
/ 20 февраля 2020

В PowerShell start - это встроенный псевдоним для Start-Process командлета [1] , синтаксис и поведение которого отличается от внутреннего start команда cmd.exe.

Чтобы вызвать последний [1] , вы должны явно вызвать cmd.exe, как указано ниже:

cmd /c start `"x265ify`" /wait /low /b /affinity C ffmpeg -y -i $i -c:v libx265 -b:v 2.1M -preset medium -x265-params pass=1 -an -f mkv NUL

Примечание:

  • " символов. около x265ify экранируются как `", чтобы гарантировать, что они переданы в start, который (неловко) использует их для различения guish между первым аргументом, представляющим заголовок окна против команды для вызова.

  • $i не нужно заключать в двойные кавычки, потому что PowerShell сделает это по требованию.

  • Использование /wait означает что ваша вторая команда start не будет вызвана до тех пор, пока первая не будет завершена.

В качестве отступления: обработка PowerShell пустых аргументов ("" ) и аргументы с встроенными " символами. передано внешним программам принципиально не работает с PowerShell [Core] 7.0, требуя неловких обходных путей - см. этот ответ для получения дополнительной информации.


[1] Используйте Get-Command start, чтобы обнаружить этот факт.

[2], что необходимо в вашем случае, потому что Start-Process не предлагает контроль над приоритетом запущенного процесса или Сродство к процессору.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...