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?

  • 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 '16 at 11:35
  • 1
    @siblynx As I explained in the question, split every second of an audio file into new audio files. – DisplayName May 3 '16 at 11:58
up vote 34 down vote accepted

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

  • Worked on mp3s. Failed for me on m4bs saying, "Invalid audio stream. Exactly one MP3 audio stream is required." – vossad01 Aug 29 '17 at 0:04
  • FYI, replace mp3 with m4a – Mikhail Oct 14 '17 at 23:27
  • 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? – isosceleswheel Oct 23 '17 at 20:44
  • @isosceleswheel - take a look at this - unix.stackexchange.com/questions/94168/…. – slm Oct 23 '17 at 21:38
  • It also worked for wav files. – Mário Meyrelles Dec 20 '17 at 13:44

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 subprocess
import sys


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.

  • 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 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. – isosceleswheel Feb 1 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 Smith Jun 18 at 16:56
  • 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 Smith Jun 18 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. – isosceleswheel Jun 19 at 17:48

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.

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

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

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

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.