Scorewright - Claude composes, the tools render
Rule zero: Claude makes every creative decision in score.json and writes the reason (direction, cue why). The script has no default style, BPM, key or progression. Never reuse the last score as a template; start from the video.
PY = a Python 3.10+ with requirements.txt installed. SW = <this folder>/scripts/scorewright.py.
Before the first render on a machine, run PY SW doctor. If it says MISSING, follow README.md > Install, then stop and tell the user.
Runbook (QUICKSTART)
| # | Step | Command / action | Done when |
|---|---|---|---|
| 0 | Check | PY SW doctor | prints ready |
| 1 | Facts | PY SW analyze <video> <work> --words <words.json> (or --voice) | facts.json (duration, cuts, speech regions, timed words) + contact.jpg |
| 2 | Watch | Read contact.jpg (tile i = t i*step) and the timed words; read the script/storyboard if any | You can state message, audience feeling, emotional arc |
| 3 | Spot | Write a spotting table: cue in/out, hit points (word times, reveals, turns), where silence is better, emotion per section (dominant + secondary + intensity) | Every cue start/hit is a measured time |
| 4 | Direction | Choose identity with reasons: genre blend, key/mode, BPM per cue, palette, leitmotif (+ how it transforms), dynamic arc. Use references/craft.md | Written into direction |
| 5 | Score | Write score.json (references/score-format.md, example examples/bed_demo.json). Start each cue ON its hit point; use s:<sec> to place notes on words; PY SW fit <times> only to test one tempo inside a cue | Valid JSON |
| 6 | Render | PY SW render score.json <out> | stems, full, no_percussion, composition.mid, previews, SCORE_NOTES.md, qc.json, spectrogram.png |
| 7 | QC | Read qc.json + spectrogram.png; fix and re-render (new out folder per version) | all checks true; every hit rise_db >= 3; no unintended silences |
| 8 | Listen | The user listens to preview_with_voice.mp3. Claude cannot hear: say so, report the numbers, ask what to change | User approves |
| 9 | Deliver | Hand full_soundtrack.wav (already X LU under the raw voice, drop in at 0 dB) or the stems to the user's editor | - |
FIRST DECISION: bed or score
- Explainer / narrated video (speech nearly continuous) = BED. No melody, no leitmotif, no tune under speech. Use pulse, texture, slow harmony, sub only. Energy changes at section borders; 2-3 hits/drop-outs on real reveals; identity comes from timbre/rhythm, not a tune. A short tune only where there is NO speech (intro before the first word, last 1-2 s after the final word).
- Film / documentary with real speech-free stretches = SCORE. Leitmotif and melody live in those gaps.
- A melody under explanation is a second voice: the viewer must choose, and the explanation loses.
DO
- Silence, restraint and contrast are tools. Not every video needs music everywhere.
- One leitmotif per core idea; develop it (invert, augment, reharmonise, change one note) at story turns.
- Reduce density under dense explanation; let music speak in speech gaps and on visual-only moments.
- Engine choice per track:
gmfor acoustic realism (piano, strings, brass, winds, choir, mallets),aacfor synths / sound-designed voices (slow: ~10x gm; use for few, sparse tracks; optional),sfxfor impacts/swells/sub drops on hit points. - Bed
bed_lu_under_voice11 (energetic) to 12.6 (calm), measured in speech regions - the script sets it exactly. - New version = new out folder; never overwrite an approved render.
DON'T
- No swish / whoosh / page-flip sound.
riser/swellare tonal swells, use sparingly. - No copied melodies, recognisable themes or reference-track arrangements.
- No same BPM/key/progression for every video; no loudness as a stand-in for emotion.
- No SFX without a visual or story reason; no SFX louder than narration.
Known limits (tested)
- GM SoundFont orchestra = good mock-up, not Spitfire/Kontakt realism. Solo piano, pads, plucks, pizzicato and synths hold up best.
- One tempo per cue (tempo change = new cue). composition.mid uses absolute time with the first cue's tempo.
- audio-as-code render is slow (all-aac 76 s score: about 8 min on a Ryzen 5 5600H; mixed score: about 50 s).
- Claude cannot listen; QC numbers + spectrogram + user ears are the loop.