#!/usr/bin/env python # From http://www.dwerg.net/projects/python/srttool.py # Converts SubStation Scripts into CMML # More information at http://trac.annodex.net/wiki/CmmlSubtitles ## Copyright (C) 2004- Commonwealth Scientific and Industrial Research ## Organisation (CSIRO) Australia ## ## Redistribution and use in source and binary forms, with or without ## modification, are permitted provided that the following conditions ## are met: ## ## - Redistributions of source code must retain the above copyright ## notice, this list of conditions and the following disclaimer. ## ## - Redistributions in binary form must reproduce the above copyright ## notice, this list of conditions and the following disclaimer in the ## documentation and/or other materials provided with the distribution. ## ## - Neither the name of CSIRO Australia nor the names of its ## contributors may be used to endorse or promote products derived from ## this software without specific prior written permission. ## ## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ## ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ## PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ## LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ## NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import re import sys import getopt global firstpart global savecmml global id timeRe = re.compile('(?P\d):(?P\d\d):(?P\d\d).(?P\d\d)') titlemsg = re.compile('Title:') scriptmsg = re.compile('Original Script:') authormsg = re.compile('Original Translation:') dialogueRe = re.compile('Dialogue:.') class CorruptSsaError(Exception): """ The SubStation File is incorrectly formatted """ pass def timeformat(times): return "%02d:%02d:%02d.%02d" % tuple(times) def get_times(line, line2): try: time1 = timeRe.match(line.strip()) time2 = timeRe.match(line2.strip()) timear1 = [ int(time1.groupdict()['hours']), int(time1.groupdict()['minutes']), int(time1.groupdict()['seconds']), int(time1.groupdict()['millis']), ] timear2 = [ int(time2.groupdict()['hours']), int(time2.groupdict()['minutes']), int(time2.groupdict()['seconds']), int(time2.groupdict()['millis']), ] return (timeformat(timear1), timeformat(timear2)) except IndexError: raise CorruptSsaError("Corrupt Time Format") def convert_block(lines): global savecmml global id if lines[0] == '[Events]': for array in lines: if dialogueRe.match(array): parts = array.split(',', 9) # Match the time sequence for start and end sequences if timeRe.match(parts[1].strip()): (start, end) = get_times(parts[1], parts[2]) savecmml += '\n' % (id, start, end) savecmml += ' \n' for line in parts[9:]: savecmml += ' ' + line + '\n' savecmml += ' \n' savecmml += '\n' id += 1 def header_metadata(line): # To process the metadata at the start of the message global savecmml for array in line: if titlemsg.match(array): ext_titlemsg = array.replace('Title: ', '') savecmml += ' ' + ext_titlemsg + '\n' if scriptmsg.match(array): ext_scriptmsg = array.replace('Original Script: ', '') savecmml += ' \n' if authormsg.match(array): ext_authmsg = array.replace('Original Translation: ', '') savecmml += ' \n' def convert_clips(file): global firstpart global savecmml current = [] for line in file: if not line.strip(): if firstpart == 1: header_metadata(current) firstpart = 0 savecmml += '\n' convert_block(current) current = [] else: current.append(line.strip()) def convert_ssa(file): global savecmml global id global firstpart id = 1 firstpart = 1 savecmml = '\n' savecmml += '\n' convert_clips (file) savecmml += '\n' if __name__ == '__main__': global savecmml savecmml = '' try: try: filesave = open(sys.argv[2], 'w') convert_ssa(file(sys.argv[1])) filesave.write(savecmml) filesave.close() except IndexError: convert_ssa(file(sys.argv[1])) print savecmml except IndexError: print "Usage: %s [Input SubStation File] [Output CMML File]" % sys.argv[0]