#!/usr/bin/python3 import math import json import os import subprocess import sys import ox def run(cmd): #print(' '.join('"%s"' % c for c in cmd)) subprocess.call(cmd) edit_json = sys.argv[1] edit = json.load(open(edit_json)) render = './cache' output = os.path.splitext(edit_json)[0] + '.mp4' height = 480 aspect = 16/9 width = int(height * aspect) width -= width % 2 if not os.path.exists(render): os.makedirs(render) files = [] edit_duration = 0 subtitles = [] position = 0 for clip in edit: out = render + '/%s_%0.3f-%0.3f.ts' % (clip['oshash'], clip['in'], clip['out']) edit_duration += (clip['out']-clip['in']) files.append(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 clip_aspect = clip['resolution'][0] / clip['resolution'][1] if clip_aspect < aspect: x = width y = int(x / clip_aspect) y -= y % 2 else: y = height x = int(y * clip_aspect) x -= x % 2 vf = 'scale=%s:%s' % (x, y) if x != width: vf += ',crop=%s:%s' % (width, height) # crop center elif y != height: offset = int(((y - height) / 3)) vf += ',crop=w=%s:h=%s:x=0:y=%s' % (width, height, offset) options = [ '-map_metadata', '-1', '-vf', vf, '-aspect', str(aspect), '-c:v', 'libx264', '-b:v', '2M', '-preset:v', 'medium', '-profile:v', 'high', '-level:v', '4.0', '-map', '0:0,0:0', '-map', '0:1,0:1', '-r', '25', '-c:a', 'aac', '-ar', '48000', '-ac', '2', '-b:a', '192k', ] clip_duration = math.ceil((clip['out'] - clip['in']) / (1/25)) * 1/25 cmd = [ 'ffmpeg', '-nostats', '-loglevel', 'error', '-ss', str(clip['in']), '-i', clip['path'] ] + options + [ '-t', str(clip_duration), out ] 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' with open(txt, 'w') as fd: fd.write('file ' + '\nfile '.join(files)) cmd = ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', txt, '-c', 'copy', output] run(cmd) 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))