#!/usr/bin/env python
# From http://www.dwerg.net/projects/python/srttool.py
# Converts AQTitle 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 math
global save_start
global save_msg
global save_msg_flag
global savecmml
global id
frameMarkRe = re.compile('-->> .')
anyValueRe = re.compile('.')
class CorruptAqtError(Exception):
"""
The AQTitle File is incorrectly formatted
"""
pass
def time_calculation(seconds, amt_in_sec):
val = seconds / amt_in_sec
val_rounded = math.floor(val)
secs_remainder = (val * amt_in_sec) - (val_rounded * amt_in_sec)
return (val_rounded, secs_remainder)
def convert_timeperiod(frame, fps):
try:
totalsec = frame / fps
(hours, secs_remainder) = time_calculation(totalsec, 3600)
(minutes, secs_remainder) = time_calculation(secs_remainder, 60)
(secs, millisecs) = time_calculation(secs_remainder, 1)
millisecs = round(millisecs*1000)
timeperiod = '%(val1)02d:%(val2)02d:%(val3)02d.%(val4)03d' % {'val1':hours, 'val2':minutes, 'val3':secs, 'val4':millisecs}
return timeperiod
except IndexError:
raise CorruptAqtError("Corrupt Frame Format")
def convert_block(lines, fps):
global savecmml
global id
global save_start
global save_msg
global save_msg_flag
last_count = 1
subtitlemsg = ''
try:
# To determine if the next line exists a subtitle
if anyValueRe.match(lines[1]):
# When a previous subtitle was saved as a whitespace was made before the ending frame could be found
if save_msg_flag == 1:
if frameMarkRe.match(lines[0]):
endtemp = lines[0].replace('-->> ', '')
endframe = float(endtemp)
save_end = convert_timeperiod(endframe, fps)
savecmml += '\n' % (id, save_start, save_end)
savecmml += ' \n'
savecmml += save_msg
savecmml += ' \n'
savecmml += '\n'
id += 1
# To clear last message buffered
subtitlemsg = ''
save_msg_flag = 0
# To process frame timings
if frameMarkRe.match(lines[0]):
starttemp = lines[0].replace('-->> ', '')
startframe = float(starttemp)
start = convert_timeperiod(startframe, fps)
for array in lines[1:]:
if not frameMarkRe.match(array):
subtitlemsg += ' ' + array + '\n'
last_count += 1
if frameMarkRe.match(array):
endtemp = array.replace('-->> ', '')
endframe = float(endtemp)
end = convert_timeperiod(endframe, fps)
last_count += 1
# To determine if the next message block continues after the ending frame
try:
if anyValueRe.match(lines[last_count]):
savecmml += '\n' % (id, start, end)
savecmml += ' \n'
savecmml += subtitlemsg
savecmml += ' \n'
savecmml += '\n'
id += 1
# To clear last message buffered
subtitlemsg = ''
if frameMarkRe.match(array):
starttemp = array.replace('-->> ', '')
startframe = float(starttemp)
start = convert_timeperiod(startframe, fps)
except Exception:
pass
# To ensure the ending time was found within the line array
if start != end:
savecmml += '\n' % (id, start, end)
savecmml += ' \n'
savecmml += subtitlemsg
savecmml += ' \n'
savecmml += '\n'
id += 1
# When no ending time was found within the existing line array, we need to save the context for the next pass
else:
save_start = start
save_msg = subtitlemsg
save_msg_flag = 1
except Exception:
pass
def convert_clips(file, fps):
current = []
for line in file:
if not line.strip():
convert_block(current, fps)
current = []
else:
current.append(line.strip())
def convert_aqt(file, fps):
global savecmml
global id
global save_msg_flag
save_msg_flag = 0
id = 1
savecmml = '\n'
savecmml += '\n'
savecmml += ' ' + sys.argv[1] + '\n'
savecmml += '\n'
convert_clips (file, fps)
savecmml += '\n'
if __name__ == '__main__':
global savecmml
fps = None
print 'Frames-per-Second of Video Required:\nEnter Frames-per-Second:'
while not fps:
try:
fps = float(raw_input())
except ValueError:
print 'Invalid FPS Entered. Try Again.'
try:
try:
filesave = open(sys.argv[2], 'w')
convert_aqt(file(sys.argv[1]), fps)
filesave.write(savecmml)
filesave.close()
except IndexError:
convert_aqt(file(sys.argv[1]), fps)
print savecmml
except IndexError:
print "Usage: %s [Input AQTitle File] [Output CMML File]" % sys.argv[0]