Skip to content

Instantly share code, notes, and snippets.

@Luzifer
Last active July 13, 2020 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Luzifer/fbef347cdff1760cc3a3d8778aa742b5 to your computer and use it in GitHub Desktop.
Save Luzifer/fbef347cdff1760cc3a3d8778aa742b5 to your computer and use it in GitHub Desktop.
A/V Synchro-Test video generator using ffmpeg
*.mp4
overlay.png
#!/bin/bash
set -euo pipefail
[ -f overlay.png ] || {
echo -e "\e[31mMissing overlay.png - loading generic image\e[0m"
curl -sSfLo overlay.png "http://www.clker.com/cliparts/2/9/6/d/11971231361344964261JPortugall_icon_speaker.svg.hi.png"
}
vcodec=${VCODEC:-libx264}
fps=${FPS:-30}
length=${LENGTH:-60}
lowfreq=${LOW_FREQ:-1046}
highfreq=${HIGH_FREQ:-2093}
beepvol=${BEEP_VOL:-80}
filters=(
# Audio (low beep)
"sine=f=1:b=${lowfreq}:d=1[beeplow]"
"[beeplow]bandpass=f=${lowfreq}:t=h:w=250[beeplow]"
"[beeplow]bandreject=f=1:t=h:w=250[beeplow]"
"[beeplow]volume=volume=${beepvol}[low]"
"[low]asplit=3[low1][low2][low3]"
# Audio (high beep)
"sine=f=1:b=${highfreq}:d=1[beephigh]"
"[beephigh]bandpass=f=${highfreq}:t=h:w=250[beephigh]"
"[beephigh]bandreject=f=1:t=h:w=250[beephigh]"
"[beephigh]volume=volume=${beepvol}[high]"
# Audio (beep low left, 0ms)
"[low1]stereotools=balance_out=-1[lowleft]"
# Audio (beep low right, 1000ms)
"[low2]stereotools=balance_out=1[lowright]"
"[lowright]adelay=1000|1000[lowright]"
# Audio (beep low both, 2000ms)
"[low3]adelay=2000|2000[lowboth]"
# Audio (beep high both, 3000ms)
"[high]adelay=3000|3000[highboth]"
# Audio combined 4s loop
"[lowleft][lowright][lowboth][highboth]amix=inputs=4[audio]"
"[audio]aloop=loop=-1:size=44100*4[audio]"
# Split out audio for visualization
"[audio]asplit[audio]"
# Audio visualization (freqs)
"[audio]showfreqs=s=1920x400:cmode=separate:fscale=log[audiovisual]"
# Video background
"color=color=0x333333:size=1920x1080:rate=${fps}[bg]"
"color=color=0xf2f2f2:size=10x50:rate=${fps}[slider]"
"[0]scale=height=250:w=-1[overl]"
"[bg][overl]overlay=x=(main_w-overlay_w)/2:y=100[bg]"
"[bg][audiovisual]overlay=x=(main_w-overlay_w)/2:y=main_h-75-overlay_h[bg]"
# Draw slider with box and markings
"[bg]drawbox=x=20:y=500:h=50:w=1880:color=white[bg]"
"[bg]drawtext=x=20:y=560:fontcolor=white:fontsize=30:text='-500ms'[bg]"
"[bg]drawtext=x=(main_w-text_w)/2:y=560:fontcolor=white:fontsize=30:text='0'[bg]"
"[bg]drawtext=x=main_w-text_w-20:y=560:fontcolor=white:fontsize=30:text='+500ms'[bg]"
"[bg][slider]overlay=x=20+((mod(n-1+(${fps}/2)\,${fps})/${fps})*1880)-overlay_w/2:y=500[bg]"
# Draw frame counter
"[bg]drawtext=fontcolor=0xffffffdd:fontsize=50:text='%{n}':x=(main_w-text_w)/2:y=main_h-text_h-20"
)
echo -e "\e[32mGenerating ${length}s synchrotest with ${vcodec} at 1920x1080@${fps} FPS\e[0m"
# Execute memory limited video generator
IFS=';'
/usr/bin/ffmpeg \
-i overlay.png \
-filter_complex "${filters[*]}" \
-c:v ${vcodec} \
-c:a aac \
-ss 4 \
-t $((length + 4)) \
-g ${fps} \
-y \
synchro_${fps}_${lowfreq}-${highfreq}_${length}s.mp4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment