#!/usr/bin/env python3
import sys
import os
from optparse import OptionParser
import json
import math
import shutil
import tempfile
import time
import urllib.error
import urllib.parse
import urllib.request
import uuid
import xml.sax.saxutils
import ox
from PIL import Image
base = os.path.abspath(os.path.dirname(__file__))
generator_template = '''
Text
3000
FALSE
25
0
%(duration)s
%(start)s
%(end)s
TRUE
FALSE
black
Text
Text
Text
generator
video
str
Text
%(text)s
fontname
Font
%(font)s
fontsize
Size
0
1000
%(fontsize)s
fontstyle
Style
1
4
Plain
1
Bold
2
Italic
3
Bold/Italic
4
1
fontalign
Alignment
1
3
Left
1
Center
2
Right
3
1
fontcolor
Font Color
255
255
255
255
origin
Origin
-0.402778
-0.217014
fonttrack
Tracking
-200
200
1
leading
Leading
-100
100
0
aspect
Aspect
0.1
5
1
autokern
Auto Kerning
TRUE
subpixel
Use Subpixel
TRUE
Basic Motion
basic
motion
motion
video
center
Center
0
-0.00315457
video
$(uuid)s
'''
fcp_header = '''
'''
fcp_footer = ''''''
sequence_template = '''
$(uuid)s
add
%(id)s
%(duration)s
FALSE
25
FALSE
25
01:00:00:00
90000
NDF
-1
-1
FALSE
'''
def wrap_text(start, end, text, fontsize=30):
margin = 40
width = 1920 - 240
font = os.path.join(base, 'DejaVuSansCondensedBold.ttf')
if not os.path.exists(font):
font = '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono-Bold.ttf'
n = 10
alltxt = []
text = ox.strip_tags(ox.decode_html(text))
for t in text.strip().split('\n'):
lines = ox.wrapText(t, width - 2 * margin, 20, font, fontsize)
for line in lines:
alltxt.append(line)
alltxt.append('')
pages = int(math.ceil(len(alltxt) / n))
lines_per_page = int(math.ceil(len(alltxt) / pages))
frames_per_page = int((end - start) / pages)
pos = start
r = []
for p in range(0, len(alltxt), lines_per_page):
txt = alltxt[p:p+lines_per_page]
r.append((pos, pos+frames_per_page, txt))
pos += frames_per_page
return r
class Fcp:
sequences = []
fps = 25
fontsize = 18
font = 'Courier New'
#font = 'Lucida Grande'
gid = 0
def __init__(self, size=None, font=None):
if size is not None:
self.fontsize = size
if font is not None:
self.font = font
def add_srt(self, srt, wrap=True):
data = ox.srt.load(srt)
#info = api.get(id=item_id, keys=['layers'])
subs = []
#for s in info['data']['layers']['transcripts']:
duration = -1
for s in data:
value = s['value'].replace('
', '\n').replace('
', '\n')
value = ox.strip_tags(value)
start = int(s['in'] * fcp.fps)
end = int(s['out'] * fcp.fps)
if start < duration:
print("warning", start, '<', duration, value)
start = duration
duration = end
if wrap:
for t in wrap_text(start, end, value, self.fontsize):
subs.append(t)
else:
subs.append((start, end, value.split('\n')))
self.sequences.append(sequence_template % {
'id': os.path.splitext(os.path.basename(srt))[0],
'uuid': str(uuid.uuid1()).upper(),
'duration': duration,
'subs': '\n'.join([self.sub(*s) for s in subs])
})
def sub(self, start, end, text):
self.gid += 1
text = xml.sax.saxutils.escape('\n'.join(text).strip()).replace('\n', '
')
return generator_template % {
'id': self.gid,
'uuid': str(uuid.uuid1()).upper(),
'start': start,
'end': end,
'duration': end-start,
'text': text,
'fontsize': self.fontsize,
'font': self.font,
}
def save(self, output):
with open(output, 'w') as f:
f.write(fcp_header)
for s in self.sequences:
f.write(s)
f.write(fcp_footer)
if __name__ == '__main__':
usage = "usage: %prog srtfile"
parser = OptionParser(usage=usage)
parser.add_option('-w', '--wrap', dest='wrap', help='rewrap text', action="store_true")
parser.add_option('-s', '--size', dest='size', help='font size, default=18', type=int, default=18)
parser.add_option('-f', '--font', dest='font', help='font name, default="Courier New"', type=str, default='Courier New')
(opts, args) = parser.parse_args()
if not args:
parser.print_help()
sys.exit()
srt = args[0]
output = srt.replace('.srt', '') + '.xml'
fcp = Fcp(font=opts.font, size=int(opts.size))
fcp.add_srt(srt, opts.wrap)
fcp.save(output)