I use a batch script in the shell:sendto folder to do video compression, the script currently looks like this:

for %%a in (%*) do (
    ffmpeg -i %%a -c:v libx265 -c:a copy "%%~na_x265.mp4"

However, I have noticed that FFmpeg cannot fully utilize all the cores on my machine. I am able to run perhaps 3-4 video compressions in parallel while maintaining the same FPS as compared to running a single video compression

Suppose I want to convert 100 videos, how can I modify this script to run say three FFmpeg instances on the first three videos in parallel, and to start a new instance each time one completes?

  • I don’t know how to do Batch file programming in windows, but I believe the best approach would be to use your current for loop, but instead of immediately going to the FFmpeg command you build an array/hash based on the value of %%a and then loop through those array/hash values and launch the FFmpeg command. As to how to know if/when one ends you can start a new one. Or just use the -threads 3 option to force it to use three threads per encode like this: ffmpeg -threads 3 -i %%a -c:v libx265 -c:a copy "%%~na_x265.mp4". 3x faster encodes without significantly changing your script. – Giacomo1968 Sep 29 at 4:47
  • libx265 does not scale linearly with threads, for example -threads 32 and -threads 64 does not show any speedup. (I have 64 physical cores). It is therefore better to run multiple encodes in parallel, but I am not sure how to write the batch script for this. Eg: when using the run command, its is not clear how to detect when the child console window completes the command. – aCuria Sep 29 at 4:57
  • Use start and give the windows a name, and use tasklist to find out when each has finished. – Michael Harvey Sep 29 at 6:44
  • 2
    Had "Windows" not been implied here, it would have been possible to write an answer based on GNU Parallel -> gnu.org/software/parallel – Hannu Sep 29 at 10:35

You can try to start your executions in background process (/b), but there will be a loss of processing / performance with this multiplicity.

See start /? if more the options can suit you better.

@echo off & title <nul

setlocal && cd /d "%~dp0"
for %%a in (%*)do call :^) "%%~dpnxa" "%%~dpna_x265.mp4"
endlocal && "%__AppDir__%timeout.exe" /t -1 & goto %:EOF

for /f %%G in ('%__AppDir__%tasklist.exe ^|find/i /c "ffmpeg.exe"
')do if not %%G leq 4 2>&1 "%__AppDir__%timeout.exe" 10 & goto %:^)

start "%~nx1" /b /min ffmpeg.exe -i "%~1" -c:v libx265 -c:a copy "%~2" 
<con: title <nul & title Encoding: "%~nx1" ^| Target: "%~nx2" & exit /b  
| improve this answer | |
  • @aCuria Thank you again! Typo edited! – It Wasn't Me Oct 7 at 9:55
  • Thanks a bunch, It would probably have been quite hard for me to have figured this out myself. I am wondering if theres a way to pipe the "status" of the ongoing background processes back to the foreground window... probably not possible right – aCuria Oct 7 at 9:57
  • @aCuria I think this is possible take a little help with C#, take a look in my answer in StackOverFlow, if you have some difficulty to apply this, open another question here – It Wasn't Me Oct 7 at 10:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.