Skip to content

Instantly share code, notes, and snippets.

@grechnik
Last active October 28, 2025 22:03
Show Gist options
  • Select an option

  • Save grechnik/6c219fd04d83e28018d6bcdb387988f3 to your computer and use it in GitHub Desktop.

Select an option

Save grechnik/6c219fd04d83e28018d6bcdb387988f3 to your computer and use it in GitHub Desktop.
the last express subtitles
assumes the ability to run Python from command line
[00:00.033-00:02.000]
Excuse me. Got a light?
[00:07.500-00:08.000]
Thanks.
[00:08.500-00:11.000]
Haven't we met somewhere before?
[00:11.033-00:20.066]
It's possible. I don't think
I would have remembered.
import io, sys, struct
def raw2str(s):
s = bytearray(s)
ret = ""
for i in range(len(s) // 2):
assert s[2 * i + 1] == 0, "invalid character"
ret = ret + bytes([s[2 * i]]).decode('cp437')
return ret
with io.open(sys.argv[1], 'rb') as f:
count, = struct.unpack('<H', f.read(2))
for _ in range(count):
v1, v2, len1, len2 = struct.unpack('<HHHH', f.read(8))
s1 = raw2str(f.read(len1 * 2))
s2 = raw2str(f.read(len2 * 2))
if s2 != "":
s2 = "\n" + s2
print("[%02d:%02d.%03d-%02d:%02d.%03d]\n%s%s" % (v1//(30*60), (v1//30)%60, (v1%30)*1000//30, v2//(30*60), (v2//30)%60, (v2%30)*1000//30, s1, s2))
import sys, io, struct, re, array
with io.open(sys.argv[1], "rb") as f:
data = []
for line in f.readlines():
line = line.decode('utf-8').strip()
if len(line) == 0:
continue
if line[0] == '[':
match = re.match(r'^\[(\d+):(\d+)\.(\d+)-(\d+):(\d+)\.(\d+)\]$', line)
assert match, "Invalid time format"
beginTime = int(match.group(1)) * 60 * 30 + int(round(float(match.group(2)+'.'+match.group(3)) * 30))
endTime = int(match.group(4)) * 60 * 30 + int(round(float(match.group(5)+'.'+match.group(6)) * 30))
assert beginTime < endTime, "Invalid time range in " + sys.argv[1]
assert len(data) == 0 or len(data[-1][2]) > 0, "Time without data in " + sys.argv[1]
assert len(data) == 0 or beginTime >= data[-1][1], "Decreasing time in " + sys.argv[1]
data.append([beginTime, endTime, "", ""])
else:
assert len(data) > 0, "Data without time in " + sys.argv[1]
assert len(line) <= 45, "Too long line in " + sys.argv[1]
if len(data[-1][2]) == 0:
data[-1][2] = line
else:
assert len(data[-1][3]) == 0, "Too many data lines in " + sys.argv[1]
data[-1][3] = line
assert len(data) > 0, "Empty file " + sys.argv[1]
assert len(data[-1][2]) > 0, "Time without data in " + sys.argv[1]
with open(sys.argv[2], "wb") as out:
packed = array.array('H')
packed.append(len(data))
for item in data:
packed.append(item[0])
packed.append(item[1])
packed.append(len(item[2]))
packed.append(len(item[3]))
for c in bytearray(item[2].encode('cp437')):
packed.append(c)
for c in bytearray(item[3].encode('cp437')):
packed.append(c)
while len(packed) % 0x400:
packed.append(0)
packed.tofile(out)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment