align subtitles to clips

This commit is contained in:
j 2017-08-13 19:24:50 +02:00
parent 4f88792491
commit 609a1209ab
2 changed files with 58 additions and 11 deletions

31
edit.py
View file

@ -1,6 +1,7 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os import os
import json import json
import math
import ox import ox
import ox.web.auth import ox.web.auth
@ -46,7 +47,7 @@ def sort_clips(edit, sort):
'id', 'index', 'in', 'out', 'duration', 'id', 'index', 'in', 'out', 'duration',
'title', 'director', 'year', 'videoRatio' 'title', 'director', 'year', 'videoRatio'
]: ]:
s = sorted(clips, key=lambda c: (str(c.get(sort, last)), c['in'], c['out'])) s = sorted(clips, key=lambda c: (str(c.get(sort, last)), c['title'], c['in'], c['out']))
if reverse: if reverse:
s = reversed(s) s = reversed(s)
else: else:
@ -77,6 +78,15 @@ if __name__ == '__main__':
position = 0 position = 0
for clip in sort_clips(edit, sort_by): for clip in sort_clips(edit, sort_by):
clip_subtitles = []
for sub in clip['layers']['subtitles']:
subtitles.append({
'in': position,
'out': position + (sub['out'] - sub['in']),
'value': sub['value'].replace('<br/>', '\n').replace('<br>', '\n').replace('\n\n', '\n'),
})
clip_subtitles.append(sub['value'].replace('<br/>', '\n').replace('<br>', '\n').replace('\n\n', '\n'))
part_pos = 0 part_pos = 0
for i, duration in enumerate(clip['durations']): for i, duration in enumerate(clip['durations']):
if part_pos + duration < clip['in']: if part_pos + duration < clip['in']:
@ -84,6 +94,10 @@ if __name__ == '__main__':
elif part_pos <= clip['in']: elif part_pos <= clip['in']:
stream_in = clip['in'] - part_pos stream_in = clip['in'] - part_pos
stream_out = min(clip['out'] - part_pos, duration) stream_out = min(clip['out'] - part_pos, duration)
stream_in = math.ceil(stream_in / (1/25)) * 1/25
stream_out = math.ceil(stream_out / (1/25)) * 1/25
part_pos += duration part_pos += duration
info = get_info(api, clip['streams'][i]) info = get_info(api, clip['streams'][i])
videos.append({ videos.append({
@ -91,11 +105,14 @@ if __name__ == '__main__':
'path': os.path.join(prefix, info['path']), 'path': os.path.join(prefix, info['path']),
'resolution': info['resolution'], 'resolution': info['resolution'],
'in': stream_in, 'in': stream_in,
'out': stream_out 'out': stream_out,
'subtitles': '\n'.join(clip_subtitles)
}) })
elif clip['out'] > part_pos: elif clip['out'] > part_pos:
stream_in = part_pos stream_in = part_pos
stream_out = min(clip['out'] - part_pos, duration) stream_out = min(clip['out'] - part_pos, duration)
stream_in = math.ceil(stream_in / (1/25)) * 1/25
stream_out = math.ceil(stream_out / (1/25)) * 1/25
part_pos += duration part_pos += duration
info = get_info(api, clip['streams'][i]) info = get_info(api, clip['streams'][i])
videos.append({ videos.append({
@ -103,17 +120,13 @@ if __name__ == '__main__':
'path': info['path'], 'path': info['path'],
'resolution': info['resolution'], 'resolution': info['resolution'],
'in': stream_in, 'in': stream_in,
'out': stream_out 'out': stream_out,
'subtitles': '\n'.join(clip_subtitles)
}) })
for sub in clip['layers']['subtitles']:
subtitles.append({
'in': position,
'out': position + (sub['out'] - sub['in']),
'value': sub['value'].replace('<br/>', '\n').replace('<br>', '\n').replace('\n\n', '\n'),
})
position += clip['duration'] position += clip['duration']
position = math.ceil(position / (1/25)) * 1/25
name = normalize(edit_id) name = normalize(edit_id)
if sort_by != 'year': if sort_by != 'year':

