Skip to content

Instantly share code, notes, and snippets.

@jshbrntt
Last active December 28, 2021 21:41
Show Gist options
  • Save jshbrntt/0764f654ba992b663ee9 to your computer and use it in GitHub Desktop.
Save jshbrntt/0764f654ba992b663ee9 to your computer and use it in GitHub Desktop.
Script to convert videos to web compatible formats.
#!/bin/bash
printf "\e[1;36m\n\
_ _ ____ _ \n\
__ _(_) __| | ___ ___ ___|___ \__ _____| |__ \n\
\ \ / / |/ _\` |/ _ \/ _ \/ __| __) \ \ /\ / / _ \ '_ \ \n\
\ V /| | (_| | __/ (_) \__ \/ __/ \ V V / __/ |_) | \n\
\_/ |_|\__,_|\___|\___/|___/_____| \_/\_/ \___|_.__/ \n\
https://gist.github.com/joshua-barnett/0764f654ba992b663ee9\n\
Usage: \n\
$ ./videos2web.sh input_directory/ output_directory \e[m\\n"
if [ -z $1 ]
then
printf "\e[1;31mMissing input directory argument.\e[m\\n"
exit 0
fi
if [ -z $2 ]
then
printf "\e[1;31mMissing output directory argument.\e[m\\n"
exit 0
fi
input_directory=$1
output_directory=$2
if ! [ -d ${input_directory} ]
then
printf "\e[1;31mInvalid input directory argument.\e[m\\n"
exit 0
fi
if ! [ -d ${output_directory} ]
then
printf "\e[1;31mInvalid output directory argument.\e[m\\n"
exit 0
fi
loglevel=info
codecs=(libx264, libvpx, libtheora)
function encodeMP4 {
local filepath=$1
local resolution=$2
local output_directory=$3
if ! [ -r ${filepath} ]
then
printf "\e[1;33mInput file either does not exist or isn't readable.\e[m\\n"
return
fi
if [ -z ${resolution} ]
then
printf "\e[1;33mNo resolution argument supplied.\e[m\\n"
return
fi
if ! [ -d ${output_directory} ]
then
mkdir -p ${output_directory}
printf "\e[1;33mCreated output directory.\e[m\\n"
fi
local file=${filepath##*/}
local filename=${file%.*}
case ${resolution} in
'360p')
local video_bitrate="500k"
local video_buffer_size="1000k"
local video_scale="640:360"
local audio_bitrate="128k"
;;
'480p')
local video_bitrate="1250k"
local video_buffer_size="2500k"
local video_scale="854:480"
local audio_bitrate="128k"
;;
'720p')
local video_bitrate="2500k"
local video_buffer_size="5000k"
local video_scale="1280:720"
local audio_bitrate="128k"
;;
*)
printf "\e[1;33mInvalid resolution must be 360p, 480p, or 720p.\e[m\\n"
return
;;
esac
local output_file="${output_directory}/${filename}_${resolution}.mp4"
if [ -a ${output_file} ]
then
printf "\e[1;33mOutput file already exists, delete '${output_file}' to re-encode.\e[m\\n"
return
fi
printf "\e[1;32mEncoding ${filepath} => ${output_file}:\n[vb: ${video_bitrate}, vbs: ${video_buffer_size}, vs: ${video_scale}, ab: ${audio_bitrate}]\e[m\\n"
ffmpeg -y -i "${filepath}" -codec:v libx264 -profile:v high422 -preset slow -b:v "${video_bitrate}" -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -vf scale="${video_scale}" -threads 4 -pass 1 -an -f mp4 -f mp4 /dev/null -nostdin && \
ffmpeg -i "${filepath}" -codec:v libx264 -profile:v high422 -preset slow -b:v "${video_bitrate}" -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -vf scale="${video_scale}" -threads 4 -pass 2 -codec:a libfdk_aac -b:a "${audio_bitrate}" -movflags +faststart -f mp4 "${output_file}" -nostdin
}
function encodeOGV {
local filepath=$1
local resolution=$2
local output_directory=$3
if ! [ -r ${filepath} ]
then
printf "\e[1;33mInput file either does not exist or isn't readable.\e[m\\n"
return
fi
if [ -z ${resolution} ]
then
printf "\e[1;33mNo resolution argument supplied.\e[m\\n"
return
fi
if ! [ -d ${output_directory} ]
then
mkdir -p ${output_directory}
printf "\e[1;33mCreated output directory.\e[m\\n"
fi
local file=${filepath##*/}
local filename=${file%.*}
case ${resolution} in
'360p')
local video_bitrate="500k"
local video_buffer_size="1000k"
local video_scale="640:360"
local audio_bitrate="128k"
;;
'480p')
local video_bitrate="1250k"
local video_buffer_size="2500k"
local video_scale="854:480"
local audio_bitrate="128k"
;;
'720p')
local video_bitrate="2500k"
local video_buffer_size="5000k"
local video_scale="1280:720"
local audio_bitrate="128k"
;;
*)
printf "\e[1;33mInvalid resolution must be 360p, 480p, or 720p.\e[m\\n"
return
;;
esac
local output_file="${output_directory}/${filename}_${resolution}.ogv"
if [ -a ${output_file} ]
then
printf "\e[1;33mOutput file already exists, delete '${output_file}' to re-encode.\e[m\\n"
return
fi
printf "\e[1;32mEncoding ${filepath} => ${output_file}:\n[vb: ${video_bitrate}, vbs: ${video_buffer_size}, vs: ${video_scale}, ab: ${audio_bitrate}]\e[m\\n"
ffmpeg -y -i "${filepath}" -codec:v libtheora -b:v "${video_bitrate}" -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -vf scale="${video_scale}" -threads 4 -an -pass 1 -f ogg /dev/null -nostdin && \
ffmpeg -i "${filepath}" -codec:v libtheora -b:v "${video_bitrate}" -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -vf scale="${video_scale}" -threads 4 -codec:a libvorbis -b:a "${audio_bitrate}" -movflags +faststart -pass 2 -f ogg "${output_file}" -nostdin
}
function encodeWEBM {
local filepath=$1
local resolution=$2
local output_directory=$3
if ! [ -r ${filepath} ]
then
printf "\e[1;33mInput file either does not exist or isn't readable.\e[m\\n"
return
fi
if [ -z ${resolution} ]
then
printf "\e[1;33mNo resolution argument supplied.\e[m\\n"
return
fi
if ! [ -d ${output_directory} ]
then
mkdir -p $output_directory
printf "\e[1;33mCreated output directory.\e[m\\n"
fi
local file=${filepath##*/}
local filename=${file%.*}
case ${resolution} in
'360p')
local video_bitrate="500k"
local video_buffer_size="1000k"
local video_scale="640:360"
local audio_bitrate="128k"
;;
'480p')
local video_bitrate="1250k"
local video_buffer_size="2500k"
local video_scale="854:480"
local audio_bitrate="128k"
;;
'720p')
local video_bitrate="2500k"
local video_buffer_size="5000k"
local video_scale="1280:720"
local audio_bitrate="128k"
;;
*)
printf "\e[1;33mInvalid resolution must be 360p, 480p, or 720p.\e[m\\n"
return
;;
esac
local output_file="${output_directory}/${filename}_${resolution}.webm"
if [ -a ${output_file} ]
then
printf "\e[1;33mOutput file already exists, delete '${output_file}' to re-encode.\e[m\\n"
return
fi
printf "\e[1;32mEncoding ${filepath} => ${output_file}:\n[vb: ${video_bitrate}, vbs: ${video_buffer_size}, vs: ${video_scale}, ab: ${audio_bitrate}]\e[m\\n"
ffmpeg -y -i "${filepath}" -codec:v libvpx -quality good -cpu-used 0 -b:v "${video_bitrate}" -qmin 10 -qmax 42 -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -threads 4 -vf scale="${video_scale}" -an -pass 1 -f webm /dev/null -nostdin && \
ffmpeg -i "${filepath}" -codec:v libvpx -quality good -cpu-used 0 -b:v "${video_bitrate}" -qmin 10 -qmax 42 -maxrate "${video_bitrate}" -bufsize "${video_buffer_size}" -threads 4 -vf scale="${video_scale}" -codec:a libvorbis -b:a "${audio_bitrate}" -pass 2 -f webm "${output_file}" -nostdin
}
find ${input_directory}/ -type f \( -name "*.mts" -o -name "*.mov" -o -name "*.mp4" \) | while read filepath; do
file=${filepath##*/}
filename=${file%.*}
# 360p
encodeOGV $filepath "360p" "${output_directory}/${filename}"
encodeMP4 $filepath "360p" "${output_directory}/${filename}"
encodeWEBM $filepath "360p" "${output_directory}/${filename}"
# 480p
encodeOGV $filepath "480p" "${output_directory}/${filename}"
encodeMP4 $filepath "480p" "${output_directory}/${filename}"
encodeWEBM $filepath "480p" "${output_directory}/${filename}"
# 720p
encodeOGV $filepath "720p" "${output_directory}/${filename}"
encodeMP4 $filepath "720p" "${output_directory}/${filename}"
encodeWEBM $filepath "720p" "${output_directory}/${filename}"
done
# Removing logs generated from 2 pass encoding.
find ${output_directory} -maxdepth 1 -type f -name "*.log*" -delete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment