zeta-ball: mux narration per scene and concatenate

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAqjv3n4yABxvJPJHFRhVA
This commit is contained in:
teahubxyzandClaude Fable 5.1 committed 2026-10-27 20:48:04 +00:00
1 parent 07127dfaa0
commit 13ccacf4fd
1 file changed
+20
+20
View File
@@ -0,0 +1,20 @@
import json, subprocess
FF, FP = '/opt/homebrew/bin/ffmpeg', '/opt/homebrew/bin/ffprobe'
D = json.load(open('durations.json')); GAP = 0.6
pcm = open('zb.pcm', 'rb').read()
V = 'media/videos/zb/720p30'
off, parts = 0.0, []
for i, d in enumerate(D):
a = int(round(off * 24000)) * 2; n = int(round(d * 24000)) * 2
open(f'seg_{i}.pcm', 'wb').write(pcm[a:a + n])
off += d + GAP
vd = float(subprocess.run([FP, '-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', f'{V}/S{i}.mp4'], capture_output=True, text=True).stdout)
print(f'S{i}: video {vd:.2f}s narration {d:.2f}s slack {vd - d:.2f}s')
out = f'part_{i}.mp4'
subprocess.run([FF, '-v', 'error', '-y', '-i', f'{V}/S{i}.mp4', '-f', 's16le', '-ar', '24000', '-ac', '1', '-i', f'seg_{i}.pcm',
'-filter_complex', '[1:a]apad[a]', '-map', '0:v', '-map', '[a]', '-c:v', 'copy', '-c:a', 'aac', '-b:a', '128k',
'-ar', '48000', '-shortest', out], check=True)
parts.append(out)
open('list.txt', 'w').write(''.join(f"file '{p}'\n" for p in parts))
subprocess.run([FF, '-v', 'error', '-y', '-f', 'concat', '-safe', '0', '-i', 'list.txt', '-c:v', 'libx264', '-crf', '20', '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-b:a', '128k', 'zeta-ball.mp4'], check=True)
print(subprocess.run([FP, '-v', 'error', '-show_entries', 'format=duration,size', '-of', 'default=noprint_wrappers=1', 'zeta-ball.mp4'], capture_output=True, text=True).stdout)