As lately I am encountering a lot of split video files with .srt subtitle i just wrote a simple script that will concat the subtitles with the correct timing shift.
It just requires mencoder and mplayer installed to do the concatenation operation. The script does not support mkv files as they have embedded subtitles and it needs some mkv toll operation, but usually mkv files are not senslessly splitted anyway
All the code can be found on github
Usage is really simple.
If you have file1.avi file2.avi file1.srt file2.srt just do:
perl concat-movie.pl file1.avi file2.avi output.avi
and you’ll have output.avi and output.srt ready to be used, or even:
perl concat-movie.pl file1.avi file2.avi output.mp4
and the output will use .mp4 as container (check mplayer manuals for the formats)
Here is the script.
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
sub add_time($);
sub shift_sub($$$);
croak "Wrong number of arguments" if (@ARGV != 3);
my $file1 = shift;
my $file2 = shift;
my $output = shift;
$output =~ /(.*)\..*/;
my $srt_output = "$1.srt";
$file1 =~ /(.*)\..*/;
my $srt1 = "$1.srt";
$file2 =~ /(.*)\..*/;
my $srt2 = "$1.srt";
croak "Input $file1 non existent" if (!-e$file1);
croak "Input $file2 non existent" if (!-e$file2);
croak "Input $srt1 non existent" if (!-e$srt1);
croak "Input $srt2 non existent" if (!-e$srt2);
croak "Output $output exists" if (-e$output);
croak "Output $srt_output exists" if (-e$srt_output);
# get file1 length
my $file1_length = 0;
open(INFO,"mplayer -vo null -nosound -frames 0 -identify '$file1'|");
foreach() {
$file1_length = $1 if(/^ID_LENGTH=(.*)\..*/);
}
close INFO;
# convert $file1_length in $h,$m,$s
my ($h,$m,$s);
$s = $file1_length % 60;
$m = int ($file1_length % (60*60))/60;
$h = int ($file1_length % (60*60*24))/(60*60);
# concatenate the subs
shift_sub($srt1,$srt2,$srt_output);
# concatenate the movie
system("mencoder -ovc copy -oac copy '$file1' '$file2' -o '$output'");
sub shift_sub($$$) {
my ($file1,$file2,$output) = @_;
open OUTPUT, ">$output" or croak "can't open $output";
open FILE, $file1 or croak "can't open $file1";
my $idx_shift = 0;
while(!eof(FILE)) { # pass trough storing maximum starting index
$_ = ;
print OUTPUT;
if (/^(\d+)\r\n$/) {
chomp;
$idx_shift = $_;
}
}
close FILE;
open FILE, $file2 or croak "can't open $file2";
while(!eof(FILE)) {
# srt idx
my $num = ; # print index
print OUTPUT $num+$idx_shift."\r\n";
# srt time
my $timing = ;
my ($start,$end) = split(/\s-->\s/,$timing);
print OUTPUT add_time($start)." --> ".add_time($end)."\r\n";
# srt text
my $line;
do {
$line = ;
print OUTPUT $line;
} while (!($line =~ m/^\r\n$/));
}
close FILE;
}
sub add_time($) {
my ($hh,$mm,$ss,$sss) = split(/[:,]/,$_[0]);
$ss += $s; $mm += $m; $hh += $h;
if ( $ss > 60 ) { $mm++; $ss -= 60; }
if ( $mm > 60 ) { $hh++; $mm -= 60; }
return sprintf("%03d:%02d:%02d,%03d",$hh,$mm,$ss,$sss);
}
#1 by Adam Pierce on January 23, 2011 - 10:46 pm
Doesn’t work for me on Ubuntu 10.04:
$ perl concat-movie.pl Tampopo.cd1.avi Tampopo.cd2.avi Tampopo.avi
“my” variable $s masks earlier declaration in same scope at concat-movie.pl line 39.
“my” variable $m masks earlier declaration in same scope at concat-movie.pl line 40.
“my” variable $file1_length masks earlier declaration in same scope at concat-movie.pl line 40.
“my” variable $h masks earlier declaration in same scope at concat-movie.pl line 41.
“my” variable $file1_length masks earlier declaration in same scope at concat-movie.pl line 41.
syntax error at concat-movie.pl line 32, near “() ”
Can’t use global @_ in “my” at concat-movie.pl line 50, near “= @_”
syntax error at concat-movie.pl line 56, near “= ;”
syntax error at concat-movie.pl line 68, near “= ;”
Global symbol “$idx_shift” requires explicit package name at concat-movie.pl line 69.
syntax error at concat-movie.pl line 72, near “= ;”
syntax error at concat-movie.pl line 79, near “= ;”
syntax error at concat-movie.pl line 84, near “}”
Can’t use global @_ in “my” at concat-movie.pl line 87, near “,$_”
Global symbol “$s” requires explicit package name at concat-movie.pl line 88.
Global symbol “$m” requires explicit package name at concat-movie.pl line 88.
Global symbol “$h” requires explicit package name at concat-movie.pl line 88.
syntax error at concat-movie.pl line 92, near “}”
concat-movie.pl has too many errors.
#2 by Dario Meloni on January 23, 2011 - 10:54 pm
Clearly something got messed up when you copied it. I’ll create a repository for the script on github to host it.
I know it works as I used it just a while ago on the same distribution.
https://github.com/mellon85/concat-movie