annotate TOOLS/subedit.pl @ 17835:b493e5ba8741

strings without terminating NUL
author ods15
date Sun, 12 Mar 2006 20:44:22 +0000
parents 401b440a6d76
children 92a795af2600
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12686
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
1 #!/usr/bin/perl -w
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
2
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
3 # A script for pipelined editing of subtitle files.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
4 # Copyright (C) 2004 Michael Klepikov <mike72@mail.ru>
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
5 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
6 # Version 1.0 initial release 28-Mar-04
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
7 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
8 # Comments, suggestions -- send me an mail, but the recommended way is
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
9 # to enhance/fix on your own and submit to the distribution;)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
10 # If you like, I can review the fixes.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
11 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
12 # This script is free software; you can redistribute it and/or
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
13 # modify it under the terms of the GNU Lesser General Public
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
14 # License as published by the Free Software Foundation; either
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
15 # version 2 of the License, or (at your option) any later version.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
16 # Retain original credits when modifying.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
17 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
18 # This script is distributed in the hope that it will be useful,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
21 # Lesser General Public License for more details.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
22 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
23 # You should have received a copy of the GNU Lesser General Public
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
24 # License along with this library; if not, write to the Free Software
17367
401b440a6d76 Update licensing information: The FSF changed postal address.
diego
parents: 12686
diff changeset
25 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12686
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
26 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
27
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
28 use Math::BigInt;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
29
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
30 # Constants
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
31 my $FMT_UNKNOWN = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
32 my $FMT_SRT = 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
33
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
34 # Argument values
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
35 my $DEBUG = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
36 my $inFormat;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
37 my $outFormat;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
38 my $shiftMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
39 my $scaleMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
40 my $splitFromMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
41 my $splitToMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
42
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
43 ## Process command line
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
44 while (defined ($argVal = shift)) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
45 if ($argVal eq "-d" || $argVal eq "--debug") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
46 $DEBUG = 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
47 } elsif ($argVal eq "-if" || $argVal eq "--input-format") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
48 $inFormat = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
49 usage ("Must specify input format") if ! $inFormat;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
50 if ($inFormat =~ /^srt/i) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
51 $inFormat = $FMT_SRT;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
52 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
53 usage ("Invalid input format");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
54 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
55 } elsif ($argVal eq "-of" || $argVal eq "--output-format") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
56 $outFormat = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
57 usage ("Must specify input format") if ! $outFormat;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
58 if ($outFormat =~ /^srt/i) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
59 $outFormat = $FMT_SRT;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
60 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
61 usage ("Invalid output format");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
62 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
63 } elsif ($argVal eq "-s" || $argVal eq "--shift") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
64 my $argTime = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
65 if (! defined $argTime ||
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
66 ! defined ($shiftMilli = getTimeMillis ($argTime))) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
67 usage ("Invalid shift time value");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
68 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
69 } elsif ($argVal eq "-c" || $argVal eq "--scale") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
70 my $argTime = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
71 if (! defined $argTime ||
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
72 ! defined ($scaleMilli = getTimeMillis ($argTime))) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
73 usage ("Invalid scale time value");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
74 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
75 } elsif ($argVal eq "-f" || $argVal eq "--split-from") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
76 my $argTime = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
77 if (! defined $argTime ||
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
78 ! defined ($splitFromMilli = getTimeMillis ($argTime))) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
79 usage ("Invalid split start time value");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
80 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
81 } elsif ($argVal eq "-t" || $argVal eq "--split-to") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
82 my $argTime = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
83 if (! defined $argTime ||
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
84 ! defined ($splitToMilli = getTimeMillis ($argTime))) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
85 usage ("Invalid split end time value");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
86 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
87 } elsif ($argVal eq "-h" || $argVal eq "--help") {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
88 usage ();
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
89 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
90 usage ("Unrecognized argument $argVal");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
91 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
92 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
93
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
94 # Input format defaults to SRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
95 $inFormat = $FMT_SRT if (! defined $inFormat);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
96 # Output format defaults to the same as input
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
97 $outFormat = $inFormat if (! defined $outFormat);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
98
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
99 ## Read
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
100
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
101 my $subs;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
102 if ($inFormat == $FMT_SRT) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
103 $subs = readSRT (*STDIN);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
104 printf STDERR ("Read %d SRT subs\n", scalar @{$subs}) if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
105 # Sort by start time
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
106 @{$subs} = sort {$a -> {srtStartTime} <=> $b -> {srtEndTime}} @{$subs};
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
107 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
108
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
109 ## Transform
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
110
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
111 if (defined $shiftMilli && 0 != $shiftMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
112 printf STDERR ("Shift: %d milliseconds\n", $shiftMilli) if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
113 shiftSRT ($subs, $shiftMilli);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
114 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
115
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
116 if (defined $splitFromMilli || defined $splitToMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
117 if ($DEBUG) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
118 my $printFrom = (defined $splitFromMilli) ? $splitFromMilli : "-";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
119 my $printTo = (defined $splitToMilli) ? $splitToMilli : "-";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
120 printf STDERR ("Split: from $printFrom to $printTo\n");
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
121 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
122 splitSRT ($subs, $splitFromMilli, $splitToMilli);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
123 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
124
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
125 if (defined $scaleMilli && 0 != $scaleMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
126 my $lastSubIdx = scalar @{$subs} - 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
127 if ($lastSubIdx >= 0) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
128 my $lastTimeOrig = $subs -> [$lastSubIdx] -> {srtEndTime};
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
129 if ($lastTimeOrig == 0) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
130 die "Cannot scale when last subtitle ends at 00:00:00,000";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
131 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
132 my $lastTimeScaled = $lastTimeOrig + $scaleMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
133 printf STDERR ("Scale: %d/%d\n", $lastTimeScaled, $lastTimeOrig) if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
134 scaleSRT ($subs, $lastTimeScaled, $lastTimeOrig);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
135 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
136 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
137
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
138 ## Write
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
139 if ($outFormat == $FMT_SRT) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
140 writeSRT (*STDOUT, $subs);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
141 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
142
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
143 # Close STDOUT, as recommended by Perl manual
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
144 # (allows diagnostics on disc overflow, etc.)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
145 close (STDOUT) || die "Cannot close output stream: $!";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
146
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
147 exit 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
148
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
149 ## Subroutines
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
150
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
151 # Convert string time format to milliseconds
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
152 # SRT style: "01:20:03.251", and "," is allowed instead of "."
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
153 # Return undef in case of format error
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
154 sub getTimeMillis
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
155 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
156 $_ = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
157 my $millis = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
158
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
159 if (/\s*(.*)[\.,]([0-9]+)?\s*$/) { # Fraction; strip surrounding spaces
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
160 #print STDERR "frac: \$1=$1 \$2=$2\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
161 $_ = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
162 $millis += ("0." . $2) * 1000 if $2;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
163 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
164 if (/(.*?)([0-9]+)$/) { # Seconds
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
165 #print STDERR "secs: \$1=$1 \$2=$2\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
166 $_ = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
167 $millis += $2 * 1000 if $2;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
168 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
169 if (/(.*?)([0-9]+):$/) { # Minutes
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
170 #print STDERR "mins: \$1=$1 \$2=$2\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
171 $_ = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
172 $millis += $2 * 60000 if $2;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
173 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
174 if (/(.*?)([0-9]+):$/) { # Hours
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
175 #print STDERR "mins: \$1=$1 \$2=$2\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
176 $_ = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
177 $millis += $2 * 3600000 if $2;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
178 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
179 if (/(.*?)\-$/) { # Minus sign
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
180 $_ = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
181 $millis *= -1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
182 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
183 $millis = undef if (! /^$/); # Make sure we ate everything up
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
184 if ($DEBUG) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
185 if (defined $millis) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
186 #print STDERR "time value match: $millis ms\n";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
187 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
188 #print STDERR "time mismatch\n";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
189 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
190 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
191 return $millis;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
192 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
193
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
194 # Convert milliseconds to SRT formatted string
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
195 sub getTimeSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
196 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
197 my $t = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
198 my $tMinus = "";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
199 if ($t < 0) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
200 $t = -$t;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
201 $tMinus = "-";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
202 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
203 my $tMilli = $t % 1000;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
204 $t /= 1000;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
205 my $tSec = $t % 60;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
206 $t /= 60;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
207 my $tMin = $t % 60;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
208 $t /= 60;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
209 my $tHr = $t;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
210 return sprintf ("%s%02d:%02d:%02d,%03d",
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
211 $tMinus, $tHr, $tMin, $tSec, $tMilli);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
212 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
213
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
214 # Read SRT subtitles
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
215 sub readSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
216 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
217 local *IN = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
218 my $subs = [];
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
219
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
220 $_ = <IN>;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
221 print STDERR "Undefined first line\n" if ! defined $_ && $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
222 my $lineNo = 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
223 READ_SUBS:
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
224 while (defined $_) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
225 # Each loop iteration reads one subtitle from <IN>
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
226 my $sub = {};
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
227
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
228 # print STDERR "Reading line $lineNo\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
229
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
230 # Skip empty lines
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
231 while (/^\s*$/) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
232 last READ_SUBS if ! ($_ = <IN>);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
233 ++$lineNo;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
234 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
235
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
236 # Subtitle number
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
237 if (/^\s*([0-9]+)\s*$/) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
238 $sub -> {srtNumber} = $1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
239 # print "SRT num: $1\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
240 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
241 die "Invalid SRT format at line $lineNo";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
242 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
243
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
244 # Timing
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
245 if ($_ = <IN>) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
246 ++$lineNo;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
247 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
248 die "Unexpected end of SRT stream at line $lineNo";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
249 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
250 # print STDERR "LINE: $_\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
251 if (/^\s*(\S+)\s*--\>\s*(\S+)\s*$/) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
252 my $startMillis = getTimeMillis ($1);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
253 my $endMillis = getTimeMillis ($2);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
254 die "Invalid SRT timing format at line $lineNo: $_"
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
255 if ! defined $startMillis || ! defined $endMillis;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
256 $sub -> {srtStartTime} = $startMillis;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
257 $sub -> {srtEndTime} = $endMillis;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
258 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
259 die "Invalid SRT timing format at line $lineNo: $_";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
260 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
261
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
262 # Text lines
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
263 my $subLines = [];
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
264 while (1) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
265 last if ! ($_ = <IN>); # EOF ends subtitle
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
266 ++$lineNo;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
267 last if /^\s*$/; # Empty line ends subtitle
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
268 ($_ = $_) =~ s/\s+$//; # Strip trailing spaces
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
269 push @{$subLines}, $_;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
270 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
271 die "No text in SRT subtitle at line $lineNo" if 0 == scalar @{$subLines};
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
272 $sub -> {lines} = $subLines;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
273
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
274 # Append subtitle to the list
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
275 push @{$subs}, $sub;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
276 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
277 print STDERR "SRT read ok, $lineNo lines\n" if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
278
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
279 return $subs;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
280 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
281
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
282 # Write SRT subtitles
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
283 sub writeSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
284 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
285 use integer; # For integer division
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
286 local *OUT = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
287 my $subs = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
288
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
289 my $subNum = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
290 foreach (@{$subs}) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
291 ++$subNum;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
292
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
293 my $sub = $_;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
294 my $sTimeSRT = getTimeSRT ($sub -> {srtStartTime});
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
295 my $eTimeSRT = getTimeSRT ($sub -> {srtEndTime});
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
296 printf OUT ("%d\n%s --> %s\n", $subNum, $sTimeSRT, $eTimeSRT);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
297 foreach (@{$sub -> {lines}}) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
298 printf OUT ("%s\n", $_);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
299 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
300 printf OUT "\n";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
301 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
302 printf STDERR ("Wrote %d SRT subs\n", $subNum) if $DEBUG;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
303 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
304
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
305 # Shift SRT subtitles by a given number of seconds.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
306 # The number may be negative and fractional.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
307 sub shiftSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
308 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
309 use integer; # $shiftMilli could be passed as float
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
310 my $subs = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
311 my $shiftMilli = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
312
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
313 foreach (@{$subs}) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
314 $_ -> {srtStartTime} += $shiftMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
315 $_ -> {srtEndTime} += $shiftMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
316 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
317 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
318
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
319 # Multiply each subtitle timing by a divident and divide by divisor.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
320 # The idea is that the divident is usually the new total number of
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
321 # milliseconds in the subtitle file, and the divisor is the old
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
322 # total number of milliseconds in the subtitle file.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
323 # We could simply use a double precision real coefficient instead of
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
324 # integer divident and divisor, and that could be good enough, but
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
325 # using integer arithmetics *guarantees* precision up to the last
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
326 # digit, so why settle for good enough when we can have a guarantee.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
327 #
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
328 # Uses Math::BigInt arithmetics, because it works with numbers
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
329 # up to (total number of milliseconds for a subtitle timing)^2,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
330 # which could be on the order of approximately 1e+13, which is
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
331 # larger than maximum 32-bit integer.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
332 # There is a performance loss when using BigInt vs. regular floating
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
333 # point arithmetics, but the actual performance is quite acceptable
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
334 # on files with a few thousand subtitles.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
335 sub scaleSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
336 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
337 use integer; # Divident and divisor could be passed as floats, truncate
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
338 my $subs = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
339 my $scaleDividend = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
340 my $scaleDivisor = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
341
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
342 foreach (@{$subs}) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
343 my $ss = Math::BigInt -> new ($_ -> {srtStartTime});
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
344 $ss = $ss -> bmul ($scaleDividend);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
345 $_ -> {srtStartTime} = $ss -> bdiv ($scaleDivisor) -> bsstr ();
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
346 my $se = Math::BigInt -> new ($_ -> {srtEndTime});
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
347 $se = $se -> bmul ($scaleDividend);
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
348 $_ -> {srtEndTime} = $se -> bdiv ($scaleDivisor) -> bsstr ();
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
349 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
350 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
351
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
352 # Extract a fragment within a given time interval
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
353 # Either "from" or "to" may be undefined
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
354 sub splitSRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
355 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
356 use integer; # fromMilli and toMilli could be passed as floats, truncate
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
357 my $subs = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
358 my $fromMilli = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
359 my $toMilli = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
360
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
361 my $iSub = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
362 while ($iSub < scalar @{$subs}) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
363 $_ = $subs -> [$iSub];
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
364 my $keep = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
365 if (! defined $fromMilli || $_ -> {srtEndTime} >= $fromMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
366 # The subtitle ends later than the start boundary
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
367
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
368 # Fix overlapping start timing,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
369 # but only of the start boundary is not infinite (undef)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
370 if (defined $fromMilli && $_ -> {srtStartTime} < $fromMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
371 $_ -> {srtStartTime} = $fromMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
372 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
373 if (! defined $toMilli || $_ -> {srtStartTime} <= $toMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
374 # The subtitle begins earlier than the end boundary
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
375
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
376 # Fix overlapping end timing,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
377 # but only of the end boundary is not infinite (undef)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
378 if (defined $toMilli && $_ -> {srtEndTime} > $toMilli) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
379 $_ -> {srtEndTime} = $toMilli;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
380 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
381
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
382 # All conditions met, all fixes done
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
383 $keep = 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
384 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
385 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
386 if ($keep) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
387 ++$iSub;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
388 } else {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
389 splice @{$subs}, $iSub, 1;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
390 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
391 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
392 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
393
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
394 # Print brief usage help
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
395 # Accepts an optional error message, e.g. for errors parsing command line
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
396 sub usage
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
397 {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
398 my $msg = shift;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
399 my $exitCode = 0;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
400
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
401 if (defined $msg) {
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
402 $exitCode = 2;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
403 print STDERR "$msg\n";
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
404 }
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
405
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
406 print STDERR <<USAGE;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
407 Usage: $0 [switches]
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
408 -if,--input-format <fmt> input format; supported: SRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
409 default is SRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
410 -of,--output-format <fmt> output format; supported: SRT
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
411 default is same as input format
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
412 -s,--shift <time> shift all subtitles by <time>
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
413 (format: [-]hh:mm:ss,fraction)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
414 -c,--scale <time> scale by adding <time> to overall duration
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
415 -f,--split-from <time> Drop subtitles that end before <time>
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
416 -t,--split-to <time> Drop subtitles that start after <time>
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
417 (will truncate timing if it overlaps a boundary)
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
418 -r,--renumber renumber SRT subtitles in output
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
419 -d,--debug enable debug output
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
420 -h,--help this help message
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
421
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
422 All times could be negative. Input/output may also contain negative timings,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
423 which is sometimes useful for intermediate results.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
424 SRT subtitles are always renumbered on output.
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
425
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
426 EXAMPLES
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
427
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
428 Split subtitle file into two disks at a boundary of one hour 15 minutes:
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
429
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
430 subedit.pl --split-to 1:15:0 < all.srt > p1.srt
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
431 subedit.pl -f 1:15:0 < all.srt | subedit.pl --shift -1:15:0 > p2.srt
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
432
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
433 Join the previous two disks back into one file:
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
434
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
435 subedit.pl -s 1:15:00 < p2.srt | cat p1.srt - | subedit.pl > all.srt
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
436
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
437 Correct a situation where the first subtitle starts in sync with the video,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
438 but the last one starts 3.5 seconds earlier than the speech in the video,
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
439 assuming the first subtitle timing is 00:01:05.030:
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
440
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
441 subedit.pl -s -1:5.03 | subedit.pl -c 3.5 | subedit.pl -s 1:5.03
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
442 USAGE
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
443
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
444 exit $exitCode;
cc5aa27a50ff simple subtitle editor by Michael Klepikov
alex
parents:
diff changeset
445 }