#!/usr/bin/env python3 """Sound effects: generate them with ElevenLabs, or synthesize a crisp UI tick locally. python3 sfx.py sfx.json --out sfx/ sfx.json: {"impact": ["Deep cinematic impact hit ...", 2.5], ...} python3 sfx.py --tick sfx/tick.wav a short two-tone click (no API), the sound reviewers liked best for clicks Generated effects can come back nearly silent; the script reports each file's peak so you notice. Useful set: an impact (cut to the title, the final reveal), a short reverse riser (into the reveal), a soft whoosh (whip transitions). Needs ELEVENLABS_API_KEY with the Sound Effects permission. """ import argparse, json, os, subprocess, sys from common import key, http_bytes, ffmpeg, decode ap = argparse.ArgumentParser() ap.add_argument("spec", nargs="?"); ap.add_argument("--out", default="sfx"); ap.add_argument("--tick") a = ap.parse_args() if a.tick: os.makedirs(os.path.dirname(os.path.abspath(a.tick)), exist_ok=True) expr = "0.55*sin(2*PI*2400*t)*exp(-t*110)+0.25*sin(2*PI*5200*t)*exp(-t*220)" subprocess.run([ffmpeg(), "-v", "error", "-y", "-f", "lavfi", "-i", f"aevalsrc='{expr}':s=48000:d=0.12", "-ac", "2", a.tick], check=True) print("wrote", a.tick); sys.exit() K = key("ELEVENLABS_API_KEY") os.makedirs(a.out, exist_ok=True) for name, (text, seconds) in json.load(open(a.spec)).items(): out = f"{a.out}/{name}.mp3" if not os.path.exists(out): data = http_bytes("https://api.elevenlabs.io/v1/sound-generation?output_format=mp3_44100_192", {"text": text, "duration_seconds": seconds, "prompt_influence": 0.6}, {"xi-api-key": K}) open(out, "wb").write(data) import numpy as np x = decode(out) peak = 20 * np.log10(np.abs(x).max() + 1e-9) onset = int(np.argmax(np.abs(x) > np.abs(x).max() * 0.3)) / 44100 print(f"{name}: peak {peak:.0f} dBFS, attack at {onset:.2f}s" + (" <- nearly silent, regenerate or synthesize" if peak < -30 else ""))