Concat videos with srt subtitle

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);
}
Advertisements
  1. #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. #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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: