Split MKV based on Chapters

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.

2

5 Answers

split mkv video by chapters using mkvmerge

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

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.

2

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\

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

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:

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

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like