This is a little help given to Jefferey, co-host of the OTP podcast which I follow since its beginning. Yesterday he sent out a tweet asking for help on something that I knew it could be solved with the power of open source. I hope everything is clear and work as intended. If it does, I'd like for Jefferey to check my suggestions for italian photographers to be featured on OTP! (aadm 22-Feb-2018)
First step, get ffmpeg on your Mac.
I recommend brew but other options exist. If you don't have brew, then install this one first (it's a powerful package manager to get all sort of cool open source, unix-like apps on Mac). Instructions are on the website or simply input this at the terminal:
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Once you have brew, install ffmpeg:
$ brew install ffmpeg
Suppose you have one image and one audio file, this is the way to combine them into a video:
$ ffmpeg -loop 1 -i TEST.jpg -i TEST.m4a -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -shortest TEST.mp4
I am assuming that the image is already in full-HD dimensions (1920x1080). You can also rescale and crop as you want using ffmpeg however (e.g., using the option -vf scale=720:480
)
The option -c:a copy
makes it for a faster encoding, because it's not re-encoding the audio. The video is encoded in standard H264 format and obviously there are countless options to fine tune the resulting video, just check the docs.
The output option -shortest
is essential to keep the final movie duration equal to the input audio file duration (otherwise the encoding never stops because it loops on itself).
My input image and audio files are respectively 1.4 and 8 Mb and the resulting video is 31 Mb. By setting 1 fps with the option -r 1
both in input and output I get a much smaller video (12 Mb):
$ ffmpeg -r 1 -loop 1 -i TEST.jpg -i TEST.m4a -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -r 1 -shortest TEST.mp4
However, I'm not sure if youtube accepts video with this unusual framerate. Likewise, the option -pix_fmt yuv420
may be redundant, I would again double check by uploading a file to youtube.
Assuming we have a bunch of image and audio files:
$ for nn in *.mp3; do ffmpeg -loop 1 -i $nn.jpg -i $nn -c:v libx264 -tune stillimage -c:a copy -shortest $nn.mp4; done
This one-liner is convenient but has a problem, i.e. that it assumes that the image files are called exactly like the audio file with its extension and the .jpg
extension appended to it, for example FILENAME.mp3.jpg
.
The following shell script fixes that and assumes that audio and images have the same basename (the part of the filename before the extension):
#!/bin/sh
DIR=/Users/aadm/audio
for i in $DIR/*.mp3
do
TMP=`basename ${i} .mp3`
AUDIO=${TMP}.mp3
IMAGE=${TMP}.jpg
MOVIE=${TMP}.mp4
ffmpeg -framerate 5 -i -vcodec h264 ${OU}.mp4
ffmpeg -loop 1 -i ${DIR}/${AUDIO} -i ${DIR}/${IMAGE} -c:v libx264 -tune stillimage -c:a copy -pix_fmt yuv420p -shortest ${MOVIE}
done