Created
April 28, 2015 03:33
-
-
Save dericed/baa1b3291fb546e1d8fb to your computer and use it in GitHub Desktop.
Bash script to use ffmpeg to pad an input with a color and silence at one or both ends.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # suffix to use on the output file | |
| suffix="_padded" | |
| # color must be a value from http://ffmpeg.org/ffmpeg-utils.html#Color | |
| color="black" | |
| # seconds_at_start must be an integer | |
| seconds_at_start=2 | |
| # seconds_at_end must be an integer | |
| seconds_at_end=10 | |
| get_width(){ | |
| width=$(ffprobe "$1" -show_streams -select_streams v:0 2> /dev/null | grep ^width= | cut -d = -f 2) | |
| } | |
| get_height(){ | |
| height=$(ffprobe "$1" -show_streams -select_streams v:0 2> /dev/null | grep ^height= | cut -d = -f 2) | |
| } | |
| get_framerate(){ | |
| framerate=$(ffprobe "$1" -show_streams -select_streams v:0 2> /dev/null | grep ^r_frame_rate= | cut -d = -f 2) | |
| if [ "$framerate" = "2997/100" ] ; then | |
| framerate="30000/1001" | |
| fi | |
| } | |
| get_channels(){ | |
| channels=$(ffprobe "$1" -show_streams -select_streams a:0 2> /dev/null | grep ^channels= | cut -d = -f 2) | |
| } | |
| get_sar(){ | |
| unset sar | |
| sar=$(ffprobe "$1" -show_streams -select_streams v:0 2> /dev/null | grep ^sample_aspect_ratio= | cut -d = -f 2 | sed 's|:|/|g') | |
| if [ "$sar" = "0/1" ] ; then | |
| sar="1/1" | |
| fi | |
| } | |
| get_samplerate(){ | |
| samplerate=$(ffprobe "$1" -select_streams a:0 -show_streams 2> /dev/null | grep ^sample_rate= | cut -d= -f2) | |
| } | |
| get_audiocodecname(){ | |
| audiocodecname=$(ffprobe "$1" -select_streams a:0 -show_streams 2> /dev/null | grep ^codec_name= | cut -d= -f2) | |
| } | |
| get_timecode(){ | |
| unset timecode | |
| timecode=$(ffprobe "$1" -show_format 2> /dev/null | grep ^TAG:timecode | cut -d= -f2) | |
| if [ "$timecode" = "" ] ; then | |
| timecode="01:00:00;00" | |
| fi | |
| } | |
| adjusttimecode() { | |
| timecode="${1}" | |
| h="${timecode:0:2}" | |
| m="${timecode:3:2}" | |
| s="${timecode:6:2}" | |
| d="${timecode:8:1}" | |
| f="${timecode:9:2}" | |
| seconds=$(echo "${h}*3600+${m}*60+${s}" | bc) | |
| adjustedseconds=$(echo "${seconds}-${seconds_at_start}" | bc) | |
| h2="$((${adjustedseconds}/60/60))" | |
| m2="$((${adjustedseconds}/60%60))" | |
| s2="$((${adjustedseconds}%60))" | |
| echo "${h2}:${m2}:${s2}${d}${f}" | |
| } | |
| if [ "$#" = 0 ] ; then | |
| echo "this script is intended to simply accept an input video and then add some amount of padded to one or both ends, while adjusting the timecode to maintain timecode-to-frame associations of the input." | |
| echo "Usage: $(basename ${0}) [ -o output_directory ] file1 [ file2 ... ]" | |
| echo | |
| echo "There's some other options but tweak the header of this script to work that." | |
| exit | |
| fi | |
| # command-line options | |
| OPTIND=1 | |
| while getopts ":o:x:" opt ; do | |
| case "${opt}" in | |
| o) output_dir="$OPTARG" ;; | |
| x) audio_offset="$OPTARG" ;; | |
| *) echo "bad option -$OPTARG" ; usage ;; | |
| :) echo "Option -$OPTARG requires an argument" ; exit 1 ;; | |
| esac | |
| done | |
| shift $(( ${OPTIND} - 1 )) | |
| while [ "${*}" != "" ] ; do | |
| # get context about the input | |
| input_movie="${1}" | |
| name=$(basename "$input_movie") | |
| if [ ! -s "$input_movie" ] ; then | |
| echo Hey "$input_movie" does not look like a real file. | |
| exit | |
| fi | |
| if [ ! -d "$output_dir" ] ; then | |
| output_dir=`dirname "$input_movie"` | |
| fi | |
| if [ ! "$audio_offset" ] ; then | |
| audio_offset="0" | |
| fi | |
| get_timecode "${input_movie}" | |
| timecodeout=$(adjusttimecode "$timecode") | |
| echo "timecode is adjusted from $timecode to $timecodeout" | |
| get_width "${input_movie}" | |
| get_height "${input_movie}" | |
| get_framerate "${input_movie}" | |
| get_channels "${input_movie}" | |
| get_sar "${input_movie}" | |
| get_samplerate "${input_movie}" | |
| get_audiocodecname "${input_movie}" | |
| ffmpeg -f lavfi -i "color=color=${color}:s=${width}x${height}:r=${framerate}:sar=${sar}:d=${seconds_at_start}" \ | |
| -f lavfi -i "aevalsrc=0:s=${samplerate}:c=${channels}:d=${seconds_at_start}" \ | |
| -i "${input_movie}" \ | |
| -f lavfi -i "color=color=${color}:s=${width}x${height}:r=${framerate}:sar=${sar}:d=${seconds_at_end}" \ | |
| -f lavfi -i "aevalsrc=0:s=${samplerate}:c=${channels}:d=${seconds_at_end}" \ | |
| -filter_complex "[0:v:0][1:a:0][2:v:0][2:a:0][3:v:0][4:a:0]concat=n=3:v=1:a=1[v][a];\ | |
| [a]asetpts=PTS+${audio_offset}/TB[a1]" \ | |
| -map '[v]' -map '[a1]' -shortest -c:v v210 -r:v "${framerate}" -metadata:s:v:0 timecode="${timecodeout}" -metadata:s:v:0 encoder="Uncompressed 10-bit 4:2:2" -c:a "${audiocodecname}" -ac "${channels}" -ar "${samplerate}" -y "$output_dir/${name%.*}${suffix}.mov" | |
| shift | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment