Sync subtitles
Sync subtitles
You are encouraged to solve this task according to the task description, using any language you may know.
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.
Gambas
Function addSeconds(timeStr As String, secs As Integer) As String
Dim hh As Integer, mm As Integer, ss As Integer, ttt As Integer
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 = ss Mod 60
mm = mm Mod 60
hh = 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 linea As String, pio As String, fin As String, fmt As String
Dim f1 As File, f2 As File
fmt = "hh:MM:ss,ttt"
f1 = Open fileOut For Output
f2 = Open fileIn For Input
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 #f1
Close #f2
End Sub
Public Sub Main()
Dim linea As String
Dim f As File
Print "After fast-forwarding 9 seconds:\n"
syncSubtitles("movie.srt", "movie_corrected.srt", 9)
f = Open "movie_corrected.srt" For Input
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)
f = Open "movie_corrected2.srt" For Input
While Not Eof(f)
Line Input #f, linea
Print linea
Wend
Close #f
End
- Output:
Same as FreeBASIC entry.
PureBasic
Procedure.s addSeconds(timeStr.s, secs)
Protected hours, minutes, seconds, milliseconds
Protected.s hh, mm, ss, ttt
hh = Mid(timeStr, 1, 2)
hours = Val(hh)
mm = Mid(timeStr, 4, 2)
minutes = Val(mm)
ss = Mid(timeStr, 7, 2)
seconds = Val(ss)
seconds + secs
ttt = Mid(timeStr, 10, 3)
If seconds < 0
seconds + 60
minutes - 1
EndIf
If minutes < 0
minutes + 60
hours - 1
EndIf
If hours < 0
hours + 24
EndIf
ProcedureReturn Str(hours) + ":" + Str(minutes) + ":" + Str(seconds) + "," + ttt
EndProcedure
Procedure syncSubtitles(fileIn.s, fileOut.s, secs)
Protected line.s, pio.s, fin.s
OpenFile(0, fileIn)
CreateFile(1, fileOut)
While Not Eof(0)
line = ReadString(0)
If FindString(line, "-->", 1)
pio = Mid(line, 1, 12)
fin = Mid(line, 18, 12)
pio = addSeconds(pio, secs)
fin = addSeconds(fin, secs)
WriteStringN(1, pio + " --> " + fin)
Else
WriteStringN(1, line)
EndIf
Wend
CloseFile(0)
CloseFile(1)
EndProcedure
OpenConsole()
PrintN("After fast-forwarding 9 seconds:" + #CRLF$)
syncSubtitles("movie.srt", "movie_corrected.srt", 9)
OpenFile(0, "movie_corrected.srt")
While Not Eof(0)
PrintN(ReadString(0))
Wend
CloseFile(0)
PrintN(#CRLF$ + #CRLF$ + "After rolling-back 9 seconds:" + #CRLF$)
syncSubtitles("movie.srt", "movie_corrected2.srt", -9)
OpenFile(0, "movie_corrected2.srt")
While Not Eof(0)
PrintN(ReadString(0))
Wend
CloseFile(0)
PrintN(#CRLF$ + "Press ENTER to exit"): Input()
CloseConsole()
- Output:
Same as FreeBASIC 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.