audio downmix
This commit is contained in:
parent
135861e9d7
commit
e713d724b2
4 changed files with 136 additions and 20 deletions
|
@ -4,7 +4,7 @@ import os
|
|||
import shutil
|
||||
import subprocess
|
||||
|
||||
for xml in glob('output/*/*.xml'):
|
||||
for xml in sorted(glob('output/*/*.xml')):
|
||||
if xml.endswith('.audio.xml'):
|
||||
continue
|
||||
audio_xml = xml.replace('.xml', '.audio.xml')
|
||||
|
@ -16,6 +16,7 @@ for xml in glob('output/*/*.xml'):
|
|||
subprocess.call([
|
||||
'qmelt', xml, '-consumer', 'avformat:' + video, 'vcodec=libx264', 'strict=-2'
|
||||
])
|
||||
'''
|
||||
subprocess.call([
|
||||
'qmelt', audio_xml, '-consumer', 'avformat:' + audio,
|
||||
])
|
||||
|
@ -33,3 +34,5 @@ for xml in glob('output/*/*.xml'):
|
|||
os.unlink(video)
|
||||
os.unlink(audio)
|
||||
shutil.move(pre, mp4)
|
||||
'''
|
||||
shutil.move(video, mp4)
|
||||
|
|
75
render.py
75
render.py
|
@ -241,29 +241,68 @@ def sequence(seq, letter):
|
|||
blank = {'blank': True, 'duration': duration - last_text}
|
||||
result['text'].append(blank)
|
||||
|
||||
def add_blank(track, d):
|
||||
if track and track[-1].get('blank'):
|
||||
track[-1]['duration'] += d
|
||||
else:
|
||||
blank = {'blank': True, 'duration': d}
|
||||
track.append(blank)
|
||||
return d
|
||||
position += d
|
||||
|
||||
# music
|
||||
track = 'music'
|
||||
if letter in MUSIC:
|
||||
position = last_music = 0
|
||||
position = 0
|
||||
while position < duration:
|
||||
n = seq()
|
||||
if n == 0:
|
||||
blank = {'blank': True, 'duration': position - last_music}
|
||||
result['music'].append(blank)
|
||||
if n < 5:
|
||||
n = seq()
|
||||
position += add_blank(result[track], min(n, duration-position))
|
||||
else:
|
||||
n = seq()
|
||||
|
||||
clip = MUSIC[letter][n]
|
||||
position += clip['duration']
|
||||
if position > duration and result['music'][-1].get('blank'):
|
||||
result['music'][-1]['duration'] -= (position-duration)
|
||||
if position > duration \
|
||||
and result[track][-1].get('blank') \
|
||||
and result[track][-1]['duration'] > clip['duration']:
|
||||
result[track][-1]['duration'] -= (position-duration)
|
||||
print('one last alignment')
|
||||
position = duration
|
||||
result['music'].append(clip)
|
||||
last_music = position
|
||||
else:
|
||||
position += n
|
||||
if last_music < duration:
|
||||
blank = {'blank': True, 'duration': duration - last_music}
|
||||
result['music'].append(blank)
|
||||
if position <= duration:
|
||||
result[track].append(clip)
|
||||
else:
|
||||
position -= clip['duration']
|
||||
break
|
||||
if position < duration:
|
||||
position += add_blank(result[track], duration - position)
|
||||
# vocals
|
||||
track = 'vocals'
|
||||
if letter in VOCALS:
|
||||
position = 0
|
||||
while position < duration:
|
||||
n = seq()
|
||||
if n < 5:
|
||||
n = seq()
|
||||
position += add_blank(result[track], min(n, duration-position))
|
||||
else:
|
||||
n = seq()
|
||||
clip = VOCALS[letter][n]
|
||||
position += clip['duration']
|
||||
if position > duration \
|
||||
and result[track][-1].get('blank') \
|
||||
and result[track][-1]['duration'] > clip['duration']:
|
||||
result[track][-1]['duration'] -= (position-duration)
|
||||
position = duration
|
||||
if position <= duration:
|
||||
result[track].append(clip)
|
||||
else:
|
||||
position -= clip['duration']
|
||||
break
|
||||
if position < duration:
|
||||
print('padding', track, duration, position)
|
||||
position += add_blank(result[track], duration - position)
|
||||
'''
|
||||
if letter in VOCALS:
|
||||
n = seq()
|
||||
clip = VOCALS[letter][n]
|
||||
|
@ -279,7 +318,13 @@ def sequence(seq, letter):
|
|||
if n != 1:
|
||||
blank = {'blank': True, 'duration': silence - silence_start}
|
||||
result['vocals'].append(blank)
|
||||
'''
|
||||
|
||||
for track in result:
|
||||
if result[track]:
|
||||
tduration = sum([c['duration'] for c in result[track]])
|
||||
if not abs(tduration - duration) < 0.000001:
|
||||
raise Exception('invalid duration %s vs %s %s' % (tduration, duration, result[track]))
|
||||
return result
|
||||
|
||||
|
||||
|
@ -305,4 +350,4 @@ if __name__ == '__main__':
|
|||
with open(tjson, 'w') as fd:
|
||||
fd.write(current)
|
||||
subprocess.call(['./render_mlt.py', tjson])
|
||||
subprocess.call(['./render_audio.py', tjson])
|
||||
#subprocess.call(['./render_audio.py', tjson])
|
||||
|
|
|
@ -43,7 +43,6 @@ def add_clip(playlist, file_, duration):
|
|||
def add_blank(playlist, length):
|
||||
playlist.blank(length)
|
||||
|
||||
|
||||
for clip in data['music']:
|
||||
frames = int(clip['duration'] * fps)
|
||||
if clip.get('blank'):
|
||||
|
@ -58,9 +57,11 @@ for clip in data['vocals']:
|
|||
else:
|
||||
add_clip(vocals, clip['path'], frames)
|
||||
|
||||
multitrack.connect(music, 0)
|
||||
multitrack.connect(vocals, 1)
|
||||
multitrack.connect(vocals, 0)
|
||||
multitrack.connect(music, 1)
|
||||
composite = mlt.Transition(profile, "mix")
|
||||
composite.set("start", 0.01)
|
||||
composite.set("end", 0.01)
|
||||
composite.set("combine", 1)
|
||||
|
||||
tractor.plant_transition(composite)
|
||||
|
|
|
@ -28,6 +28,8 @@ with open(source) as fd:
|
|||
|
||||
video = mlt.Playlist()
|
||||
overlay = mlt.Playlist()
|
||||
music = mlt.Playlist()
|
||||
vocals = mlt.Playlist()
|
||||
|
||||
fps = 60
|
||||
profile = mlt.Profile("atsc_1080p_%d" % fps)
|
||||
|
@ -49,6 +51,14 @@ def add_clip(playlist, file_, in_, duration):
|
|||
clip.set_in_and_out(in_, in_+duration-1)
|
||||
playlist.append(clip)
|
||||
|
||||
def add_audio_clip(playlist, file_, duration):
|
||||
in_ = 0
|
||||
if not isinstance(file_, str):
|
||||
file_ = file_.encode('utf-8')
|
||||
clip = mlt.Producer(profile, file_)
|
||||
clip.set_in_and_out(in_, in_+duration-1)
|
||||
playlist.append(clip)
|
||||
|
||||
def add_blank(playlist, length):
|
||||
playlist.blank(length)
|
||||
|
||||
|
@ -61,6 +71,7 @@ def add_text(playlist, value, length):
|
|||
text.set('length', length)
|
||||
playlist.append(text)
|
||||
|
||||
|
||||
for clip in data['clips']:
|
||||
if clip.get('black'):
|
||||
# fixme seconds to fps! duration fame etc!!
|
||||
|
@ -84,6 +95,20 @@ for clip in data['text']:
|
|||
frames = int(clip['duration'] * fps)
|
||||
add_text(overlay, clip['text'].upper(), frames)
|
||||
|
||||
for clip in data['music']:
|
||||
frames = int(clip['duration'] * fps)
|
||||
if clip.get('blank'):
|
||||
add_blank(music, frames)
|
||||
else:
|
||||
add_audio_clip(music, clip['path'], frames)
|
||||
|
||||
for clip in data['vocals']:
|
||||
frames = int(clip['duration'] * fps)
|
||||
if clip.get('blank'):
|
||||
add_blank(vocals, frames)
|
||||
else:
|
||||
add_audio_clip(vocals, clip['path'], frames)
|
||||
|
||||
multitrack.connect(video, 0)
|
||||
multitrack.connect(overlay, 1)
|
||||
composite = mlt.Transition(profile, "composite")
|
||||
|
@ -91,8 +116,50 @@ composite = mlt.Transition(profile, "composite")
|
|||
|
||||
tractor.plant_transition(composite)
|
||||
|
||||
volume = mlt.Filter(profile, "volume")
|
||||
volume.set("gain", '0.01')
|
||||
tractor.plant_filter(volume)
|
||||
|
||||
# mix vocals and music
|
||||
|
||||
atractor = mlt.Tractor()
|
||||
atractor.mark_in = -1
|
||||
atractor.mark_out = -1
|
||||
|
||||
audio = atractor.multitrack()
|
||||
audio.connect(vocals, 0)
|
||||
audio.connect(music, 1)
|
||||
mix = mlt.Transition(profile, "mix")
|
||||
mix.set("start", 0.20)
|
||||
mix.set("end", 0.20)
|
||||
atractor.plant_transition(mix)
|
||||
|
||||
# mix video + audio
|
||||
dtractor = mlt.Tractor()
|
||||
dtractor.mark_in = -1
|
||||
dtractor.mark_out = -1
|
||||
dmix = dtractor.multitrack()
|
||||
dmix.connect(atractor, 0)
|
||||
dmix.connect(tractor, 1)
|
||||
|
||||
mix2 = mlt.Transition(profile, "mix")
|
||||
mix2.set("start", 0.5)
|
||||
mix2.set("end", 0.5)
|
||||
dtractor.plant_transition(mix2)
|
||||
|
||||
|
||||
output = mlt.Tractor()
|
||||
tractor.mark_in = -1
|
||||
tractor.mark_out = -1
|
||||
output_tracks = output.multitrack()
|
||||
output_tracks.connect(dtractor, 0)
|
||||
|
||||
norm = mlt.Filter(profile, "volume")
|
||||
norm.set("gain", "-12dB")
|
||||
output.plant_filter(norm)
|
||||
|
||||
consumer = 'xml'
|
||||
consumer = mlt.Consumer(profile, consumer, target)
|
||||
consumer.connect(tractor)
|
||||
consumer.connect(output)
|
||||
#consumer.set("real_time", -2)
|
||||
consumer.start()
|
||||
|
|
Loading…
Reference in a new issue