84

I found something for videos, which looks like this.

ffmpeg -i * -c:v libx264 -crf 22 -map 0 -segment_time 1 -g 1 -sc_threshold 0 -force_key_frames "expr:gte(t,n_forced*9)" -f segment output%03d.mp4

I tried using that for an audio file, but only the first audio file contained actual audio, the others were silent, other than that it was good, it made a new audio file for every second. Does anyone know what to modify to make this work with audio files, or another command that can do the same?

2
  • If you want other ways of doing this then please explain in more detail what are you trying to achieve. ffmpeg cmdlines are hard to remember.
    – user140866
    May 3, 2016 at 11:35
  • 1
    @siblynx As I explained in the question, split every second of an audio file into new audio files. May 3, 2016 at 11:58

7 Answers 7

111

This worked for me when I tried it on a mp3 file.

$ ffmpeg -i somefile.mp3 -f segment -segment_time 3 -c copy out%03d.mp3

Where -segment_time is the amount of time you want per each file (in seconds).

References

6
  • Worked on mp3s. Failed for me on m4bs saying, "Invalid audio stream. Exactly one MP3 audio stream is required."
    – vossad01
    Aug 29, 2017 at 0:04
  • FYI, replace mp3 with m4a
    – Mikhail
    Oct 14, 2017 at 23:27
  • 1
    What about a case where I have a 40min file that I'd like to break into, say, 4min, 6min, 12min, 8min, 10min instead breaking up into uniform sub-files? Oct 23, 2017 at 20:44
  • 1
    It also worked for wav files. Dec 20, 2017 at 13:44
  • 1
    Anyway to make the output files overlap by about a second? -- (I'm splitting them up into 3 minute chunks). Dec 20, 2017 at 21:54
56

To split a big audio file into a set of tracks with varying lengths, you can use the following command:

# -to is the end time of the sub-file
ffmpeg -i BIG_FILE -acodec copy -ss START_TIME -to END_TIME LITTLE_FILE

For example, I broke up a single .opus file of the Inception Original Soundtrack into sub-files using this text file containing start, end, name:

00:00:00 00:01:11 01_half_remembered_dream
00:01:11 00:03:07 02_we_built_our_own_world
00:03:07 00:05:31 03_dream_is_collapsing
00:05:31 00:09:14 04_radical_notion
00:09:14 00:16:58 05_old_souls
00:16:58 00:19:22 06
00:19:22 00:24:16 07_mombasa
00:24:16 00:26:44 08_one_simple_idea
00:26:44 00:31:49 09_dream_within_a_dream
00:31:49 00:41:19 10_waiting_for_a_train
00:41:19 00:44:44 11_paradox
00:44:44 00:49:20 12_time

I wrote this short awk program to read the text file and create ffmpeg commands from each line:

{
    # make ffmpeg command string using sprintf
    cmd = sprintf("ffmpeg -i inception_ost.opus -acodec copy -ss %s -to %s %s.opus", $1, $2, $3)

    # execute ffmpeg command with awk's system function
    system(cmd)
}

Here is a more detailed python version of the program called split.py, where now both the original track file and the text file specifying sub-tracks are read from the command line:

import sys
import subprocess


def main():
    """split a music track into specified sub-tracks by calling ffmpeg from the shell"""

    # check command line for original file and track list file
    if len(sys.argv) != 3:
        print("usage: split <original_track> <track_list>")
        exit(1)

    # record command line args
    original_track = sys.argv[1]
    track_list = sys.argv[2]

    # create a template of the ffmpeg call in advance
    cmd_string = "ffmpeg -i {tr} -acodec copy -ss {st} -to {en} {nm}.opus"

    # read each line of the track list and split into start, end, name
    with open(track_list, "r") as f:
        for line in f:
            # skip comment and empty lines
            if line.startswith("#") or len(line) <= 1:
                continue

            # create command string for a given track
            start, end, name = line.strip().split()
            command = cmd_string.format(tr=original_track, st=start, en=end, nm=name)

            # use subprocess to execute the command in the shell
            subprocess.call(command, shell=True)

    return None


if __name__ == "__main__":
    main()

You can easily build up more and more complicated ffmpeg calls by modifying the command template and/or adding more fields to each line of the track_list file.

10
  • this is fantastic, ! please tell me How to run this from a python program, i.e i want to read audio, and the annotation file with start,end, label. and then split audio into pieces with sizes corresponding to each line in the file.
    – kRazzy R
    Jan 31, 2018 at 20:47
  • 2
    @kRazzyR subprocess.call(command) is the python analog to system(command) in awk, both of which allow you to send ffmpeg commands the shell. I edited my post to include a flexible python implementation illustrating one way you could go about this. Feb 1, 2018 at 3:14
  • 1
    In my experience the beginning time of track #2 should equal the end time of track #1, and so on. That is, your example times will skip a second between each track.
    – Tim Siegel
    Jun 18, 2018 at 16:56
  • 2
    Here's a compact bash/zsh version. Edit the times as needed, and then remove the word echo to actually run the commands. source="source audio file.m4a"; i=0; t1=0:00; for end_time in 1:24 5:40 14:48 19:33 35:11 40:00 46:08 51:58 ''; do i=$((i+1)); t0=$t1 t1=$end_time; echo ffmpeg -i "$source" -acodec copy -ss $t0 ${t1:+-to} $t1 $(printf "track%02d.%s" $i ${source##*.}); done
    – Tim Siegel
    Jun 18, 2018 at 17:10
  • @TimSmith thanks for catching that, I added an edit above. Depending on your player, there might still be a small hiccup between tracks but this definitely sounds better than chopping out 1s. Jun 19, 2018 at 17:48
4

The following line will split an audio file into multiple files each with 30 sec duration.

ffmpeg -i file.wav -f segment -segment_time 30 -c copy parts/output%09d.wav

Change 30 (which is the number of seconds) to any number you want.

3

slm’s answer:

ffmpeg -i somefile.mp3  -f segment -segment_time 3 -c copy out%03d.mp3

wouldn't work for me with out the -map 0 added:

ffmpeg -i somefile.mp3 -map 0 -f segment -segment_time 3 -c copy out%03d.mp3
1
  • The mapping works great, but also add -vn to strip out any pictures embedded, or it will try to recreate the picture for each segment, (sloooowww).
    – Chris Reid
    Jan 25, 2019 at 11:25
2

The given solution did not work for me. I believe this to be due to an older version of ffmpeg on my system.
In any case, I wanted to provide a solution that did work for me. You can also customise the timers so as to allow overlapping on audio if you'd like.

Output file #0 does not contain any stream

ffmpeg -i your_audio_file.mp3 -acodec copy -t 00:00:30 -ss 00:00:00 split_audio_file.mp3

split your audio files into 30 second increments

1
  • A new question would be in order, as this doesn't answer OP's question! Jan 14, 2018 at 7:03
2

I liked @isosceleswheel answer but don't like python so I made a js version.

const readline = require('readline');
const fs = require('fs')
const args = process.argv.slice(2);

const timeStampRegex = /(\d{2}:\d{2}:\d{2}) (\d{2}:\d{2}:\d{2}) ([A-Za-z\d ']+)/;

const readInterface = readline.createInterface({
    input: fs.createReadStream(args[1])
});

readInterface.on('line', function(line) {
    const match = timeStampRegex.exec(line);
    
    console.log(`ffmpeg -i "${args[0]}" -ss ${match[1]} -to ${match[2]} "${match[3]}.mp3" &&`);
});

Run with:

node split.js "big.mp3" "timestamp.txt"
2

Great python script by @isosceleswheel, I've just used it, but I made some modification of my own, so you can name the tracks with spaces.

Line 18 -> cmd_string = 'ffmpeg -i {tr} -acodec copy -ss {st} -to {en} "{nm}".opus'

"{nm}", quotes, to take entire string as literal.

Line 28 -> start, end, name = line.strip().split(" ", 2)

It will consider only the first 2 spaces as string separation and take the rest as one entire string (the third).
i.e. 00:00:00(start), 00:01:11(end), 01 Half Remembered Dream(name)

With these modifications, you could name rename the music names as such:

00:00:00 00:01:11 01 Half Remembered Dream
00:01:11 00:03:07 02 We Built Our Own World
00:03:07 00:05:31 03 Dream Is Collapsing

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .