14

I have a long MKV file which I want to split into its individual chapters.

Running ffmpeg -i long.mkv gives me all the information about the chapters embedded in the file:

 Duration: 01:23:45.80, start: 0.000000, bitrate: 8116 kb/s
    Chapter #0.0: start 0.000000, end 235.000000
    Metadata:
      title           : Chapter 01
    Chapter #0.1: start 235.000000, end 450.160000
    Metadata:
      title           : Chapter 02
    Chapter #0.2: start 450.160000, end 789.400000
    ...

There are 10 chapters in the file - I want to end up with 10 separate files.

It looks like -map_chapters might to something similar - but I can't find any documentation on it.

Hennes
  • 64,768
  • 7
  • 111
  • 168
Terence Eden
  • 813
  • 2
  • 7
  • 22

5 Answers5

24

split mkv video by chapters using mkvmerge

mkvmerge -o output.mkv --split chapters:all input.mkv

https://www.bunkus.org/videotools/mkvtoolnix/doc/mkvmerge.html

Endoro
  • 2,854
  • 1
  • 17
  • 17
  • 2
    Unfortunately, since MKVmerge can only split on keyframes, this only works if there's a keyframe at the exact time as the chapter time for each chapter. If not, some or all of your chapters will contain parts of other chapters. Still haven't found a solution that works on exact times regardless of keyframes. – Natsukane Oct 31 '18 at 20:42
  • You may try [Avidemux](http://avidemux.sourceforge.net/) to split between key frames (inside the [GOP](https://en.wikipedia.org/wiki/Group_of_pictures)). – Endoro Nov 01 '18 at 01:15
9

I can't find a reliable way to do this with ffmpeg / avconv - but I can find a way to do this with HandBrakeCLI.

 HandBrakeCLI -c 3 -i whatever.mkv -o 3.mkv

Will extract chapter 3 from an mkv.

Terence Eden
  • 813
  • 2
  • 7
  • 22
  • 2
    This looks like it does what I want, but is it truely only extracting a chapter, or will this re-encode the entire chapter? Because it's my understanding that the Handbrake team considers anything not related to transcoding as out-of-scope, which makes me suspicious this will re-encode a file I only want to trim. – Tim M. Dec 28 '18 at 05:17
  • According to [Handbrake documentation](https://handbrake.fr/docs/en/latest/cli/cli-options.html) this will indeed re-encode the video using the "Normal" preset, and not just extract. – LapplandsCohan Jun 26 '20 at 20:48
4

brute force solution, hehe:

ffmpeg -i long.mkv | grep 'start.*end.*[0-9]*' | sed -r 's/.*#[0-9]\.([0-9]*).* ([0-9]*\.[0-9]*).*( [0-9]*\.[0-9]*)/ ffmpeg -i long.mkv -ss \2 -to\3 -acodec copy -vcodec copy chapter\1.mkv/g;'

You can add xargs to run the output in cowboy style: | xargs -I cmd bash -c 'cmd'

gabriel_agm
  • 323
  • 3
  • 12
0

This is my solution, it works well on ubuntu-16.04.02-LTS. It is based on another posted solution but has improved handling of chapters and the generated files for each chapter.

This is a sample execution:

$ mkv-split-chapters some-mkv-file.mkv
Filename: some-mkv-file
Extension: mkv
Filedir: .
ffmpeg -i some-mkv-file.mkv -ss 0.000000 -to 394.800000 -acodec copy -vcodec copy ./some-mkv-file-#00.mkv
[...]
ffmpeg -i some-mkv-file.mkv -ss 394.800000 -to 767.160000 -acodec copy -vcodec copy ./some-mkv-file-#01.mkv
[...]
ffmpeg -i some-mkv-file.mkv -ss 757.160000 -to 1216.720000 -acodec copy -vcodec copy ./some-mkv-file-#02.mkv
[...]

This is the script:

$ cat /usr/local/bin/mkv-split-chapters
#!/bin/bash
file="$1"
if [ -z "$file" ]; then
        echo "Missing file argument!"
        exit 1
fi

filename=$(basename "$file")
fileextension="${filename##*.}"
filename="${filename%.*}"
filedir=$(dirname "$file")
echo "Filename: $filename"
echo "Extension: $fileextension"
echo "Filedir: $filedir"
ffmpeg -i $file 2>&1 | grep 'Chapter' | grep 'start' | grep ', end' | awk "{
        chapter=\$2
        # replace : with nil
        gsub(/:/, \"\", chapter)
        start=\$4
        # remove everything but 0-9.
        gsub(/[^0123456789\.]/, \"\", start)
        end=\$6
        command=sprintf(\"ffmpeg -i $file -ss %s -to %s -acodec copy -vcodec copy $filedir/$filename-%s.$fileextension\n\", start, end, chapter)
        print(command)
        system(command)
}"

The script is also available here:

https://github.com/dpsenner/mkv-split-chapters

0

You can use the open source GUI program called LosslessCut. It losslessly cuts popular formats like mp4 and mkv instantly without reencoding the video. It works really well.

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 19 '22 at 13:47