Archive for category perl

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

2 Comments