Skip to content

Instantly share code, notes, and snippets.

@andreas-venturini
Last active December 22, 2016 13:58
Show Gist options
  • Save andreas-venturini/fef589a7fc4827dcbdbf72acc48a09ce to your computer and use it in GitHub Desktop.
Save andreas-venturini/fef589a7fc4827dcbdbf72acc48a09ce to your computer and use it in GitHub Desktop.
ffmpeg_video_transcoding
#!/usr/bin/:/usr/local/bin/
# set -u: only allow referencing of variables if they were previously defined
# set -o pipefail: don't mask pipeline errors
set -uo pipefail
# case-insensitive regex matching
setopt nocasematch
video_input_dir=""
video_output_dir="."
thumbnail_output_dir="."
# The convert_video() function transcodes an input mpg stream into h.264 mp4 video with the following parameters:
# c:v libx264 => create H.264 video using the encoder x264
# profile:v main => use main profile (see https://trac.ffmpeg.org/wiki/Encode/H.264#Compatibility for compatibility)
# r 30 => force frame rate to 30 fps
# c:a libfdk_aac => Use Fraunhofer FDK AAC codec library (currently the highest-quality AAC encoder available with ffmpeg, see https://trac.ffmpeg.org/wiki/Encode/AAC. Requires ffmpeg to be compiled with --enable-libfdk-aac, see https://trac.ffmpeg.org/wiki/CompilationGuide)
# ac 2 => downmix to stereo
# b:a 160k => use constant bit rate of 160kbits
# ar 44100 => set audio sampling frequency to 44.1khz
# nostdin => prevent ffmpeg from reading its standard input
function convert_video() {
mkdir -p logs
basename="$(basename "$1")"
basename="$(echo -e "${basename}" | tr -d '[:space:]')" # strip whitespaces
mp4_filename="${basename%.*}.mp4"
if ! [[ "$basename" =~ ^[0-9]{4,6}.(mpg|mp4|wmv|mov)$ ]]; then
echo "$1 invalid filename, skipping..."
echo "$1" >> logs/invalid_filenames.log
elif [ -e "$video_output_dir/$mp4_filename" ]; then
echo "$mp4_filename already exists, skipping..."
else
echo "Transcoding $1"
ffmpeg -i "$1" -c:v libx264 -profile:v main -r 30 -c:a libfdk_aac -ac 2 -b:a 160k -ar 44100 "$video_output_dir/$mp4_filename" &>"$video_output_dir/logs/$mp4_filename.log" -nostdin || log_errors
ffmpeg -i "$video_output_dir/$mp4_filename" -ss 00:00:10.000 -vframes 1 "$thumbnail_output_dir/$mp4_filename.jpg" -nostdin
fi
}
# log files that ffmpeg couldn't handle and remove broken output file
function log_errors () {
echo "$file" >> logs/broken_files.log
rm "$video_output_dir/$mp4_filename"
}
# find all files in subdirectories (at least 2 levels nested) and transcode them
while IFS= read -r file; do
convert_video "$file"
done < <(find "$video_input_dir" -mindepth 2 -type f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment