Automator - Shell Script - ffmpeg: image sequence to video

After doing a bit of research, it turns out that the -i option for ffmpeg takes a single filename and when converting a number of image files to a .mov file, it has to be in the form of e.g. %05d.png. Obviously the padding of the sequential numbering can be a different number of digits and the image type extension can vary as well.

Then to that end, the following example bash code works for me:

Method 1:

The following assumes the sequential numbered files are four digits, starting at 0001, add all files have the same extension.

It will process all four digit sequential numbered files in the same directory while overwriting the output.mov file, if it already exists.

Change Service receives selected files or folders inFinder to:

Service receives selected folders in Finder

Remove the Get Selected Finder Items action,

Set Pass input: to as arguments in the Run Shell Script action.

Replace the default code with the following example bash code:

cd "$1" || exit
ext="$(file="$(ls 0001.*)"; echo "${file##*.}")"
/opt/local/bin/ffmpeg -y -i %04d.${ext} -r 24 -codec prores output.mov

The example bash code above assumes you are selecting only one folder in Finder. For multiple folder selections, use the following example bash code:

for f in "$@"; do
    cd "$f" || exit
    ext="$(file="$(ls 0001.*)"; echo "${file##*.}")"
    /opt/local/bin/ffmpeg -y -i %04d.${ext} -r 24 -codec prores output.mov
done

Note: The example bash code contains limited error handling. The onus is upon the user to add any error handling as may be appropriate, needed or wanted.


Method 2:

Service receives selected files or folders in Finder

Remove the Get Selected Finder Items action,

Set Pass input: to as arguments in the Run Shell Script action.

Assuming the selected image files in Finder are all the same type, in the same folder and the e.g. output.mov file will be created in the same folder of the selected image files...

Then to that end, the following example bash code works for me:

o="output"
e="mov"

d="$(dirname "$1")"
cd "$d" || exit

if [[ ! -e "${o}.${e}" ]]; then
    o="${o}.${e}"
else
    n=2
    for f in ${o} *.${e}; do
        if [[ "${o} ${n}.${e}" == "$f" ]]; then
            n="$(( n + 1 ))"
        fi
    done
    o="${o} ${n}.${e}"
fi

foo="$(date +%s)"
mkdir "/tmp/${foo}" || exit
cd "/tmp/${foo}" || exit

i=1
for f in "$@"; do
    ln -s "$f" "$(printf "%05d" $i).${f##*.}"
    (( i++ ))
done

/opt/local/bin/ffmpeg -i %05d."${f##*.}" -r 24 -codec prores "${d}/${o}"

rm -r "/tmp/${foo}"

Note: The example bash code contains limited error handling. The onus is upon the user to add any error handling as may be appropriate, needed or wanted.

Method 2 Notes:

  • If the e.g. output.mov file already exists, an incremented filename is used, starting at, e.g. output 2.mov and continuing to increment as needed so the Automator Service doesn't fail because the output file already exists. This is primarily handled in the if...else...then block; however, the lines of code prior to it are a part of it as well.
  • In order to accomplish the goal, a temporary directory is created in /tmp, named for the number of seconds since the Unix epoch, e.g. /tmp/1574058046 and is handle by foo="$(date +%s)" and mkdir "/tmp/${foo}".
  • Within this temporary directory a sequential numbered symlink is created for each of the selected image files, and is handled primarily by the for f in "$@"; do ... done loop.
  • ffmpeg then creates the e.g. output.mov file.
  • The temporary directory, e.g, /tmp/1574058046 is removed.
  • Note that the selected image files must all be of the same type per run, however, each run can use a different supported image file type as long as all are the same type per run. As currently coded you can not mix different image file types per each run of the service.

Note: The Get Specified Finder Items action is just for testing purposes and would be deleted before saving the Automator Service.

enter image description here