I have a PowerShell script that calls ffmpeg to do a two-pass encode of all .mp4 video files in the current folder.
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"
}
It works perfectly but brings my system to a halt when in use, so I want to give the ffmpeg processes a low priority and an affinity that only lets them use two CPU cores. So I try
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"
}
This doesn't work, because the -i
is considered to be ambiguous. So I try putting the entire command ("ffmpeg -y -i..."
onward) in a string, with the quotation marks escaped. That doesn't work because a positional parameter can't be found that accepts /low
. I try omitting that, passing the command as a separate variable, nothing I try seems to work.
Yet I have an Ruby script invoking ffmpeg the exact same way that does work. It reads
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
So what am I doing wrong? Why does PowerShell not want to run this command, which runs okay if Ruby is the middleman? Why is /low
not a parameter when it's listed in the documentation as one, and how can I make -i
any less ambiguous when the entire string passed to start
is supposed to be the command it's running, with -i
as a valid argument of that command?