Tighten the trailer to 1:30 and fix its two audio faults
Cut 3 of LIFETIME MEMBERS: the intro music no longer runs into Reg's first line, Ambrose finishes "...still waiting for a result" (line ends are now measured off each take instead of the QA transcript), every shot is tighter, and the black title cards are set larger. Cut 2 stays on disk beside it as the reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d388004eac
commit
5fba837ead
5 files changed
+65
-36
No files matched your search
+37
-28
@@ -23,35 +23,38 @@ game = lambda n: os.path.join(ROOT, 'assets', 'audio', n)
|
||||
# ov: [(card, t_in, t_out)] faded overlays · fi/fo: picture fade from/to black · gain: clip audio dB
|
||||
# mute: drop the clip's own audio · dlg: a spoken line — its gain is MEASURED so every voice in the
|
||||
# film sits at DLG LUFS (eq: lift a voice out of loud ambience first)
|
||||
L3 = (0.7, 4.8)
|
||||
L3 = (0.6, 4.6)
|
||||
DLG = -20.0
|
||||
QUIET = 2.3 # seconds into s_amb where "please" ends and the music is cut
|
||||
CUT = 3 # cut 2 (1:45) is kept beside it as lifetime-members-cut2.mp4, the reference
|
||||
# Line ends below are MEASURED off each take's speech-band envelope, not off the QA transcript
|
||||
# (its timestamps drift): cut 2 lost the end of Ambrose's "...result" by trusting 6.6 s; it is 7.2.
|
||||
EDL = [
|
||||
('gates', 'gates_v1', 0.0, 7.0, dict(fi=1.2, gain=-2, afi=1.0)),
|
||||
('court', 'court_v1', 0.0, 5.0, dict(gain=-4)),
|
||||
('board', 'board_v1', 0.0, 5.5, dict(fo=0.5, gain=-3, afo=0.5)),
|
||||
('trad', None, 0, 5.2, dict(ov=[('t_a', 0.3, 4.8), ('t_b', 2.3, 4.8)])),
|
||||
('title', None, 0, 4.0, dict(ov=[('title', 0.2, 3.5)])),
|
||||
('q1', None, 0, 2.3, dict(ov=[('q_start', 0.15, 2.0)])),
|
||||
('reg', 'reg_v1.keep', 0.0, 7.3, dict(ov=[('lt_reg', *L3)], dlg=True)),
|
||||
('tin', 'tin_v1', 0.0, 3.0, dict(gain=-6)),
|
||||
('doris', 'doris_v1', 0.0, 8.0, dict(ov=[('lt_doris', *L3)], dlg=True)),
|
||||
('cream', 'cream_v1', 0.0, 3.2, dict(gain=-6)),
|
||||
('clive', 'clive_v1', 0.0, 6.3, dict(ov=[('lt_clive', *L3)], dlg=True)),
|
||||
('bylaws', 'bylaws_v1', 0.0, 3.0, dict(gain=-6)),
|
||||
('ambrose', 'ambrose_v1', 0.0, 7.0, dict(ov=[('lt_ambrose', *L3)], dlg=True)),
|
||||
('archive', 'archive_v1', 0.0, 5.0, dict(fo=0.5, gain=-4, afo=0.5)),
|
||||
('q2', None, 0, 2.3, dict(ov=[('q_chall', 0.15, 2.0)])),
|
||||
('s_doris', 'stare_doris_v1', 0.6, 3.4, dict(dlg=True)),
|
||||
('s_clive', 'stare_clive_v2', 0.8, 3.2, dict(gain=-6)),
|
||||
('gates', 'gates_v1', 0.0, 5.6, dict(fi=1.0, gain=-2, afi=0.8)),
|
||||
('court', 'court_v1', 0.0, 4.0, dict(gain=-4)),
|
||||
('board', 'board_v1', 0.0, 4.6, dict(fo=0.5, gain=-3, afo=0.5)),
|
||||
('trad', None, 0, 4.4, dict(ov=[('t_a', 0.25, 4.0), ('t_b', 1.8, 4.0)])),
|
||||
('title', None, 0, 3.4, dict(ov=[('title', 0.15, 3.0)])),
|
||||
('q1', None, 0, 1.9, dict(ov=[('q_start', 0.1, 1.7)])),
|
||||
('reg', 'reg_v1.keep', 0.0, 7.1, dict(ov=[('lt_reg', *L3)], dlg=True)),
|
||||
('tin', 'tin_v1', 0.0, 2.2, dict(gain=-6)),
|
||||
('doris', 'doris_v1', 0.0, 7.6, dict(ov=[('lt_doris', *L3)], dlg=True)),
|
||||
('cream', 'cream_v1', 0.4, 2.2, dict(gain=-6)),
|
||||
('clive', 'clive_v1', 0.0, 6.1, dict(ov=[('lt_clive', *L3)], dlg=True)),
|
||||
('bylaws', 'bylaws_v1', 0.0, 2.2, dict(gain=-6)),
|
||||
('ambrose', 'ambrose_v1', 0.0, 7.9, dict(ov=[('lt_ambrose', *L3)], dlg=True, afo=0.5)),
|
||||
('archive', 'archive_v1', 0.0, 3.8, dict(fo=0.5, gain=-4, afo=0.5)),
|
||||
('q2', None, 0, 1.9, dict(ov=[('q_chall', 0.1, 1.7)])),
|
||||
('s_doris', 'stare_doris_v1', 0.7, 2.7, dict(dlg=True)),
|
||||
('s_clive', 'stare_clive_v2', 1.0, 2.8, dict(gain=-6)),
|
||||
# "Quiet, please." — and the score obeys: it stops dead on the end of "please" (see MUSIC)
|
||||
('s_amb', 'stare_ambrose_v1', 0.0, 3.2, dict(dlg=True, afo=0.9)),
|
||||
('stands', 'stands_close_v2', 0.9, 3.5, dict(gain=-17)), # the heads creak, barely
|
||||
('play', 'ambrose_night_v2', 0.0, 2.0, dict(dlg=True)),
|
||||
('splat', None, 0, 1.6, dict()),
|
||||
('logo', None, 0, 4.6, dict(ov=[('logo', 0.25, 4.6)], fo=0.6)),
|
||||
('stinger', 'reg_dawn_v1', 0.0, 5.4, dict(fi=0.4, afi=0.35, dlg=(0.0, 2.6), lift=2, eq=True)),
|
||||
('end', None, 0, 4.2, dict(ov=[('end', 0.5, 4.2)], fo=1.0)),
|
||||
('s_amb', 'stare_ambrose_v1', 0.0, 3.0, dict(dlg=True, afo=0.8)),
|
||||
('stands', 'stands_close_v2', 0.9, 3.0, dict(gain=-17)), # the heads creak, barely
|
||||
('play', 'ambrose_night_v2', 0.0, 1.9, dict(dlg=True)),
|
||||
('splat', None, 0, 1.2, dict()),
|
||||
('logo', None, 0, 3.8, dict(ov=[('logo', 0.2, 3.8)], fo=0.5)),
|
||||
('stinger', 'reg_dawn_v1', 0.6, 3.6, dict(fi=0.4, afi=0.35, dlg=(1.0, 2.7), lift=2, eq=True)),
|
||||
('end', None, 0, 3.6, dict(ov=[('end', 0.4, 3.6)], fo=0.9)),
|
||||
]
|
||||
|
||||
# every segment is a whole number of frames, or the audio drifts a sub-frame per cut
|
||||
@@ -63,9 +66,15 @@ for name, _, _, dur, _ in EDL:
|
||||
TOTAL = t
|
||||
|
||||
# music/effects: (file, src_in, dur, at, gain dB, fade_in, fade_out)
|
||||
# m_open turns a corner at 21.0 s (segment.py's join): that turn lands on the title card, and the
|
||||
# whole cue has faded out under the question card, before Reg opens his mouth (cut 2 ran it 3 s into
|
||||
# his line — Oliver: "the music from the intro is overlapping the voice")
|
||||
OPEN_TURN = 21.0
|
||||
o_in = max(0.0, OPEN_TURN - start['title'])
|
||||
o_at = max(0.0, start['title'] - OPEN_TURN)
|
||||
MUSIC = [
|
||||
(aud('m_open.mp3'), 0.0, 30.5, start['gates'] + 1.5, -11, 2.0, 2.5),
|
||||
(aud('cue_a.mp3'), 35.0, 38.6, start['reg'], -20, 1.5, 2.0),
|
||||
(aud('m_open.mp3'), o_in, start['q1'] + 1.2 - o_at, o_at, -11, 2.0, 3.4), # gone mid-question
|
||||
(aud('cue_a.mp3'), 35.0, start['q2'] - start['reg'], start['reg'], -20, 1.5, 2.0),
|
||||
# the drone sits low under Doris, then swells through Clive's eyes so the shush has something to stop
|
||||
(aud('cue_b.mp3'), 0.0, start['s_amb'] + QUIET - start['q2'], start['q2'], -17, 1.0, 0.01,
|
||||
f"'if(lt(t,{start['s_clive'] - start['q2']:.2f}),1,min(2.4,1+(t-{start['s_clive'] - start['q2']:.2f})*0.6))':eval=frame"),
|
||||
@@ -181,7 +190,7 @@ def mix(parts):
|
||||
# a touch of contrast, a little less saturation, a soft vignette, and live 35mm-ish grain
|
||||
f.append('[0:v]eq=contrast=1.04:saturation=0.9:gamma=0.98,vignette=angle=PI/5.5,'
|
||||
'noise=c0s=5:c0f=t+u,format=yuv420p[v]')
|
||||
out = os.path.join(T, 'lifetime-members.mp4')
|
||||
out = os.path.join(T, f'lifetime-members-cut{CUT}.mp4')
|
||||
cmd += ['-filter_complex', ';'.join(f), '-map', '[v]', '-map', '[a]',
|
||||
# grain is the costliest thing to encode: tune for it and cap the rate (~14 Mb/s keeps it
|
||||
# postable everywhere; uncapped crf 16 came out at 36 Mb/s, 480 MB for 2 minutes)
|
||||
|
||||
Reference in new issue
Block a user