Skip to content

Instantly share code, notes, and snippets.

@jeffchannell
Last active January 17, 2025 11:56
Show Gist options
  • Save jeffchannell/339005c6c4cc6bc30145d8733a927637 to your computer and use it in GitHub Desktop.
Save jeffchannell/339005c6c4cc6bc30145d8733a927637 to your computer and use it in GitHub Desktop.
Create FFMETADATA for ffmpeg from multiple files.
#!/usr/bin/env bash
# FFMETADATA Chapter generator
# Pass multiple media files to this script to generate a generic FFMETADATA file
# Usage: ARTIST="My Artist" ALBUM="My Album" ./chapters.sh /path/to/*.wav > my.metadata
set -eo pipefail
ARTIST="${ARTIST:-ARTIST}"
ALBUM="${ALBUM:-ALBUM}"
end_stamp=0
begin_stamp=0
i=1
# output the metadata header
echo ';FFMETADATA'
echo "artist=${ARTIST}"
echo "album=${ALBUM}"
# build the chapter list from the arguments
while [ -f "$1" ]
do
if [ $((0+${TITLED:-0})) -eq 0 ]
then
title="Chapter $i"
# increment the counter
i=$((i+1))
else
# attempt to clean up filenames (track numbers, extensions)
title=$(basename "$1"|sed -r -e 's/^([0-9]+)?( - )?(.*)(\.[a-zA-Z0-9]{1,4})$/\3/')
# remove the artist name, if that appears too
title=$(echo -n ${title#$ARTIST}|sed -r -e 's/^ ?- //')
fi
# extract timestamp parts from ffprobe output
read -r h m s ms < <(ffprobe "$1" 2>&1|grep Duration|awk '{print $2}'|sed -e 's/[\.:,]/ /g')
# calculate the new ending
end_stamp=$(($((end_stamp+$(($(($((10#$s+$(($((10#$m+$((10#$h*60))))*60))))*1000))+10#${ms:0:4}))))-1))
# output this chapter
echo '[CHAPTER]'
echo 'TIMEBASE=1/1000'
echo "START=$begin_stamp"
echo "END=$end_stamp"
echo "title=$title"
# set next beginning based on previous end
begin_stamp=$((end_stamp+1))
# remove this file from the argument list
shift 1
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment