Find subtitles under MacOSX/Linux

There are a plethora of subtitle finders for Windows but only a few for MacOSX and Linux. Most of them often don’t work.

Searching for the right subtitle for a specific avi file can be frustrating. It’s not enough to match the filename. It’s always better to rely on the hash of the movie to find a properly sync’ed subtitle.

Fortunately, OpenSubtitles.org started offering a nice and easy interface to search their subtitle database. Here is a simple script I found on opensubtitles.org site and modified for my needs. It will help you to find the subtitles for your favourite movies and tv series:


#!/usr/bin/perl
# http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
use strict;
use warnings;
my $file = $ARGV[0];
unless (defined($file) and -r $file) { print "Syntax: $0 /path/file.avi\n"; }
my $hash = OpenSubtitlesHash($file);
print "
Now visit:
ALL: http://www.opensubtitles.org/search/sublanguageid-all/moviehash-$hash
English: http://www.opensubtitles.org/search/sublanguageid-eng/moviehash-$hash
Polish: http://www.opensubtitles.org/search/sublanguageid-pol/moviehash-$hash
Italian: http://www.opensubtitles.org/search/sublanguageid-ita/moviehash-$hash
";
sub OpenSubtitlesHash {
my $filename = shift or die("Need video filename");
open my $handle, "<", $filename or die $!; binmode $handle; my $fsize = -s $filename; my $hash = [$fsize & 0xFFFF, ($fsize >> 16) & 0xFFFF, 0, 0];
$hash = AddUINT64($hash, ReadUINT64($handle)) for (1..8192);
my $offset = $fsize - 65536;
seek($handle, $offset > 0 ? $offset : 0, 0) or die $!;
$hash = AddUINT64($hash, ReadUINT64($handle)) for (1..8192);
close $handle or die $!;
return UINT64FormatHex($hash);
}
sub ReadUINT64 {
read($_[0], my $u, 8);
return [unpack("vvvv", $u)];
}
sub AddUINT64 {
my $o = [0,0,0,0];
my $carry = 0;
for my $i (0..3) {
if (($_[0]->[$i] + $_[1]->[$i] + $carry) > 0xffff ) {
$o->[$i] += ($_[0]->[$i] + $_[1]->[$i] + $carry) & 0xffff;
$carry = 1;
} else {
$o->[$i] += ($_[0]->[$i] + $_[1]->[$i] + $carry);
$carry = 0;
}
}
return $o;
}
sub UINT64FormatHex {
return sprintf("%04x%04x%04x%04x", $_[0]->[3], $_[0]->[2], $_[0]->[1], $_[0]->[0]);
}

Share

Leave a Reply