Skip to content

Instantly share code, notes, and snippets.

@ottosch
Created October 27, 2025 00:27
Show Gist options
  • Select an option

  • Save ottosch/5ac124babf941c9acda23ccc918f770c to your computer and use it in GitHub Desktop.

Select an option

Save ottosch/5ac124babf941c9acda23ccc918f770c to your computer and use it in GitHub Desktop.
Splits an audio file in chapters, according to file metadata. Tested with Privacy and Utopia from Escape the Technocracy
#! /usr/bin/env bash
# Splits an audio file into chapters
# Usage: ./split-chapters.sh input_file
if [ "$#" -ne 1 ]; then
echo "Usage: $0 input_file" >&2
exit 1
fi
audio="$1"
output_format="mp3" # or ogg etc
if ! command -v ffprobe >/dev/null; then
echo "ffprobe is required but not installed. Please install the ffmpeg package" >&2
exit 1
fi
tmp_file="$(mktemp)"
ffprobe -print_format json -show_chapters -i "$audio" 2>/dev/null | jq -c '.chapters[]' >"$tmp_file"
readarray -t chapters <"$tmp_file"
rm "$tmp_file"
count=${#chapters[@]}
echo "$count chapters found"
pad=$((1 + count / 10))
for chap in "${chapters[@]}"; do
id=$(echo "$chap" | jq -r '.id')
chap_num=$(printf "%0${pad}d" "$id")
tags=$(echo "$chap" | jq -r '.tags')
title=$(echo "$tags" | jq -r '.title' | cut -f2 -d':' | tr -s ' ' '-' | tr -cd '[:alnum:]-' | tr '[:upper:]' '[:lower:]')
output=$(echo "$chap_num-$title.$output_format" | tr -s '-')
start_time=$(echo "$chap" | jq -r '.start_time')
end_time=$(echo "$chap" | jq -r '.end_time')
echo "$chap_num: [$start_time:$end_time] $output"
ffmpeg -ss "$start_time" -to "$end_time" -i "$audio" -map 0:a -c:a libmp3lame -b:a 192k "$output"
echo "wrote $output"
done
echo
echo "Done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment