███████╗ ██████╗ ███╗ ██╗██╗ ██████╗ ██████╗██████╗ █████╗ ███████╗████████╗ ██╔════╝██╔═══██╗████╗ ██║██║██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝╚══██╔══╝ ███████╗██║ ██║██╔██╗ ██║██║██║ ██║ ██████╔╝███████║█████╗ ██║ ╚════██║██║ ██║██║╚██╗██║██║██║ ██║ ██╔══██╗██╔══██║██╔══╝ ██║ ███████║╚██████╔╝██║ ╚████║██║╚██████╗╚██████╗██║ ██║██║ ██║██║ ██║ ╚══════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
> declarative audio for AI agents
Your agent writes the script as one YAML timeline. SonicCraft compiles it into TTS voices, music beds and sound effects: measured to the sample, ducked under every word, mastered to broadcast loudness, with subtitles that match the audio. A CLI, an MCP server and an Agent Skill.
curl -fsSL https://raw.githubusercontent.com/user-github-me/soniccraft/main/install.sh | sh01how it works
Intent goes in as data; SonicCraft does the geometry. Everything below is real output for this one timeline, rendered with the built-in mock voice: no API key needed.
version: "1.0" output: { path: episode.mp3, format: mp3, export_subtitles: [vtt, srt] } speakers: host: { provider: mock, voice_id: host } # or elevenlabs, openai, kokoro, piper... guest: { provider: mock, voice_id: guest } tracks: - id: voice type: speech start_at_ms: 1500 sequence: - { speaker: host, text: "Welcome back to the show." } - pause: 300ms - { id: thanks, speaker: guest, text: "Thanks! Today: audio for AI agents." } - id: bed type: music source: music/bed.wav loop: true end_relative: { after_cue: thanks, offset_ms: 2000 } ducking: { trigger_tracks: [voice], reduction_db: -18 }
$ soniccraft plan timeline.yaml SonicCraft plan duration 0:08.6 | 48000 Hz | 2 tracks | 2 cues, 1 pause, 1 clip time 0s 1s 2s 3s 4s 5s 6s 7s 8s |--+---|---+---|---+---|---+---|--+---|---+---|---+---|---+---|---+ voice ############## ######################### bed ===========------------------------------------------------------============== legend: # speech = music/sfx - ducked blank = silence (1 col = 0.13 s)
$ soniccraft render timeline.yaml Rendered episode.mp3 in 0.28 s format mp3, 48000 Hz, stereo, 192 kbps, 208.5 kB duration 8.62 s loudness -16.0 LUFS (target -16.0), true peak -7.3 dBTP (ceiling -1.0), LRA 0.6 LU subtitles episode.vtt, episode.srt synthesis 2 cues: 2 synthesized, 0 from cache (called mock)
02errors an agent can fix
Every problem comes with a stable code, the exact line and column, and a hint. People read the
text; agents get the same report as JSON with --json.
$ soniccraft validate timeline.yaml error[unknown_reference]: `after_cue` refers to `intr`, which is not the id of a cue, clip or track --> timeline.yaml:10:38 | 10 | start_relative: { after_cue: intr, offset_ms: "350 ms" } | ^^^^ | = hint: Did you mean `intro`? Known ids: `voice`, `intro`, `voice.cue2`, `bed` error[unknown_field]: unknown field `file` in music track `bed` --> timeline.yaml:13:5 | 13 | file: assets/audio/synthwave_loop.wav | ^^^^ | = hint: Did you mean `source`? Write `source: "assets/audio/synthwave_loop.wav"` error: timeline.yaml is invalid: 2 errors (1 note hidden, use -v to show)
03what's inside
A Rust engine built like a compiler: parse, lower, lay out, synthesize, mix, master.
- [x]sample-accurate layoutevery clip measured; overlapping lines moved apart
- [x]sidechain duckingmusic dips under each word, with attack, hold and release
- [x]broadcast loudnessEBU R128 mastering, true-peak limiter, -16 / -14 LUFS presets
- [x]word-timed subtitlesWebVTT, SRT, JSON word timings, HyperFrames transcripts
- [x]free dry runslayout, ducking and cost before a single TTS call
- [x]deterministicsame input, byte-identical audio; TTS results cached
- [x]8 voice providersElevenLabs, OpenAI-compatible, Cartesia, Kokoro, Piper, macOS, command, mock
- [x]outputsWAV, MP3, FLAC (OGG, Opus, M4A via ffmpeg), stems, manifest, web preview
04plug it into your agent
Install the CLI above, then give your agent the skill and the MCP server, or just the link.
claude plugin marketplace add user-github-me/soniccraftclaude plugin install soniccraft@soniccraftcodex mcp add soniccraft -- soniccraft mcpnpx skills add user-github-me/soniccraft -g -a codexnpx skills add user-github-me/soniccraft -g -a cursornpx -y soniccraft-mcp