HOWTO: Split WAV and CUE files on Linux
Mostly notes to myself, as a follow-up to this older post. This is a 3-step process.
Add the file to an MKV
Use MKVmerge:
mkvmerge "audio.wav" --chapters "audio.cue" -o "audio.mkv"
You can see that chapter names have been added to the .mkv if you run ffmpeg -i
or mkvinfo
.
Split the MKV by chapter
This generates one file per chapter:
mkvmerge -D -S "audio.mkv" --split chapters:all -o "split-%02d.mkv"
The -D
switch means no video will be copied. -S
means no subtitles.
Extract the audio
This quickly pulls out the audio, raw, without changing anything.
mkvextract split-01.mkv tracks "0:output"
The raw audio is placed in a file called output
You can also do this with:
ffmpeg -i "split-01.mkv" -acodec copy "whatever.wav"
Replace .wav
with .ac3
or .flac
or whatever the audio format is. You can transcode the audio to something else. I recommend Opus
ffmpeg -i "split-01.mkv" -af aformat=channel_layouts="7.1|5.1|stereo" -b:a 1536k "whatever.opus"
There is a bug with the surround sound mapping in ffmpeg.
Rename it
This is bit convoluted. ffprobe
can get the chapter name:
ffprobe -i "split-01.mkv" -show_chapters -loglevel error
The use of -loglevel error
means you only get the data, rather than the debug cruft.
In order to get the title, we get ffprobe
to spit out JSON and then get jq
to interpret it:
ffprobe -i "split-01.mkv" -print_format json -show_chapters -loglevel error | jq ".chapters[0].tags.title" -r
All in one script to extract the audio and rename it
#!/bin/bash
AUDIO="audio.wav"
CUE="audio.cue"
MKV="audio.mkv"
# What's the audio format?
FORMAT=$(ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$AUDIO")
# Create the MKV
mkvmerge "$AUDIO" --chapters "$CUE" -o "$MKV"
# How many chapters are there?
JSON=$(ffprobe -i "$MKV" -print_format json -show_chapters -loglevel error)
COUNT=$(echo $JSON | jq ".chapters | length" )
# Split the MKV into chapters
mkvmerge -D -S "$MKV" --split chapters:all -o "split-%02d.mkv"
# Loop through all the created .mkv files
COUNTER=1
while [ $COUNTER -le $COUNT ]; do
# Zero pad the counter
printf -v ZEROTRACK "%02d" $COUNTER
# Get the chapter name
JSON=$(ffprobe -i "split-$ZEROTRACK.mkv" -print_format json -show_chapters -loglevel error)
TITLE=$(echo $JSON | jq ".chapters[0].tags.title" -r)
FILENAME="[$ZEROTRACK] $TITLE.$FORMAT"
# Raw Audio
mkvextract "split-$ZEROTRACK.mkv" tracks "0:$FILENAME"
# Transcode. Optional
#ffmpeg -i "split-$ZEROTRACK.mkv" "$FILENAME.opus"
let COUNTER=COUNTER+1
done
# Delete the generated MKVs. Optional
#rm *.mkv
Note, there is no single command in MKVtools to do this
GC says:
this is a rather convoluted way of doing it, you should just use shnsplit which can do it all in one go https://wiki.archlinux.org/title/CUE_Splitting
@edent says:
I don't think shnsplit works with surround sound WAV files or DTS WAV. At least, it didn't when this blog post was written.