160 lines
4.6 KiB
Python
Executable file
160 lines
4.6 KiB
Python
Executable file
#!/usr/bin/python3
|
|
from argparse import ArgumentParser
|
|
from glob import glob
|
|
import json
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
def get_videoduration(video):
|
|
cmd = [
|
|
'ffprobe',
|
|
'-show_format',
|
|
'-show_chapters',
|
|
'-show_streams',
|
|
'-print_format', 'json',
|
|
'-i', video
|
|
]
|
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
stdout, stdin = p.communicate()
|
|
data = json.loads(stdout.decode())
|
|
duration = float([s for s in data['streams'] if 'width' in s][0]['duration']) - 70/60
|
|
return '%0.3f' % duration
|
|
|
|
def is_new(xml, mp4):
|
|
if not os.path.exists(mp4):
|
|
return True
|
|
vtime = os.path.getmtime(mp4)
|
|
xtime = max(
|
|
os.path.getmtime(xml),
|
|
os.path.getmtime('text.html'),
|
|
os.path.getmtime('encode.py'),
|
|
os.path.getmtime('DRONES.json'),
|
|
os.path.getmtime('VOCALS.json'),
|
|
)
|
|
return vtime < xtime
|
|
|
|
def encode(xml, force=False, prefix='.'):
|
|
item_json = xml.replace('.xml', '.json')
|
|
audio_xml = xml.replace('.xml', '.audio.xml')
|
|
vocals_xml = xml.replace('.xml', '.vocals.xml')
|
|
mp4 = xml.replace('.xml', '.mp4')
|
|
mp4_480p = mp4.replace('.mp4', '.480p.mp4')
|
|
video = mp4 + '.v.mov'
|
|
amix = mp4 + '.amix.mp4'
|
|
audio = mp4 + '.wav'
|
|
vocals = mp4 + '.vocals.wav'
|
|
silence = 'silence_mono.wav'
|
|
left = video + '_left.wav'
|
|
right = video + '_right.wav'
|
|
|
|
public_mp4 = os.path.join(prefix, 'public', mp4.split('/')[-1][0].lower() + mp4.split('/')[-2] + '.1080p.mp4')
|
|
public_mp4_480p = public_mp4.replace('.1080p.mp4', '.480p.mp4')
|
|
|
|
if force or is_new(xml, public_mp4):
|
|
cmd = [
|
|
'qmelt', xml, '-consumer',
|
|
'avformat:' + video,
|
|
'vcodec=libx264',
|
|
'acodec=pcm_s16le'
|
|
]
|
|
subprocess.call(cmd)
|
|
duration = get_videoduration(video)
|
|
cmd = [
|
|
'ffmpeg', '-y', '-i', video,
|
|
'-map_channel', '0.1.0', left,
|
|
'-map_channel', '0.1.1', right,
|
|
]
|
|
subprocess.call(cmd)
|
|
cmd = [
|
|
'qmelt', vocals_xml, '-consumer',
|
|
'avformat:' + vocals,
|
|
'acodec=pcm_s16le',
|
|
'ac=1'
|
|
]
|
|
subprocess.call(cmd)
|
|
#for wav in (left, right, vocals):
|
|
# cmd = ['normalize-audio', wav]
|
|
# subprocess.call(cmd)
|
|
cmd = [
|
|
'ffmpeg', '-y',
|
|
'-i', left, # FL
|
|
'-i', right, # FR
|
|
'-i', vocals, # FC
|
|
'-i', silence, # LFE
|
|
'-i', vocals, # BL
|
|
'-i', vocals, # BR
|
|
'-filter_complex',
|
|
'[0:0][1:0][2:0][3:0][4:0][5:0] amerge=inputs=6[aout]',
|
|
'-map', "[aout]",
|
|
'-strict', '-2',
|
|
'-c:a', 'aac',
|
|
amix
|
|
]
|
|
subprocess.call(cmd)
|
|
os.unlink(left)
|
|
os.unlink(right)
|
|
os.unlink(vocals)
|
|
|
|
cmd = [
|
|
'ffmpeg', '-y',
|
|
'-i', video,
|
|
'-i', amix,
|
|
'-t', duration,
|
|
'-c:a', 'copy',
|
|
'-c:v', 'copy',
|
|
'-map', '0:v:0', '-map', '1:a:0',
|
|
'-movflags', '+faststart',
|
|
mp4
|
|
]
|
|
subprocess.call(cmd)
|
|
os.unlink(video)
|
|
os.unlink(amix)
|
|
cmd = [
|
|
'ffmpeg', '-y',
|
|
'-i', mp4,
|
|
'-c:a', 'copy',
|
|
'-vf', 'scale=854:480',
|
|
'-c:v', 'libx264',
|
|
'-preset', 'medium',
|
|
'-b:v', '750k',
|
|
'-profile:v', 'high',
|
|
'-movflags', '+faststart',
|
|
mp4_480p
|
|
]
|
|
subprocess.call(cmd)
|
|
shutil.move(mp4, public_mp4)
|
|
shutil.move(mp4_480p, public_mp4_480p)
|
|
cmd = [
|
|
'./subtitles.py',
|
|
'--prefix', prefix,
|
|
item_json
|
|
]
|
|
subprocess.call(cmd)
|
|
|
|
def encode_all(prefix):
|
|
for xml in sorted(glob(os.path.join(prefix, 'output/*/*.xml'))):
|
|
parts = xml.split('.')
|
|
if len(parts) > 2 and parts[-2] in (
|
|
'audio',
|
|
'drones',
|
|
'music',
|
|
'source',
|
|
'vocals',
|
|
):
|
|
continue
|
|
encode(xml, prefix=prefix)
|
|
|
|
if __name__ == '__main__':
|
|
usage = "usage: %(prog)s [options] xml"
|
|
parser = ArgumentParser(usage=usage)
|
|
parser.add_argument('-p', '--prefix', dest='prefix',
|
|
help='version prefix', default='.')
|
|
parser.add_argument('files', metavar='path', type=str, nargs='*', help='xml files')
|
|
opts = parser.parse_args()
|
|
if opts.files:
|
|
for xml in opts.files:
|
|
encode(xml, True, prefix=opts.prefix)
|
|
else:
|
|
encode_all(prefix=opts.prefix)
|