Sync subtitles
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Sync subtitles
Sync subtitles
Sometimes, when you download a movie, the subtitles are out of sync with the audio in this movie. Video players like VLC solve the problem, but it must be done manually.
Make a program that takes the "movie.srt" file, and synchronizes the subtitles "n" seconds.
- Try to fast-forward the subtitles by 9 seconds.
- Try rolling back the subtitles by 9 seconds.
Take the excerpt from the following subtitles file as an example:
movie.srt
1 00:01:31,550 --> 00:01:36,347 Four billion years ago, the first marine life forms. 2 00:01:36,555 --> 00:01:42,019 First came the fish...then slowly other life forms evolved. 3 00:01:42,144 --> 00:01:43,979 Therefore, our ancestors... 4 00:01:43,979 --> 00:01:45,898 ...came from fish. 5 00:01:46,232 --> 00:01:47,608 Everyone, come and see this. 6 00:01:47,733 --> 00:01:50,361 Cretaceous Tyrannosaurus. 7 00:01:50,736 --> 00:01:52,488 Ferocious! 8 00:01:58,035 --> 00:01:58,869 Red, 9 00:01:59,203 --> 00:02:00,079 Pong! 10 00:02:02,540 --> 00:02:03,999 Isn't this a gecko? 11 00:02:04,416 --> 00:02:07,419 How else can I get a 15 ton T-Rex in here? 12 00:02:07,503 --> 00:02:11,048 With our advanced technology, I shrank it down.
Amazing Hopper
#include <basico.h>
algoritmo
fd=0
abrir para leer ( "movie.srt", fd )
iterar
s="", t1=0, t2=0, s1=0, s2=0
usando '1000', leer línea desde 'fd', mover a 's'
cuando ( "-->", está exactamente en 's' ){
[1:8] obtener de 's', ---copiar en 's1'---
convertir a segundos, sumarle '9', convertir a hora, guardar en 't1'
[18:25] obtener de 's', ---copiar en 's2'---
convertir a segundos, sumarle '9', convertir a hora, guardar en 't2'
transformar(s1,t1,s), guardar en 's'
transformar(s2,t2,s), guardar en 's'
}
imprimir ( s, "\n")
mientras ' no sea fin de archivo (fd ) '
cerrar archivo 'fd'
terminar
- Output:
$ hopper3 basica/modsrt.bas > movie_corrected.srt $ cat movie_corrected.srt 1 00:01:40,550 --> 00:01:45,347 Four billion years ago, the first marine life forms. 2 00:01:45,555 --> 00:01:51,019 First came the fish...then slowly other life forms evolved. 3 00:01:51,144 --> 00:01:52,979 Therefore, our ancestors... 4 00:01:52,979 --> 00:01:54,898 ...came from fish. 5 00:01:55,232 --> 00:01:56,608 Everyone, come and see this. 6 00:01:56,733 --> 00:01:59,361 Cretaceous Tyrannosaurus. 7 00:01:59,736 --> 00:02:01,488 Ferocious! 8 00:02:07,035 --> 00:02:07,869 Red, 9 00:02:08,203 --> 00:02:09,079 Pong! 10 00:02:11,540 --> 00:02:12,999 Isn't this a gecko? 11 00:02:13,416 --> 00:02:16,419 How else can I get a 15 ton T-Rex in here? 12 00:02:16,503 --> 00:02:20,048 With our advanced technology, I shrank it down.
BASIC
BASIC256
f = freefile
print "After fast-forwarding 9 seconds:" + chr(10)
call syncSubtitles("movie.srt", "movie_corrected.srt", 9)
open f, "movie_corrected.srt"
while not eof(f)
linea = readline (f)
print linea;
end while
close
print chr(10) + chr(10)
print "After rolling-back 9 seconds:" + chr(10)
call syncSubtitles("movie.srt", "movie_corrected2.srt", -9)
open f, "movie_corrected2.srt"
while not eof(f)
linea = readline (f)
print linea;
end while
close
end
function addSeconds (timestring, secs)
hh = int(mid(timestring, 1, 2))
mm = int(mid(timestring, 4, 2))
ss = int(mid(timestring, 7, 2)) + secs
ttt = int(mid(timestring, 10, 3))
while ss < 0
ss = ss + 60
mm = mm - 1
end while
while mm < 0
mm = mm + 60
hh = hh - 1
end while
while hh < 0
hh = hh + 24
end while
mm = mm + ss \ 60
hh = hh + mm \ 60
ss = ss mod 60
mm = mm mod 60
hh = hh mod 24
return right("0" + string(hh), 2) + ":" + right("0" + string(mm), 2) + ":" + right("0" + string(ss), 2) + "," + right("000" + string(ttt), 3)
end function
subroutine syncSubtitles (fileIn, fileOut, secs)
fmt = "hh:MM:ss,ttt"
f1 = freefile
open f1, fileOut
f2 = freefile
open f2, fileIn
while not eof(f2)
linea = readline (f2)
if instr(linea, "-->") > 0 then
pio = mid(linea, 1, 12)
pio = addSeconds(pio, secs)
fin = mid(linea, 18, 12)
fin = addSeconds(fin, secs)
write f1, pio; " --> "; fin + chr(10)
else
write f1, linea
end if
end while
close
end subroutine
Chipmunk Basic
100 cls
110 print "After fast-forwarding 9 seconds:";chr$(10)
120 syncsubtitles("movie.srt","movie_corrected.srt",9)
130 open "movie_corrected.srt" for input as #1
140 while not eof(1)
150 line input #1,linea$
160 print linea$
170 wend
180 close #1
190 print
200 print "After rolling-back 9 seconds:";chr$(10)
210 syncsubtitles("movie.srt","movie_corrected2.srt",-9)
220 open "movie_corrected2.srt" for input as #1
230 while not eof(1)
240 line input #1,linea$
250 print linea$
260 wend
270 close #1
280 end
290 sub addseconds$(timestr$,secs)
300 hh = val(mid$(timestr$,1,2))
310 mm = val(mid$(timestr$,4,2))
320 ss = val(mid$(timestr$,7,2))+secs
330 ttt = val(mid$(timestr$,10,3))
340 while ss < 0
350 ss = ss+60
360 mm = mm-1
370 wend
380 while mm < 0
390 mm = mm+60
400 hh = hh-1
410 wend
420 while hh < 0
430 hh = hh+24
440 wend
450 mm = mm+int(ss/60)
460 hh = hh+int(mm/60)
470 ss = ss mod 60
480 mm = mm mod 60
490 hh = hh mod 24
500 addseconds$ = right$("0"+str$(hh),2)+":"+right$("0"+str$(mm),2)+":"+right$("0"+str$(ss),2)+","+right$("000"+str$(ttt),3)
510 end sub
520 sub syncsubtitles(filein$,fileout$,secs)
530 fmt$ = "hh:MM:ss,ttt"
540 open fileout$ for output as #1
550 open filein$ for input as #2
560 while not eof(2)
570 line input #2,linea$
580 if instr(linea$,"-->") > 0 then
590 pio$ = mid$(linea$,1,12)
600 pio$ = addseconds$(pio$,secs)
610 fin$ = mid$(linea$,18,12)
620 fin$ = addseconds$(fin$,secs)
630 print #1,pio$;" --> ";fin$
640 else
650 print #1,linea$
660 endif
670 wend
680 close #2
690 close #1
700 end sub
FreeBASIC
Function addSeconds(timeStr As String, secs As Integer) As String
Dim As Integer hh, mm, ss, ttt
hh = Val(Mid(timeStr, 1, 2))
mm = Val(Mid(timeStr, 4, 2))
ss = Val(Mid(timeStr, 7, 2)) + secs
ttt = Val(Mid(timeStr, 10, 3))
While ss < 0
ss += 60
mm -= 1
Wend
While mm < 0
mm += 60
hh -= 1
Wend
While hh < 0
hh += 24
Wend
mm += ss \ 60
hh += mm \ 60
ss Mod= 60
mm Mod= 60
hh Mod= 24
Return Right("0" & Str(hh), 2) & ":" & Right("0" & Str(mm), 2) & ":" & _
Right("0" & Str(ss), 2) & "," & Right("000" & Str(ttt), 3)
End Function
Sub syncSubtitles(fileIn As String, fileOut As String, secs As Integer)
Dim As String linea, pio, fin, fmt
Dim As Ubyte f1, f2
fmt = "hh:MM:ss,ttt"
f1 = Freefile
Open fileOut For Output As #f1
f2 = Freefile
Open fileIn For Input As #f2
While Not Eof(f2)
Line Input #f2, linea
If Instr(linea, "-->") > 0 Then
pio = Mid(linea, 1, 12)
pio = addSeconds(pio, secs)
fin = Mid(linea, 18, 12)
fin = addSeconds(fin, secs)
Print #f1, pio; " --> "; fin
Else
Print #f1, linea
End If
Wend
Close #f2, #f1
End Sub
Dim As String linea
Dim As Ubyte f = Freefile
Print !"After fast-forwarding 9 seconds:\n"
syncSubtitles("movie.srt", "movie_corrected.srt", 9)
Open "movie_corrected.srt" For Input As #f
While Not Eof(f)
Line Input #f, linea
Print linea
Wend
Close #f
Print !"\n\nAfter rolling-back 9 seconds:\n"
syncSubtitles("movie.srt", "movie_corrected2.srt", -9)
Open "movie_corrected2.srt" For Input As #f
While Not Eof(f)
Line Input #f, linea
Print linea
Wend
Close #f
Sleep
- Output:
Same as Wren entry.
QB64
Dim As String linea
f = FreeFile
Print "After fast-forwarding 9 seconds:"; Chr$(10)
Call syncSubtitles("movie.srt", "movie_corrected.srt", 9)
Open "movie_corrected.srt" For Input As #f
While Not EOF(f)
Line Input #f, linea
Print linea
Wend
Close #f
Print Chr$(10); Chr$(10); "After rolling-back 9 seconds:"; Chr$(10)
Call syncSubtitles("movie.srt", "movie_corrected2.srt", -9)
Open "movie_corrected2.srt" For Input As #f
While Not EOF(f)
Line Input #f, linea
Print linea
Wend
Close #f
Function addSeconds$ (timeStr As String, secs As Integer)
Dim As Integer hh, mm, ss, ttt
hh = Val(Mid$(timeStr, 1, 2))
mm = Val(Mid$(timeStr, 4, 2))
ss = Val(Mid$(timeStr, 7, 2)) + secs
ttt = Val(Mid$(timeStr, 10, 3))
While ss < 0
ss = ss + 60
mm = mm - 1
Wend
While mm < 0
mm = mm + 60
hh = hh - 1
Wend
While hh < 0
hh = hh + 24
Wend
mm = mm + ss \ 60
hh = hh + mm \ 60
ss = ss Mod 60
mm = mm Mod 60
hh = hh Mod 24
addSeconds$ = Right$("0" + Str$(hh), 2) + ":" + Right$("0" + Str$(mm), 2) + ":" + Right$("0" + Str$(ss), 2) + "," + Right$("000" + Str$(ttt), 3)
End Function
Sub syncSubtitles (fileIn As String, fileOut As String, secs As Integer)
Dim As String linea, pio, fin, fmt
Dim As Integer f1, f2
fmt = "hh:MM:ss,ttt"
f1 = FreeFile
Open fileOut For Output As #f1
f2 = FreeFile
Open fileIn For Input As #f2
While Not EOF(f2)
Line Input #f2, linea
If InStr(linea, "-->") > 0 Then
pio = Mid$(linea, 1, 12)
pio = addSeconds$(pio, secs)
fin = Mid$(linea, 18, 12)
fin = addSeconds$(fin, secs)
Print #f1, pio; " --> "; fin
Else
Print #f1, linea
End If
Wend
Close #f2, #f1
End Sub
C++
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <ctime>
using namespace std;
string addSeconds(string timeStr, int secs) {
int hours, minutes, seconds, milliseconds;
sscanf(timeStr.c_str(), "%d:%d:%d,%d", &hours, &minutes, &seconds, &milliseconds);
int total_seconds = hours * 3600 + minutes * 60 + seconds + secs;
hours = total_seconds / 3600;
total_seconds %= 3600;
minutes = total_seconds / 60;
seconds = total_seconds % 60;
char buffer[13];
sprintf(buffer, "%02d:%02d:%02d,%03d", hours, minutes, seconds, milliseconds);
return string(buffer);
}
void syncSubtitles(string fileIn, string fileOut, int secs) {
ifstream fin(fileIn);
ofstream fout(fileOut);
string line;
while (getline(fin, line)) {
if (line.find("-->") != string::npos) {
string start = line.substr(0, 12);
string end = line.substr(17, 12);
start = addSeconds(start, secs);
end = addSeconds(end, secs);
fout << start << " --> " << end << "\n";
} else {
fout << line << "\n";
}
}
fin.close();
fout.close();
}
int main() {
cout << "After fast-forwarding 9 seconds:\n\n";
syncSubtitles("movie.srt", "movie_corrected.srt", 9);
ifstream f("movie_corrected.srt");
string line;
while (getline(f, line)) {
cout << line << "\n";
}
f.close();
cout << "\n\nAfter rolling-back 9 seconds:\n\n";
syncSubtitles("movie.srt", "movie_corrected2.srt", -9);
ifstream f2("movie_corrected2.srt");
while (getline(f2, line)) {
cout << line << "\n";
}
f2.close();
return 0;
}
- Output:
Same as FreeBASIC entry.
Phix
Needed a bugfix to adjust_timedate() for time-only handling, in that a y,m,d of 0,0,0 pre-dates the introduction of the Gregorian calendar. There was also a floor(milliseconds) which should have been/is now round(milliseconds). Fixes can be grabbed from github if needed.
requires("1.0.6") -- (a time-only handling bugfix in adjust_timedate)
constant movie_srt = `
1
00:01:31,550 --> 00:01:36,347
Four billion years ago,
00:01:36,555 --> 00:01:42,019
00:01:42,144 --> 00:01:43,979
00:01:43,979 --> 00:01:45,898
00:01:46,232 --> 00:01:47,608
00:01:47,733 --> 00:01:50,361
00:01:50,736 --> 00:01:52,488
00:01:58,035 --> 00:01:58,869
00:01:59,203 --> 00:02:00,079
00:02:02,540 --> 00:02:03,999
00:02:04,416 --> 00:02:07,419
00:02:07,503 --> 00:02:11,048
With our advanced technology, I shrank it down.
`,
sep = ` --> `,
fmt = `hh:mm:ss,ms`
include timedate.e
for line in split(movie_srt,'\n') do
if match(sep,line) then
line = split(line,sep)
for i,t in line do
timedate td = parse_date_string(t,{fmt})
line[i] = format_timedate(adjust_timedate(td,9),fmt)
end for
line = join(line,sep)
end if
printf(1,"%s\n",line)
end for
- Output:
1 00:01:40,550 --> 00:01:45,347 Four billion years ago, 00:01:45,555 --> 00:01:51,019 00:01:51,144 --> 00:01:52,979 00:01:52,979 --> 00:01:54,898 00:01:55,232 --> 00:01:56,608 00:01:56,733 --> 00:01:59,361 00:01:59,736 --> 00:02:01,488 00:02:07,035 --> 00:02:07,869 00:02:08,203 --> 00:02:09,079 00:02:11,540 --> 00:02:12,999 00:02:13,416 --> 00:02:16,419 00:02:16,503 --> 00:02:20,048 With our advanced technology, I shrank it down.
Python
#! /usr/bin/env python3
import datetime
def add_seconds(time_str, secs):
time_format = "%H:%M:%S,%f"
time_obj = datetime.datetime.strptime(time_str, time_format)
delta = datetime.timedelta(seconds=secs)
new_time_obj = time_obj + delta
new_time_str = new_time_obj.strftime(time_format)[:-3] # remove the last 3 digits of microseconds
return new_time_str
def sync_subtitles(file_in, file_out, secs):
with open(file_in, 'r') as fin, open(file_out, 'w') as fout:
for line in fin:
if '-->' in line:
start_time, end_time = line.strip().split(' --> ')
start_time = add_seconds(start_time, secs)
end_time = add_seconds(end_time, secs)
fout.write(f"{start_time} --> {end_time}\n")
else:
fout.write(line)
print("After fast-forwarding 9 seconds:\n")
sync_subtitles("movie.srt", "movie_corrected.srt", 9)
with open("movie_corrected.srt", 'r') as f:
print(f.read())
print("\n\nAfter rolling-back 9 seconds:\n")
sync_subtitles("movie.srt", "movie_corrected2.srt", -9)
with open("movie_corrected2.srt", 'r') as f:
print(f.read())
- Output:
Same as FreeBASIC entry.
Wren
import "./date" for Date
import "./ioutil" for File, FileUtil
var syncSubtitles = Fn.new { |fileIn, fileOut, secs|
var nl = FileUtil.lineBreak
var fmt = "hh|:|MM|:|ss|,|ttt"
var f = File.create(fileOut)
for (line in FileUtil.readLines(fileIn)) {
if (line.contains("-->")) {
var start = line[0..11]
var startDate = Date.parse(start, fmt).addSeconds(secs)
start = startDate.format(fmt)
var end = line[17..28]
var endDate = Date.parse(end, fmt).addSeconds(secs)
end = endDate.format(fmt)
f.writeBytes(start + " --> " + end + nl)
} else {
f.writeBytes(line + nl)
}
}
f.close()
}
System.print("After fast-forwarding 9 seconds:\n")
syncSubtitles.call("movie.srt", "movie_corrected.srt", 9)
System.print(File.read("movie_corrected.srt"))
System.print("After rolling-back 9 seconds:\n")
syncSubtitles.call("movie.srt", "movie_corrected2.srt", -9)
System.print(File.read("movie_corrected2.srt"))
- Output:
After fast-forwarding 9 seconds: 1 00:01:40,550 --> 00:01:45,347 Four billion years ago, the first marine life forms. 2 00:01:45,555 --> 00:01:51,019 First came the fish...then slowly other life forms evolved. 3 00:01:51,144 --> 00:01:52,979 Therefore, our ancestors... 4 00:01:52,979 --> 00:01:54,898 ...came from fish. 5 00:01:55,232 --> 00:01:56,608 Everyone, come and see this. 6 00:01:56,733 --> 00:01:59,361 Cretaceous Tyrannosaurus. 7 00:01:59,736 --> 00:02:01,488 Ferocious! 8 00:02:07,035 --> 00:02:07,869 Red, 9 00:02:08,203 --> 00:02:09,079 Pong! 10 00:02:11,540 --> 00:02:12,999 Isn't this a gecko? 11 00:02:13,416 --> 00:02:16,419 How else can I get a 15 ton T-Rex in here? 12 00:02:16,503 --> 00:02:20,048 With our advanced technology, I shrank it down. After rolling-back 9 seconds: 1 00:01:22,550 --> 00:01:27,347 Four billion years ago, the first marine life forms. 2 00:01:27,555 --> 00:01:33,019 First came the fish...then slowly other life forms evolved. 3 00:01:33,144 --> 00:01:34,979 Therefore, our ancestors... 4 00:01:34,979 --> 00:01:36,898 ...came from fish. 5 00:01:37,232 --> 00:01:38,608 Everyone, come and see this. 6 00:01:38,733 --> 00:01:41,361 Cretaceous Tyrannosaurus. 7 00:01:41,736 --> 00:01:43,488 Ferocious! 8 00:01:49,035 --> 00:01:49,869 Red, 9 00:01:50,203 --> 00:01:51,079 Pong! 10 00:01:53,540 --> 00:01:54,999 Isn't this a gecko? 11 00:01:55,416 --> 00:01:58,419 How else can I get a 15 ton T-Rex in here? 12 00:01:58,503 --> 00:02:02,048 With our advanced technology, I shrank it down.