Split Audio with CUE Sheet Using FFmpeg
This article provides a straightforward guide on how to split a
single large audio file into individual tracks using a .cue
sheet and FFmpeg. Because FFmpeg does not natively support direct,
automatic CUE-based splitting in a single command, we will show you how
to automate the process using a simple Bash script, as well as how to
use the popular shntool utility alongside FFmpeg for a
quick alternative.
Method 1: Automated Splitting Using FFmpeg and Bash
To split an audio file using FFmpeg, you need to pass the start time
(-ss) and stop time (-to) for each track. You
can automate the parsing of the .cue file and execute the
FFmpeg commands using the following Bash script.
Save this script as split_cue.sh and run it in the
folder containing your audio file and .cue sheet:
#!/bin/bash
# Input files
CUE_FILE="$1"
AUDIO_FILE="$2"
if [ -z "$CUE_FILE" ] || [ -z "$AUDIO_FILE" ]; then
echo "Usage: $0 <file.cue> <audio_file>"
exit 1
fi
# Extract tracks, titles, and timestamps
grep -E 'TRACK|TITLE|INDEX 01' "$CUE_FILE" | while read -r line; do
if [[ $line =~ TRACK ]]; then
track_num=$(echo "$line" | awk '{print $2}')
elif [[ $line =~ TITLE ]]; then
# Clean quotes from title
track_title=$(echo "$line" | cut -d'"' -f2)
elif [[ $line =~ "INDEX 01" ]]; then
time_raw=$(echo "$line" | awk '{print $3}')
# Convert CUE MM:SS:FF (minutes:seconds:frames) to FFmpeg HH:MM:SS.ms
m=$(echo "$time_raw" | cut -d':' -f1)
s=$(echo "$time_raw" | cut -d':' -f2)
f=$(echo "$time_raw" | cut -d':' -f3)
# 75 frames per second
ms=$((f * 1000 / 75))
formatted_time=$(printf "00:%02d:%02d.%03d" $m $s $ms)
# Store time and track info in a temporary array/file
echo "$track_num|$track_title|$formatted_time" >> temp_tracks.txt
fi
done
# Read the temporary file to calculate durations and split
IFS=$'\n' read -d '' -r -a tracks < temp_tracks.txt
for ((i=0; i<${#tracks[@]}; i++)); do
current_track="${tracks[i]}"
next_track="${tracks[i+1]}"
num=$(echo "$current_track" | cut -d'|' -f1)
title=$(echo "$current_track" | cut -d'|' -f2)
start=$(echo "$current_track" | cut -d'|' -f3)
output_name=$(printf "%02d - %s.${AUDIO_FILE##*.}" "$((10#$num))" "$title")
if [ -n "$next_track" ]; then
end=$(echo "$next_track" | cut -d'|' -f3)
ffmpeg -y -i "$AUDIO_FILE" -ss "$start" -to "$end" -acodec copy "$output_name"
else
# Last track goes to the end of the file
ffmpeg -y -i "$AUDIO_FILE" -ss "$start" -acodec copy "$output_name"
fi
done
# Clean up
rm temp_tracks.txtHow to run the script:
Make the script executable:
chmod +x split_cue.shRun the script by targeting your CUE sheet and audio file:
./split_cue.sh album.cue album.flac
Using -acodec copy ensures that the audio is split
without re-encoding, preserving 100% of the original audio quality
instantly.
Method 2: The Command-Line Alternative (shntool + FFmpeg)
If you do not want to use a custom script, the industry-standard way
to split CUE sheets on Linux and macOS is using shntool
(which utilizes FFmpeg under the hood for decoding various formats like
FLAC, APE, and WV).
1. Install the required tools:
- Ubuntu/Debian:
sudo apt install shntool cuetools flac - macOS (via Homebrew):
brew install shntool cuetools
2. Split the file:
Run the following command to split your audio file using the timings from the CUE sheet:
shnsplit -f album.cue -o flac -t "%n - %t" album.flac-f album.cue: Specifies the CUE sheet file.-o flac: Sets the output format to FLAC (you can use other formats likewav).-t "%n - %t": Names the output files automatically based on the Track Number (%n) and Title (%t) defined in the CUE sheet.
3. Apply metadata tags:
shnsplit does not write the metadata tags (like Artist
and Album) to the split tracks automatically. To copy the tags from the
CUE sheet directly to your newly split FLAC files, run:
cuetag.sh album.cue [0-9]*.flac