#! /bin/sh

set -e

progname=$(basename $0)

usage="Usage: $progname [OPTIONS] FILE [FILE...]
  -f  path to font file (overrides -F)
  -F  font face (requires ffmpeg with --enable-fontconfig)
  -t  number of thumbnails, WxH (default: 4x4) 
  -w  width of thumbnails (default: 192)
  -h  show this help and exit
"

die() {
    [ -n "$1" ] && echo "Error: $1" || echo "$(basename $0): ffmpeg thumbnail gallery generator"
    echo "$usage"
    exit 1
}

tile="4x4"
width="192"

while getopts ":f:F:t:w:h" opt; do
    case $opt in
        f)
            font=$OPTARG
            ;;
        F)
            font=${font:-$OPTARG}
            ;;
        t)
            tile=$OPTARG
            ;;
        w)
            width=$OPTARG
            ;;
        h)
            die
            ;;
        \?)
            die "Invalid option -$OPTARG"
            ;;
    esac
done

shift $((OPTIND - 1))

[ "$#" -eq 0 ] && die "No filenames specified"
[ -z "$font" ] && die "No font specified"

thumbs=$(echo $tile | tr x \* | bc)

awkscript=$(cat << "EOT"
function format_video(idx,  fmt, bitrate) {
    fmt = "Stream #%d\\: %s\\, %dx%d\\, %s\\, %dkbps\\, %s"
    bitrate = int(streams[idx]["bit_rate"] / 1000)
    durationf = strftime("%H\\:%M\\:%S", duration, 1)
    return sprintf(fmt, idx, streams[idx]["codec_name"], streams[idx]["width"],
                   streams[idx]["height"], streams[idx]["pix_fmt"], bitrate, durationf)
}

function format_audio(idx,  fmt, bitrate) {
    fmt = "Stream #%d\\: %s\\, %s\\, %dkbps"
    bitrate = int(streams[idx]["bit_rate"] / 1000)
    return sprintf(fmt, idx, streams[idx]["codec_name"], streams[idx]["channel_layout"], bitrate)
}

BEGIN {
    FS = "[.=]" 
} 

/^streams/ { 
    gsub("\"", "", $5)
    streams[$3][$4] = $5
}

/^format/ {
    gsub("\"", "", $3)
    duration = $3
}

END {
    filter = ",\ndrawtext=fontcolor=white:text='%s':fontfile=%s:x=4:y=%d"
    off = 24
    for (idx in streams) {
        if (streams[idx]["width"]) {
            out = out sprintf(filter, format_video(idx), font, off)
            off += 20
        }
        if (streams[idx]["channel_layout"]) {
            out = out sprintf(filter, format_audio(idx), font, off)
            off += 20
        }
    }
    printf("pad=in_w:in_h+%d:0:%d", off, off)
    printf(filter, filename, font, 4)
    print out
}
EOT
)

for file; do
    keyframes=$(ffprobe -skip_frame nokey -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 "$file")
    selection=$(($keyframes/320))
    properties=$(ffprobe -v error -show_entries stream=codec_name,duration,channel_layout,nb_read_frames,width,height,pix_fmt,bit_rate:format=duration -of flat "$file" | gawk -v font="$font" -v filename="$(basename $file)" "$awkscript")

    filtergraph="
select=not(mod(n\,$selection)),
scale=$width:-2,
thumbnail=20,
drawtext=fontcolor=white:shadowx=1:shadowy=1:text='%{pts\:hms}':fontfile=$font:x=w-text_w-2:y=h-text_h-2,
tile=$tile:margin=4:padding=4,
$properties"

    ffmpeg -skip_frame nokey -i "$file" -vf "${filtergraph}" -frames:v 1 "$file".thumbs.png
done