Skip to content

Instantly share code, notes, and snippets.

@jamiely
Last active August 7, 2018 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamiely/e4119442f95c8d3ca090ace482d48bb3 to your computer and use it in GitHub Desktop.
Save jamiely/e4119442f95c8d3ca090ace482d48bb3 to your computer and use it in GitHub Desktop.
Split an mp3 file into many parts

Let's say you have a few files:

  • 01.mp3
  • 02.mp3
  • 03.mp3

They are really large audio books, so you want to split them into chapters. You don't care about the chapter lengths.

Let's create a function to split them up. First, we want to create a directory to hold them

local directory_name="${file_name%.mp3}"
mkdir -p "$directory_name"

We use a bash string function to remove the trailing .mp3 extension. Now, we need to do the actual split

local segment_seconds=30
local output_path="$directory_name/${directory_name}_%03d.mp3"
ffmpeg -i "$file_name" \
  -f segment \
  -segment_time "$segment_seconds" \
  -codec copy \
  "$output_path"

The ffmpeg options used:

  • -f fmt - force format
  • -codec copy - We just want to grab a copy of the segment without re-encoding.

Some possible formats visible when you run ffmpeg -formats:

 DE sap             SAP output
 D  sbg             SBaGen binaural beats script
 D  sdp             SDP
 D  sdr2            SDR2
  E segment         segment
 D  sgi_pipe        piped sgi sequence
 D  shn             raw Shorten
 D  siff            Beam Software SIFF
  E singlejpeg      JPEG single image

This will put the files into the directories, using a 3-digit numbering. To finish things off, we just run this for every file:

find . -name '*.mp3' | while read file_name; do
  split "$file_name"
done

Where split is defined using the components above:

split() {
  local file_name="$1"
  local directory_name="${file_name%.mp3}"
  mkdir -p "$directory_name"
  local segment_seconds=30
  local output_path="$directory_name/${directory_name}_%03d.mp3"
  ffmpeg -i "$file_name" \
    -f segment \
    -segment_time "$segment_seconds" \
    -codec copy \
    "$output_path"

}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment