Skip to content

Instantly share code, notes, and snippets.

@ispedals
Created May 20, 2013 21:44
Show Gist options
  • Select an option

  • Save ispedals/5615827 to your computer and use it in GitHub Desktop.

Select an option

Save ispedals/5615827 to your computer and use it in GitHub Desktop.
Converts the currently set .ass subtitle to .srt and sets it as the subtitle for the current video in XBMC for Xbox
"""
ass2srt.py
Converts the currently set .ass subtitle to .srt and sets it as the subtitle for the current video
"""
import re
import xbmc
from os.path import basename, splitext
from datetime import time
import traceback
import codecs
encoding='utf-8'
try:
from chardet.universaldetector import UniversalDetector
except ImportError:
UniversalDetector=False
print 'ass2srt.py: could not load UniversalDetector, defaulting encoding to %s' % encoding
class SubripLine:
FORMAT=None
@classmethod
def set_format(cls,line):
"""Sets static FORMAT dictionary
Raises if the fields do not contain:
Start
End
Text
"""
print 'ass2srt.py: field is %s' % line
fields=[field.strip() for field in line.split(',')]
if not set(['Start', 'End', 'Text']) <= set(fields): #if (start, end, text) not a subset of fields
raise ValueError('ass2srt.py: Fields do not contain Start, End, or Text')
cls.FORMAT=dict(zip(fields, range(0,len(fields))))
print 'ass2srt.py: Format is %s' % cls.FORMAT
@staticmethod
def create_time_from_timestamp(timestamp):
"""Parses timestamp and returns a datetime.time object
Example timestamp: 0:20:46.090
"""
m=[int(digit) for digit in re.findall(r'(\d):(\d\d):(\d\d)\.(\d\d)',timestamp)[0]]
return time(m[0], m[1], m[2], microsecond=m[3]*1000)
def __init__(self, line):
FORMAT=self.__class__.FORMAT
line=re.sub(r'{.*?}','',line) #strip formatting
line=re.sub(r'\\N','\n',line) #convert newlines to real newline
line=re.sub(r'\\.','',line) #strip control characters
#need to limit splits or else the commas in the dialogue will also be split. -1 needed as split limits to maxsplit+1
tokens=[token.strip() for token in line.split(',', len(FORMAT)-1)]
self.text=tokens[FORMAT['Text']]
self.start_time=self.create_time_from_timestamp(tokens[FORMAT['Start']])
self.end_time=self.create_time_from_timestamp(tokens[FORMAT['End']])
def __str__(self):
"""Returns string in format of:
start_time --> end_time\ntext\n
ex.
00:00:02,500 --> 00:00:04,970
Fairy Tail
does not add index
"""
start_time=self.start_time.strftime('%H:%M:%S,') + \
str('%03d' % (self.start_time.microsecond/100))
end_time=self.end_time.strftime('%H:%M:%S,') + \
str('%03d' % (self.end_time.microsecond/100))
return '%s --> %s\n%s\n' % (start_time, end_time, self.text)
ass_subtitle='special://temp/%s' % xbmc.Player().getSubtitles()
OUTPUT='Z:\\sp_%s.srt' % splitext(basename(ass_subtitle))[0]
# ass_subtitle='C:\\Users\\Viqar Samad\\Desktop\\gogakumono\\subs\\yukimeimeri.ass'
# OUTPUT='C:\\Users\\Viqar Samad\\Desktop\\%s.srt' % splitext(basename(ass_subtitle))[0]
print 'ass2srt.py: converting %s' % ass_subtitle
if UniversalDetector:
f=open(ass_subtitle, 'r')
detector = UniversalDetector()
for line in f:
detector.feed(line)
if detector.done: break
detector.close()
f.close()
encoding=detector.result['encoding']
print 'ass2srt.py: determined encoding to be %s' % encoding
try:
f=codecs.open(ass_subtitle, 'r' , encoding)
except LookupError:
encoding='utf-8' #most likely choice
f=codecs.open(ass_subtitle, 'r' , encoding)
line=f.readline()
while len(line) != 0 and line.strip() != '[Events]':
line=f.readline()
if len(line) == 0:
raise EOFError('ass2srt.py: reached eof, did not find [Events]')
line=f.readline().strip() #line after [Events] containing format
SubripLine.set_format(line)
subtitles=[]
line=f.readline()#main dialogue
while len(line) != 0 and not line.startswith('['): #not end of file or not the start of another section
line.strip()#strip newline, can't do it before loop or else length will be 0 for a blank line
if not line.startswith('Dialogue'):
print 'ass2srt.py: skipping line %r' % line
line=f.readline()
continue
try:
subtitles.append(SubripLine(line))
except:
err='ass2srt.py: failure occured'
if len(subtitles)>0:
err+=', previous line \n%s' % subtitles[-1]
print err
traceback.print_exc()
line=f.readline()
f.close()
print 'ass2srt.py: finished parsing'
subtitles.sort(cmp=lambda a,b: cmp(a.start_time,b.start_time)) #ass subtitles are not guaranteed to be chronologically sorted
print 'ass2srt.py: sorted subtitles'
srt_subs='\n'.join(['%d\n%s' % (i+1, line) for i, line in enumerate(subtitles)])
print 'ass2srt.py: printing to %s; length:%d' % (OUTPUT, len(srt_subs))
subfile=codecs.open(OUTPUT, 'w', 'utf-8', buffering=0)
subfile.write(srt_subs)
subfile.close()
xbmc.Player().setSubtitles(OUTPUT)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment