use strict; if (@ARGV < 2) { print STDERR "syntax: $0 hh:mm:ss.hhh hh:mm:ss.hhh file.srt\n"; print STDERR "where the times are the start of the first subtitle\n"; print STDERR "and the end of the last subtitle, respectively.\n"; exit; } my $newStart = timeToMilliseconds(shift); my $newEnd = timeToMilliseconds(shift); my @subtitles = (); while (<>) { # the ID my $time = <>; # the time my $text = ""; while (($_ = <>) !~ m/^\s*$/os) { # the subtitle lines $text .= $_; } $time =~ m/(\d+:\d+:\d+.\d+) --> (\d+:\d+:\d+.\d+)/os or die "$0:$ARGV:$.: block in unexpected format\n"; my $start = $1; my $end = $2; push(@subtitles, { start => timeToMilliseconds($start), end => timeToMilliseconds($end), text => $text, }); } my $oldStart = $subtitles[0]->{start}; my $oldEnd = $subtitles[$#subtitles]->{end}; my $oldLength = $oldEnd - $oldStart; my $newLength = $newEnd - $newStart; my $scale = $newLength / $oldLength; my $id = 0; foreach (@subtitles) { print ++$id; print "\n"; print millisecondsToTime(($_->{start} - $oldStart) * $scale + $newStart); print ' --> '; print millisecondsToTime(($_->{end} - $oldStart) * $scale + $newStart); print "\n"; print $_->{text}; print "\n"; } sub timeToMilliseconds($) { shift =~ m/(\d+):(\d+):(\d+).(\d+)/os or die 'time in unexpected format'; return $4 + $3 * 1000 + $2 * 1000 * 60 + $1 * 1000 * 60 * 60; } sub millisecondsToTime($) { my $milliseconds = shift; my $hours = int($milliseconds / 1000 / 60 / 60); $milliseconds -= $hours * 1000 * 60 * 60; my $minutes = int($milliseconds / 1000 / 60); $milliseconds -= $minutes * 1000 * 60; my $seconds = int($milliseconds / 1000); $milliseconds -= $seconds * 1000; $milliseconds = int($milliseconds); $hours = "0$hours" if $hours < 10; $minutes = "0$minutes" if $minutes < 10; $seconds = "0$seconds" if $seconds < 10; $milliseconds = "0$milliseconds" if $milliseconds < 100; $milliseconds = "0$milliseconds" if $milliseconds < 10; return "$hours:$minutes:$seconds.$milliseconds"; }