Log in

View Full Version : Joining MKV files and chapters


pelle412
18th May 2010, 01:24
I'd like to join two MKV files using mkvmerge and have the chapters intact, i.e. have mkvmerge recalculate chapter offsets. I can't seem to accomplish this. Any ideas?

Mosu
19th May 2010, 14:57
mkvmerge does that automatically. Make sure you actually append the two files. The difference between "mkvmerge -o out.mkv in1.mkv in2.mkv" and "mkvmerge -o out.mkv in1.mkv +in2.mkv" are subtle, but the resulting files are completely different. Same goes for using mmg; use the "add" button for the first and the "append" button for the second file.

pelle412
26th May 2010, 18:43
mkvmerge does that automatically. Make sure you actually append the two files. The difference between "mkvmerge -o out.mkv in1.mkv in2.mkv" and "mkvmerge -o out.mkv in1.mkv +in2.mkv" are subtle, but the resulting files are completely different. Same goes for using mmg; use the "add" button for the first and the "append" button for the second file.

That works fine for video, audio, and subtitles, but it really doesn't work for chapters. If you look in the MMG window when appending files you see the ++ signs appearing next to video, audio, and subs, but it doesn't for chapters.

I solved the problem by writing my own program that takes a chapter file and rewrites it based on a new starting chapter, and length of previous video file so I can concatenate them manually, and add them in to the final MKV.

@MeGui
26th May 2010, 20:37
Can we see your small program here?

pelle412
29th May 2010, 03:07
Can we see your small program here?

Sure. Unrefined C code hack.

#include <stdio.h>
#include <stdlib.h>

// use: chapadd chap_start_num time_to_add chapter_file

// limitation: < 100 chapters

int main(int argc, char **argv) {
int hour, min, sec, thousands;
int chap_num;
int h, m, s, t;
FILE *fp;
char buffer[128];

if (argc != 4) {
fprintf(stderr, "Usage: chapadd chapter_start start_time chapter_file\n");
fprintf(stderr, " - chapter_start: the new chapter to start at\n");
fprintf(stderr, " - start_time: length of first movie file [hh:mm:ss.hhh]\n");
fprintf(stderr, " - chapter_file: OGG chapter file to rewrite\n");
return 0;
}

chap_num = atoi(argv[1]);
sscanf(argv[2], "%d:%d:%d.%d", &hour, &min, &sec, &thousands);
fp = fopen(argv[3], "rt");
if (fp == NULL) {
fprintf(stderr, "Error opening OGG chapter file.\n");
return 0;
}

// Loop through chapter file
// Expected input format:
// CHAPTERnn=hh:mm:ss.hhh
// CHAPTERnnNAME=Chapter n
while (fgets(buffer, 128, fp) != NULL) {
sscanf(&buffer[10], "%d:%d:%d.%d", &h, &m, &s, &t);
t += thousands;
if (t >= 1000) {
s++;
t -= 1000;
}
s += sec;
if (s >= 60) {
m++;
s -= 60;
}
m += min;
if (m >= 60) {
h++;
m -= 60;
}
h += hour;
// output new chapter data to stdout (user can copy/paste from there)
printf("CHAPTER%02d=%02d:%02d:%02d.%03d\n", chap_num,
h, m, s, t);
printf("CHAPTER%02dNAME=Chapter %d\n", chap_num, chap_num);
chap_num++;
fgets(buffer, 128, fp); // discard the second line of each chapter
}

fclose(fp);
return 0;
}