View file

@ -3,6 +3,7 @@ import json
import os import os
import subprocess import subprocess
import sys import sys
import ox
def run(cmd): def run(cmd):
#print(' '.join('"%s"' % c for c in cmd)) #print(' '.join('"%s"' % c for c in cmd))
@ -12,7 +13,7 @@ def run(cmd):
edit_json = sys.argv[1] edit_json = sys.argv[1]
edit = json.load(open(edit_json)) edit = json.load(open(edit_json))
render = '/tmp/out' render = './cache'
output = os.path.splitext(edit_json)[0] + '.mp4' output = os.path.splitext(edit_json)[0] + '.mp4'
height = 480 height = 480
aspect = 16/9 aspect = 16/9
@ -23,10 +24,23 @@ if not os.path.exists(render):
os.makedirs(render) os.makedirs(render)
files = [] files = []
edit_duration = 0
subtitles = []
position = 0
for clip in edit: for clip in edit:
out = render + '/%s_%0.3f-%0.3f.ts' % (clip['oshash'], clip['in'], clip['out']) out = render + '/%s_%0.3f-%0.3f.ts' % (clip['oshash'], clip['in'], clip['out'])
edit_duration += (clip['out']-clip['in'])
files.append(out) files.append(out)
if os.path.exists(out): if os.path.exists(out):
duration = ox.avinfo(out)['duration']
if clip['subtitles']:
subtitles.append({
'in': position,
'out': position+duration,
'value': clip['subtitles']
})
position += duration
print(out, duration, (clip['out'] - clip['in']))
continue continue
clip_aspect = clip['resolution'][0] / clip['resolution'][1] clip_aspect = clip['resolution'][0] / clip['resolution'][1]
if clip_aspect < aspect: if clip_aspect < aspect:
@ -44,12 +58,14 @@ for clip in edit:
offset = int(((y - height) / 3)) offset = int(((y - height) / 3))
vf += ',crop=w=%s:h=%s:x=0:y=%s' % (width, height, offset) vf += ',crop=w=%s:h=%s:x=0:y=%s' % (width, height, offset)
options = [ options = [
'-map_metadata', '-1',
'-vf', vf, '-vf', vf,
'-aspect', str(aspect), '-aspect', str(aspect),
'-c:v', 'libx264', '-c:v', 'libx264',
'-b:v', '2M', '-b:v', '2M',
'-preset:v', 'medium', '-profile:v', 'high', '-level:v', '4.0', '-preset:v', 'medium', '-profile:v', 'high', '-level:v', '4.0',
'-r:v', '25', '-map', '0:0,0:0', '-map', '0:1,0:1',
'-r', '25',
'-c:a', 'aac', '-c:a', 'aac',
'-ar', '48000', '-ar', '48000',
'-ac', '2', '-ac', '2',
@ -65,6 +81,15 @@ for clip in edit:
out out
] ]
run(cmd) run(cmd)
duration = ox.avinfo(out)['duration']
if clip['subtitles']:
subtitles.append({
'in': position,
'out': position+duration,
'value': clip['subtitles']
})
position += duration
print(out, duration, (clip['out'] - clip['in']))
txt = output + '.txt' txt = output + '.txt'
with open(txt, 'w') as fd: with open(txt, 'w') as fd:
@ -72,3 +97,12 @@ with open(txt, 'w') as fd:
cmd = ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', txt, '-c', 'copy', output] cmd = ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', txt, '-c', 'copy', output]
run(cmd) run(cmd)
os.unlink(txt) os.unlink(txt)
srt = output.replace('.mp4', '.srt')
with open(srt, 'wb') as fd:
fd.write(ox.srt.encode(subtitles))
duration = ox.avinfo(output)['duration']
print('file is %d, edit should be %d' % (duration, edit_duration))