Created
May 20, 2013 21:44
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| 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