tried make subtitle using mplayer. thankfully, mplayer has -edlfile option. so, using that, I can cue when subtitle should change.
given the following:
subtitle.txt
hello!
how are you?
bye
I can play mplayer -edlfile subtitle.edl movie.avi
. and as I play the movie, I press i to cue for new subtitle text from subtitle.txt. Then,
python edl2srt.py subtitle.edl -t subtitle.txt > movie.srt
mplayer movie.avi -sub movie.srt
will play movie.avi with subtitle.
You can get comma separated cue seconds (seconds when i was pressed):
python edl2srt.py subtitle.edl
EDL to srt script is here: It needs optfunc module.
#!/usr/bin/python
# LICENSE: public domain.
"""converts edl file to srt.
EDL (Edit Decision List) file: http://www.mplayerhq.hu/DOCS/HTML/en/edl.html
SRT file: http://forum.doom9.org/archive/index.php/t-73953.html
requires optfunc found at: http://github.com/simonw/optfunc/tree/master"""
def split_float(f):
i = int(f)
return i, f - i
def split_float_str(fstr):
l = fstr.split('.')
return l[0], l[1]
def sec_to_hour_min_sec(seconds):
m,sec = divmod(seconds, 60)
hour,min = divmod(m, 60)
return (hour,min,sec)
def timestamp(seconds):
f = float(seconds)
i,frac = split_float(f)
hour,min,sec = sec_to_hour_min_sec(i)
return (hour, min, sec, int(frac*100))
def to_timestamp(seconds, format="%(hour)s:%(min)s:%(sec)s,%(millisec)s"):
hour,min,sec,millisec = timestamp(seconds)
return format % {"hour":hour, "min":min, "sec":sec, "millisec":millisec}
class ED(object):
"edit decision"
def __init__(self, sec_from=0.0, sec_to=0.0, flag=0):
self.sec_from = float(sec_from)
self.sec_to = float(sec_to)
self.flag = int(flag)
def to_tuple(self):
return (self.sec_from, self.sec_to, self.flag)
def to_pair(self):
return (self.sec_from, self.sec_to)
class EDL(object):
def __init__(self, filename=None):
self.edl = self.read_edl(filename) if filename else []
def read_edl(self, filename):
f = open(filename, "r")
l = []
for line in f:
x = line.split()
l.append(ED(x[0], x[1], x[2]))
return l
def seconds(self):
l = []
for ed in self.edl:
l.extend([ed.sec_from, ed.sec_to])
return l
def second_pairs(self):
l = []
for x in self.edl:
l.append(x.to_pair())
return l
class Text(object):
def __init__(self, filename=None):
self.text = self.read_text(filename) if filename else []
def __len__(self):
return len(self.text)
def __getitem__(self, key):
return self.text[key]
def __str__(self):
return '\n'.join(self.text)
def read_text(self, filename):
f = open(filename, "r")
l = []
for line in f:
x = line.strip()
if x:
l.append(x)
f.close()
return l
class Subtitle(object):
def __init__(self, index=0, time_from=0, time_to=0, text=""):
self.index = index
self.time_from = to_timestamp(time_from)
self.time_to = to_timestamp(time_to)
self.text = text
def __str__(self):
return """%u
%s --> %s
%s""" % (self.index, self.time_from, self.time_to, self.text)
def insert_end(seconds, limit=3.0, gap=0.001):
def delta(x,y):
d = y - x
return limit if d > limit else d
return [(x, x + delta(x,y) - gap) for x,y in zip(seconds, seconds[1:])]
def make_srt(edl, text):
index = 1
sec_pairs = insert_end(edl.seconds())
srt = []
for i,(sec_from,sec_to) in enumerate(sec_pairs):
t = text[i] if len(text) > i else None
srt.append(Subtitle(i+1, sec_from, sec_to, t))
return srt
def edl2srt(edlname, txtname=None):
"""Usage: %prog edlfile [-t textfile]
edlfile specification is at:
http://www.mplayerhq.hu/DOCS/HTML/en/edl.html
textfile should contain subtitles delimited by new line.
Example
mplayer a.avi -edlfile a.edl
during movie play, press i to insert a cue to change subtitle
defined in a.txt
%prog a.edl -t a.txt > a.srt
mplayer a.avi -sub a.srt"""
edl = EDL(edlname)
if txtname is None:
print(','.join([str(x) for x in edl.seconds()]))
else:
txt = Text(txtname)
print '\n\n'.join([str(x) for x in make_srt(edl, txt)])
if __name__ == "__main__":
import optfunc
optfunc.run(edl2srt)