Automated Video Editing using FFmpeg

video
programming

#1

Goal: create a script that

  • downloads a submitted video from YouTube
  • adds a fade in and out
  • concatenates pre and post rolls

Note: you really need all the video files to have consistent codecs, number of channels (video and audio), dimensions, frame rate, etc.

There is probably some extra re-encoding going on in the below.

Preparation

Create pre and post roll videos, eg as Keynote slides and export.

Make sure they have the right frame rate, and audio channels, etc.

Fixing frame rate:

ffmpeg -i preroll.mp4 -r preroll2.mp4

Adding stereo silence (starting point:

ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -i preroll.mp4 -vcodec copy -acodec aac -map 0:0 -map 1:0 -shortest -strict experimental -y preroll2.mp4

Download

youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]' -o download.mp4 <id of stream>

Add Fades

Starting point: https://video.stackexchange.com/questions/19867/how-to-fade-in-out-a-video-audio-clip-with-unknown-duration

#!/bin/bash

# Starting point: https://video.stackexchange.com/questions/19867/how-to-fade-in-out-a-video-audio-clip-with-unknown-duration

f="$*" # all args
p="${f##*/}" # file
fn="${p%.*}" # name only
e="${p##*.}" # extension

sec=5 # in and out fade duration
fr=30 # output framerate

r=$(ffprobe -show_streams "$f" 2> /dev/null | grep r_frame_rate | head -1 | cut -d \= -f 2) # frame rate
let "frames=$r * $sec" # duration of fade as number of frames

lf=$(ffprobe -show_streams "$f" 2> /dev/null | grep nb_frames | head -1 | cut -d \= -f 2) # total number of frames
let "lf = $lf - $frames" # initial frame to start fade at

echo "Initial fand end frame: $frames , Final fade start frame: $lf"

ffmpeg -i "$f" -vf fade=in:0:$frames,fade=out:$lf:$frames -r $r -vcodec libx264 -preset slow -crf 12 -bf 2 -flags +cgop -pix_fmt yuv420p -r $fr "${fn}_faded.$e"

Concatenate It All Together

Refs:

ffmpeg -i preroll2.mp4 -i download_faded.mp4 -i postroll2.mp4 -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" -map "[v]" -map "[a]" final.mp4