1

I'd like to test out several ffmpeg settings and run multiple commands as 'sub-processes'. I would not like to launch more than 4 processes at a time, though. What is a good way to do this? Maybe something like trapping the process id's before running the process in the bg and waiting till they're no longer in the process list? or xargs?

Here's the script with no 'queuing':

#!/bin/bash

for crf in 10 15 20 23 25 30 35 ; do
    for vid_preset in medium slow veryslow; do
        ffmpeg -r 25 -i pics/pic_%04d.png -vcodec libx264 -crf $crf -vpre $vid_preset anim_crf$crf\_$vid_preset.mp4
    done
done
HotDogCannon
  • 2,113
  • 11
  • 34
  • 53

1 Answers1

2

A very simple approach is to just run each ffmpeg process in the background, then wait for them to complete before going on to the next value of crf.

for crf in 10 15 20 23 25 30 35 ; do
    for vid_preset in medium slow veryslow; do
        ffmpeg -r 25 -i pics/pic_%04d.png -vcodec libx264 \
               -crf $crf -vpre $vid_preset anim_crf${crf}_${vid_preset}.mp4 &
    done
    wait
done

If you have parallel installed, you can use it to run all 21 processes in a busy fashion.

# Run 4 jobs at a time, starting a new job whenever one completes.
parallel -j 4 ffmpeg -r 25 -i pics/pic_%04d.png \
         -vcode libx264 -crf {1} -vpre {2} \
         anim_crf{1}_{2}.mp4 ::: 10 15 20 23 25 30 35 ::: medium slow veryslow

{1} is replaced by a choice from the first input source (following the first :::), {2} by a choice form the second input source. An example explains it more simply:

$ parallel echo {1} {2} ::: a b c :: 1 2
a 2
a 1
b 1
b 2
c 1
c 2

A messy approach in bash 4.3 or later (when wait -n was introduced):

max_jobs=4
running=()
for c in 10 15 20 23 25 30 35; do
  for v in medium slow veryslow; do
    ffmpg ... &
    running+=($!)
    # If we're at capacity, wait for a job to complete
    if (( ${#running[@]} == $max_jobs )); then
      wait -n
      # Any where from 0 to max_jobs - 1 could still be running
      running=( $(jobs -p) )
    fi
  done
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • that's true, but is there a way that's more independent of the number of items for iteration? something more like a simple 'queue'? – HotDogCannon Jun 06 '16 at 15:39
  • 2
    `parallel` handles that quite nicely. Doing so in pure shell is surprisingly difficult. – chepner Jun 06 '16 at 15:46