关于 SonicCraft
SonicCraft 是面向 AI Agent、命令行用户和 MCP 客户端的确定性音频引擎。它将 YAML 或 JSON 时间线编译为混音并完成响度母带处理的语音、音乐和音效,并生成与渲染音频对应的字幕。
主要功能
- 01编译 YAML 或 JSON 音频时间线
- 02组合 TTS、音乐与音效
- 03自动安排时间并进行侧链闪避
- 04响度归一化与峰值限制
- 05生成字幕和分轨文件
- 06渲染前验证并预览
适用场景
- 01制作带背景音乐的旁白
- 02制作带定时停顿的多人语音
- 03生成带匹配字幕的音频
- 04渲染前预览时间安排和合成字符量
MCP 相关
MCP 服务向 MCP 客户端提供 SonicCraft 音频工作流,也可通过 Agent 集成使用。它调用 SonicCraft CLI 执行验证、计划和渲染。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm -e ELEVENLABS_API_KEY -e OPENAI_API_KEY -e CARTESIA_API_KEY ghcr.io/user-github-me/soniccraft:0.1.0ELEVENLABS_API_KEY密钥ElevenLabs API key for the elevenlabs TTS provider (optional)OPENAI_API_KEY密钥OpenAI API key for the openai TTS provider (optional)CARTESIA_API_KEY密钥Cartesia API key for the cartesia TTS provider (optional)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/user-github-me/soniccraft:0.1.0stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
SonicCraft
一款面向 AI Agent 的声明式、确定性音频引擎。 用 YAML(或 JSON)时间线描述制作内容:谁说什么、按什么顺序、配什么音乐、音量多大。SonicCraft 会将其编译为 TTS 语音、背景音乐和音效,通过侧链压低背景音进行混音,并按照 EBU R128 响度目标进行母带处理,还会生成与实际渲染音频相匹配的 WebVTT/SRT 字幕。它以 CLI、MCP 服务和 Agent Skill 的形式提供。
官方网站 · 快速入门 · 在 AI Agent 中使用 · MCP 服务 · Agent Skill
在 AI Agent 中使用
将此仓库链接提供给 Agent(Claude Code、Codex、Cursor、Gemini CLI 等),并请它制作音频,例如 “使用 https://github.com/user-github-me/soniccraft 为我的产品视频制作一段 30 秒的配背景音乐旁白。” 所需内容见下文和 AGENTS.md。
-
安装 CLI(预构建并已验证校验和,无需 Rust)。也支持 Homebrew、Scoop、Docker 和 Cargo:参见快速入门。
curl -fsSL https://raw.githubusercontent.com/user-github-me/soniccraft/main/install.sh | sh # macOS, Linuxirm https://raw.githubusercontent.com/user-github-me/soniccraft/main/install.ps1 | iex # Windows -
编写时间线。
soniccraft init my-audio会创建一个可离线渲染的时间线:在 Mac 上使用 macOS 语音,其他平台使用模拟测试语音(不是真实语音)。要在任何平台使用真实语音,可选 Kokoro 或 Piper(免费、本地运行),也可使用 ElevenLabs、OpenAI 或 Cartesia 密钥;参见提供方。soniccraft init --list会显示模板,soniccraft providers会显示此处可用的语音,soniccraft schema会显示 JSON Schema;Agent Skill 介绍了格式。 -
检查、查看费用并进行渲染:
soniccraft validate my-audio/timeline.yaml # errors with a code, line, column and fix hint soniccraft plan my-audio/timeline.yaml # free dry run: timing, ducking, characters to synthesize soniccraft render my-audio/timeline.yaml --preview # mastered audio, subtitles, manifest, preview page
要让 Agent 持续使用 SonicCraft,请添加 Skill 和 MCP 服务。两者都使用步骤 1 中的 CLI;如果安装了 Node.js 20 或更高版本,MCP 服务也可以在无需安装任何内容的情况下运行:在下文中用 npx -y soniccraft-mcp 替代 soniccraft mcp。
| Agent | Skill | MCP 服务 |
|---|---|---|
| Claude Code | claude plugin marketplace add user-github-me/soniccraft,然后运行 claude plugin install soniccraft@soniccraft | 插件中已包含,或运行 claude mcp add soniccraft -- soniccraft mcp |
| Codex | npx skills add user-github-me/soniccraft -g -a codex | codex mcp add soniccraft -- soniccraft mcp |
| Cursor | npx skills add user-github-me/soniccraft -g -a cursor | 在 .cursor/mcp.json 中填写 {"mcpServers": {"soniccraft": {"command": "soniccraft", "args": ["mcp"]}}} |
| Gemini CLI 和其他工具 | npx skills add user-github-me/soniccraft -g(选择 Agent) | 使用相同的 mcpServers 条目(Gemini CLI:~/.gemini/settings.json) |
此服务也已作为容器映像收录在官方 MCP Registry,名称为 io.github.user-github-me/soniccraft。详情见:MCP 服务和Agent Skill。
原因
让 Agent 制作带背景音乐的双人讲解,通常会得到它手写的 ffmpeg 滤镜图:adelay 的偏移量根据猜测的语音时长计算,再加上 amix,或许还有一个只记得一半的 sidechaincompress。这会以一些可预见的方式出错:
- 时间漂移和重叠。 合成语音的时长永远不会和 Agent 猜测的完全一致,因此台词会相互冲突或留下空白,而且每次修改脚本都会改变后续所有偏移量。
- 没有自动压低背景音乐。 很难在滤镜图中正确设置侧链压缩,因此背景音乐要么盖过人声,要么始终音量过低。
- 响度差异。 不同提供商和语音的输出音量各不相同。没有任何机制会测量综合响度或真峰值,因此成品音量不均,还可能出现削波。
- 字幕漂移。 字幕是根据估算时间编写的,而不是根据渲染完成的音频生成。
- 迭代过程不透明且成本高。 出错的滤镜图只会返回难以理解的 ffmpeg 错误,而每次重试都会再次为所有 TTS 调用付费。
SonicCraft 的工作原理
HyperFrames 表明,当 Agent 编写声明式 HTML,再由确定性渲染器完成精确到帧的工作时,制作出的视频效果更好。SonicCraft 将同样的理念应用于音频。Agent 将意图写成数据;编译器会验证数据、测量实际时长、以整数采样帧解析所有时间,并使用 Rust 原生渲染。同一条时间线、TTS 缓存和二进制文件始终会生成字节完全一致的音频、字幕和清单。
version: "1.0"
output:
format: "mp3"
sample_rate: 48000
bitrate: "320k"
target_lufs: -16.0 # integrated loudness target, measured per EBU R128 / ITU-R BS.1770
export_subtitles: true # Emits matching .vtt and .srt
tracks:
- id: ambient_bed
type: "music"
source: "assets/audio/synthwave_loop.wav"
loop: true
volume: 0.65
fade_in_ms: 1200
fade_out_ms: 2500
ducking:
trigger_tracks: ["voice_primary", "voice_secondary"]
reduction_db: -18.0
attack_ms: 80
release_ms: 350
- id: voice_primary
type: "speech"
pan: -0.15 # Subtle left stereo placement
sequence:
- id: cue_01
speaker: "narrator"
provider: "elevenlabs"
voice_id: "21m00Tcm4TlvDq8ikWAM"
text: "Autonomous software development requires deterministic compilation targets."
- pause_duration: 350ms
- id: cue_03
speaker: "narrator"
provider: "elevenlabs"
voice_id: "21m00Tcm4TlvDq8ikWAM"
text: "By separating high-level planning from digital signal processing, systems eliminate runtime hallucinations."
- id: voice_secondary
type: "speech"
pan: 0.15 # Subtle right stereo placement
sequence:
- id: cue_02
start_relative:
after_cue: "cue_01"
offset_ms: 150
speaker: "guest"
provider: "local_kokoro"
voice_id: "am_adam"
text: "Exactly. SonicCraft treats audio composition the same way Hyperframes treated web-based video."
- id: sfx_impact
type: "sfx"
source: "assets/sfx/whoosh.wav"
volume: 0.8
start_at_ms: 0
这是 examples/tech-briefing/timeline.yaml。以下是
soniccraft render 对它的处理:
- 一次性验证所有内容。 未知键、拼写错误的枚举值、无效锚点、缺失的声音、缺失的文件和缺失的 API 密钥都会一并报告,每条报告均包含稳定代码、路径、行号和列号,以及修复提示。
- 合成并缓存。
cue_01和cue_03使用 ElevenLabs(带词级时间戳);cue_02使用本地 Kokoro-FastAPI 服务(local_kokoro是内置kokoro提供方的别名)。每个结果都按内容哈希缓存,因此之后渲染时只需为有更改的行付费。 - 平衡人声音量。 每段提示音都会裁掉开头和结尾的静音,并标准化至 -20 LUFS,因此云端声音和本地声音的音量相同。
- 以采样帧为单位排布时间线。
cue_01从 0 开始。cue_02在cue_01结束后 150 ms 开始。cue_03按顺序播放,在cue_01结束后 350 ms 开始,但该位置与cue_02冲突,因此默认的重叠策略(push)会自动将cue_03移至cue_02结束后 350 ms,保留其暂停时长作为间隔,并报告一条cue_pushed信息。最终形成自然的三轮对话,无需 Agent 计算时间。 - 放置音乐。 背景音乐是没有长度限制的循环片段,因此会持续播放至时间线结束,并淡入 1.2 s;时间线在最后一个词之后 2.5 s 结束(即背景音乐的
fade_out_ms),背景音乐会在这段尾音期间精确淡出。呼啸音效在 0 时触发。 - 压低背景音乐音量,每当任一人声说话时降低 18 dB。检测基于人声自身信号,并使用 80 ms 前瞻时间(默认与起音时间相同),因此第一个音节响起时背景音乐已被压低;随后用 350 ms 恢复音量,默认的 250 ms 保持时间会跨越 150 ms 的轮次间隔。
- 调整声像,将两个人声分别设为 -0.15 和 +0.15(恒定功率)。
- 对混音进行母带处理,将综合响度设为 -16 LUFS,真峰值上限设为 -1.0 dBTP(采用默认的
podcast预设),并迭代调整响度增益和 4× 过采样真峰值限制器,直至误差在 0.2 LU 以内(若没有任何一次处理达到目标,则保留最接近的一次,并由loudness_target_missed报告偏差;若目标无法达到,则无论目标为何,都会在平均限制量 6 dB 以内选取响度最大的母带)。 - 编码为原生 48 kHz、320 kbps 的 MP3,解码并测量交付文件(若编解码器导致峰值超过上限,则重新限幅),并根据放置后的词级时间戳生成
timeline.vtt和timeline.srt,并标注为narrator和guest。
在花费任何费用之前,soniccraft plan(别名 dry-run)会显示根据估算时长生成的相同布局,但不会调用 TTS API(JSON 内容经过删减,数字为估算值):
{ "valid": true, "duration_ms": 20616.9, "estimated": true,
"items": [
{ "id": "cue_01", "kind": "cue", "start_ms": 0.0, "end_ms": 4838.7, "duration_source": "estimate" },
{ "id": "cue_02", "kind": "cue", "start_ms": 4988.7, "end_ms": 10863.7, "duration_source": "estimate" },
{ "id": "cue_03", "kind": "cue", "start_ms": 11213.7, "end_ms": 18116.9, "duration_source": "estimate",
"pushed_from_ms": 5188.7 } ],
"synthesis": { "cues": 3, "cached": 0, "characters_to_synthesize": 276 } }
功能
- Timeline DSL v1.0:使用 YAML 或 JSON 编写,并提供已发布的 JSON Schema。严格校验:未知键会报错并提供“是否想输入”的提示;一次性报告所有问题,并附带稳定的代码、路径、行/列位置和可机械执行的修复方法。
- **无需计算即可安排时间:**按顺序排列提示和停顿、设置绝对起始时间,以及通过相对锚点(
after_cue、with_cue、before_cue,支持有符号偏移量)在提示、片段或整个轨道上定位。语音重叠会自动分开(或针对每条提示配置串音警告、拒绝或允许)。 - **八种 TTS 提供商:**ElevenLabs、任意兼容 OpenAI
/audio/speech的服务、Cartesia、Kokoro(Kokoro-FastAPI)、Piper、macOSsay、任意本地命令,以及确定性模拟语音。可在同一时间轴中自由混用。提供支持分层语音设置的说话人注册表。 - **低成本迭代:**基于内容寻址的 TTS 缓存;不会调用付费 API 的试运行(提供预估时长和各提供商的字符数);支持并发数上限和带退避的重试。
- **音乐和音效:**循环(无缝循环或带循环交叉淡化)、裁剪、三种曲线的淡入淡出、片段间交叉淡化,以及结束时自动添加淡出尾音的开放式背景音轨。
- **侧链闪避:**由实际语音信号(或时间轴)驱动,并支持起音、释放、保持和预读。
- **正确处理响度:**先对每个音源进行 BS.1770 标准化,再按预设进行母带标准化(播客 -16、流媒体 -14、EBU R128 广播 -23、ATSC A/85 -24 LUFS),并使用过采样真峰值限制器。对有损输出进行解码并测量最终交付音频,同时补偿编解码器真峰值和响度漂移。
- **原生 DSP 和编码器:**无需 ffmpeg 即可处理 wav、mp3 和 flac;安装了 ffmpeg 时可处理 ogg、opus 和 m4a。支持 16/24 位整数或 32 位浮点,以及固定种子的 TPDF 抖动。
- **根据渲染后的音频生成字幕:**WebVTT、SRT、带逐词时间戳的 JSON,以及兼容 HyperFrames 的转录文本;支持说话人标签和逐条提示的字幕覆盖。
- **附属文件:**每条轨道的分轨文件、确定性清单,以及包含波形、闪避包络和字幕的独立 HTML 预览。
- Agent 接口:
validate、plan、render、providers和voices提供机器可读的--json报告;兼容两个协议版本的 MCP 服务、Agent Skill,以及 Claude Code 插件。
快速开始
安装预构建二进制文件(已验证校验和;无需 Rust 或 C 工具链):
curl -fsSL https://raw.githubusercontent.com/user-github-me/soniccraft/main/install.sh | sh # macOS, Linux: ~/.local/bin
brew install user-github-me/soniccraft/soniccraft # Homebrew (macOS, Linux)
irm https://raw.githubusercontent.com/user-github-me/soniccraft/main/install.ps1 | iex # Windows
scoop bucket add soniccraft https://github.com/user-github-me/scoop-soniccraft; scoop install soniccraft
使用 Rust:cargo binstall soniccraft 会下载相同的发行版二进制文件,而 cargo install --locked soniccraft
会从 crates.io 构建(要求见下文)。
从源代码构建。 要求:Rust 1.89 或更高版本(rustup),以及用于捆绑的 LAME MP3
编码器的 C 工具链(cc 和 make:macOS 上使用 Xcode 命令行工具,Linux 上使用 build-essential;Windows 上使用
Visual Studio Build Tools,除非已安装 NASM,否则还需在环境中设置 AWS_LC_SYS_PREBUILT_NASM=1)。
ffmpeg 是可选项(用于 ogg/opus/m4a 输出和更多输入格式)。预构建二进制文件无需这些依赖:见
下文。
git clone https://github.com/user-github-me/soniccraft
cd soniccraft
cargo install --locked --path crates/soniccraft-cli # installs `soniccraft` and `soniccraft-mcp` into ~/.cargo/bin
soniccraft --version
--locked 会使用 Cargo.lock 中的依赖版本,也就是 CI 测试所用的版本。
预构建二进制文件。 每个 GitHub 发行版都提供适用于
Linux(x86_64-unknown-linux-gnu、aarch64-unknown-linux-gnu;glibc 2.35 或更高版本)、macOS
(aarch64-apple-darwin、x86_64-apple-darwin;macOS 11 或更高版本)和 Windows(x86_64-pc-windows-msvc)的压缩包。
soniccraft-v<version>-<target>.tar.gz(Windows 上为 .zip)包含 soniccraft、soniccraft-mcp、
许可证文本和 THIRD-PARTY-LICENSES.txt。-no-mp3 压缩包不含 LGPL MP3 编码器;此时 MP3
输出需要 ffmpeg。使用 sha256sum --check --ignore-missing SHA256SUMS 检查下载文件(macOS 上:
shasum -a 256 --check --ignore-missing SHA256SUMS)。这些二进制文件未经公证:在 macOS 上,浏览器
下载的文件会被隔离;使用 xattr -d com.apple.quarantine soniccraft soniccraft-mcp 清除隔离标记(curl 和
npm 启动器不会设置此属性)。
容器镜像。 每个发行版也会发布为
ghcr.io/user-github-me/soniccraft
(linux/amd64 和 linux/arm64,包含用于 ogg、opus 和 m4a 输出的 ffmpeg):
docker run --rm -v "$PWD":/work ghcr.io/user-github-me/soniccraft render timeline.yaml
docker run -i --rm -v "$PWD":/work ghcr.io/user-github-me/soniccraft mcp --base-dir /work # MCP on stdio
写入挂载目录的文件归 uid 1000 所有;添加 --user "$(id -u):$(id -g)",即可用自己的身份写入。
使用 -e ELEVENLABS_API_KEY 传入 API 密钥(绝不要放入时间线)。容器中无法使用 macOS 的 say:请使用
模拟语音、云服务提供商或本地服务。docker build -t soniccraft . 可从源代码构建相同的镜像。
无需任何 API 密钥即可渲染演示:
# macOS: Samantha and Daniel from macOS `say`, plus the built-in mock voice
soniccraft render examples/offline-demo/timeline.yaml --preview
# any OS: the same timeline with mock voices only
soniccraft render examples/offline-demo/timeline.mock.yaml
macOS 上的运行会生成 examples/offline-demo/offline-demo.wav,以及 .vtt、.srt、.words.json 和
.transcript.json 字幕文件、一个 .manifest.json,还有 offline-demo.preview.html(在浏览器中打开即可
查看波形、闪避包络和字幕)。Agent 遵循的完整流程:
soniccraft validate examples/offline-demo/timeline.mock.yaml # errors, warnings, fix hints
soniccraft plan examples/offline-demo/timeline.mock.yaml # dry run: layout, ducking, cost
soniccraft render examples/offline-demo/timeline.mock.yaml --json # one JSON report on stdout
使用 API 密钥和本地 Kokoro 服务,渲染 README 时间线:
export ELEVENLABS_API_KEY=... # never put keys in timelines
docker run -d -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest
soniccraft render examples/tech-briefing/timeline.yaml
从模板开始创建自己的项目(会写入时间线,并为其音频资源生成替代文件):
soniccraft init my-episode --template two-person-podcast
CLI
soniccraft validate <TIMELINE> [--json] [--check-credentials]
soniccraft plan <TIMELINE> [--json] (alias: dry-run)
soniccraft render <TIMELINE> [-o PATH] [--format F] [--subtitles] [--stems] [--manifest] [--preview]
[--no-cache] [--cache-dir DIR] [--jobs N] [--json]
soniccraft schema [-o FILE]
soniccraft init [DIR] [--template NAME] [--list] [--no-assets] [--force]
soniccraft providers [--json]
soniccraft voices <PROVIDER> [--json]
soniccraft cache <info|clear> [--cache-dir DIR] [TIMELINE]
soniccraft mcp [--base-dir DIR] [--allow-command]
| 命令 | 功能 |
|---|---|
validate | 解析并检查时间线及其环境(资源是否存在且可解码、凭据是否齐全且允许发送到对应主机、本地 TTS 服务是否有响应、macOS 语音和 piper 模型是否已安装、是否需要 ffmpeg、渲染是否符合内存预算、缓存状态)。--check-credentials 还会通过一次低成本的身份验证请求验证 API 密钥。 |
plan / dry-run | 验证后,使用缓存或估算的时长(模拟语音使用精确时长)布局时间线:条目时间、重叠调整、闪避区段、各提供方需要合成的角色,以及 ASCII 示意图。绝不会调用付费 API。 |
render | 完整的处理流程。-o 设置输出路径(仅当未设置 output.format 时,才根据扩展名选择格式:对于 format: wav 的时间线,使用 -o out.mp3 --format mp3);--format 可设为 wav、mp3、flac、ogg、opus、m4a,并会覆盖两者。--subtitles、--stems 和 --manifest 会启用对应导出(类似于 output.export_* 字段);--preview 会写入 <stem>.preview.html。--no-cache 会忽略缓存的 TTS 音频(新结果仍会缓存);--cache-dir 选择缓存目录;--jobs N 限制并发合成请求数(默认值为 4)。只有渲染成功后才会写入输出文件,且绝不会覆盖现有的非 SonicCraft 输出文件。 |
schema | 打印时间线 JSON Schema,或使用 -o 将其写入文件。 |
init | 根据模板写入 DIR/timeline.yaml(默认 DIR 为当前目录),并生成它引用的音频资源(以程序化方式生成无缝合成器循环和三个 SFX,结果确定且免版税)。模板(--list):offline-demo(macOS 默认:系统语音 + 模拟)、offline-demo-mock(其他平台默认:可在任何地方渲染)、tech-briefing、two-person-podcast、voiceover-with-music、dialogue-crosstalk。--no-assets 只写入时间线;未指定 --force 时绝不会覆盖现有文件。 |
providers | 列出内置提供方及其可用状态、凭据状态和默认语音。 |
voices | 列出某个提供方的语音(可能会调用其 API);提供方名称不区分大小写,且会忽略 - / _。 |
cache | info 显示 TTS 缓存位置、条目数和大小;clear 清空缓存。 |
mcp | 通过 stdio 运行 MCP 服务。--allow-command(或 SONICCRAFT_ALLOW_COMMAND=1)允许时间线运行 command 提供方;默认情况下会拒绝此类操作。 |
退出代码:0 表示成功,1 表示时间线无效(错误诊断),2 表示用法错误,3 表示运行时或渲染失败,130 表示中断。使用 --json 时,stdout 仅包含一份 JSON 文档(报告;命令失败时则为 {"message", "diagnostics", "hint"},包括用法错误);进度和日志输出到 stderr。由于环境或选项导致渲染停止时(例如缺少密钥、提供方无法运行、语音未安装或超出内存预算),也会以代码 1 退出,并以 error: render stopped: N errors 结尾。时间线(文件、FIFO、表示 stdin 的 -)最多读取 5 MB 文档,不会继续读取。运行 soniccraft <command> --help 查看各命令的所有选项。
MCP 服务
soniccraft mcp 通过 stdio 提供引擎服务(以换行符分隔的 JSON-RPC 2.0);soniccraft-mcp 是无需参数即可运行的同一服务。它支持两个版本的 MCP 协议:initialize 握手(2024-11-05 至 2025-11-25,Codex 和 Cursor 使用)以及无状态的 2026-07-28 版本(包含 server/discover,Claude Code 会先探测此接口)。
| 工具 | 输入 | 结果 |
|---|---|---|
soniccraft_validate_timeline | {yaml_content?, yaml_path?, base_dir?, check_credentials?, detail?}(内容和路径二选一;path 是 yaml_path 的别名) | ValidationReport |
soniccraft_dry_run | {yaml_content?, yaml_path?, base_dir?, detail?} | PlanReport(附文本形式的图表) |
soniccraft_render | {yaml_content?, yaml_path?, output_path?, format?, base_dir?, export_subtitles?, no_cache?, detail?} | RenderReport |
soniccraft_get_schema | {detail?} | DSL 快速参考(detail: "full" 时附 JSON Schema) |
soniccraft_list_providers | {} | 提供商、可用情况(已探测本地服务)、凭据状态、默认语音 |
soniccraft_list_voices | {provider} | 语音(可能会调用提供商 API) |
报告以 structuredContent 的形式返回(同时镜像为 JSON 文本,并附简短摘要)。较长的时间线默认会生成精简报告(detail: "auto"),使结果在 Agent 的上下文中保持易读;传入 detail: "full" 可获取所有条目。渲染结果会添加带有 file:// URI 的 resource_link 块,指向音频及旁侧文件(协议修订版本早于 2025-06-18 的会话会以文本形式获取这些文件);音频绝不会以内嵌 base64 的形式返回。format 会覆盖时间线的 output.format(传入该参数时,output_path 的扩展名应对应另一种格式)。对于 mp3/ogg/opus/m4a,报告中的响度描述的是最终交付文件(母带的响度见 loudness.pre_encode)。无效时间线仍会成功完成 validate/dry-run 调用(valid: false);渲染失败或参数无效时会返回 isError: true,并说明需要修正的内容,方便 Agent 修正后重试。相对路径会依次以 base_dir、soniccraft mcp --base-dir、CLAUDE_PROJECT_DIR 或服务的工作目录为基准解析。较长的渲染会报告 notifications/progress 并响应取消请求;同时最多运行两个(SONICCRAFT_MCP_MAX_RENDERS)。每次渲染最多可使用 SONICCRAFT_MAX_RENDER_GB 内存(默认 8 GB),因此服务的峰值内存可能达到其乘积(默认 16 GB);小型机器请调低其中一个值。只有在启动服务时使用 soniccraft mcp --allow-command,时间线才会运行 command 提供商(参见安全性)。工具参数和报告结构:
skills/soniccraft/reference/mcp-tools.md。
Claude Code
claude mcp add soniccraft -- soniccraft mcp # local scope (default): this project, private to you
claude mcp add --scope user soniccraft -- soniccraft mcp # all your projects
claude mcp add --scope project soniccraft -- soniccraft mcp # writes .mcp.json to commit with the project
claude mcp add soniccraft -- soniccraft mcp --allow-command # only if your timelines use `command` providers (they run local programs)
也可以在项目的 .mcp.json 中配置(timeout 是每次调用的毫秒数上限)。stdio 服务会继承 Claude Code 运行时的环境,因此导出的 API 密钥无需 env 块即可传递给服务:
{
"mcpServers": {
"soniccraft": {
"type": "stdio",
"command": "soniccraft",
"args": ["mcp"],
"timeout": 900000
}
}
}
请勿添加 "env": {"ELEVENLABS_API_KEY": "${ELEVENLABS_API_KEY}"}:如果变量未设置,客户端会传递字面文本 ${ELEVENLABS_API_KEY}。SonicCraft 会将这类占位符视为缺少密钥,并明确提示(missing_credentials);如果需要添加 env 条目,请写成 "${ELEVENLABS_API_KEY:-}"。
无需安装 Rust,可通过 npm 使用(Node.js 20 或更高版本):soniccraft-mcp 包会在 PATH 中找到 soniccraft 时使用它;否则会在首次使用时下载适用于当前平台的预构建版本,并使用包中固定的 SHA-256 校验和进行验证。npm 上的每个版本都是发布包中的 soniccraft-mcp-X.Y.Z.tgz 资源,通过 GitHub Actions 并附带来源证明发布。
claude mcp add soniccraft -- npx -y soniccraft-mcp
{ "mcpServers": { "soniccraft": { "command": "npx", "args": ["-y", "soniccraft-mcp"] } } }
包名后的参数会传递给 soniccraft mcp(例如 --base-dir);
packages/soniccraft-mcp/README.md 介绍了平台、环境变量、代理和离线安装。下文的 Cursor 和 Codex 配置也使用相同的 npx 形式(命令为 npx,参数为 ["-y", "soniccraft-mcp"])。
Cursor:~/.cursor/mcp.json(全局)或 .cursor/mcp.json(项目):
{
"mcpServers": {
"soniccraft": {
"type": "stdio",
"command": "soniccraft",
"args": ["mcp"],
"env": { "ELEVENLABS_API_KEY": "${env:ELEVENLABS_API_KEY}" }
}
}
}
在项目级文件中,可以将 "CLAUDE_PROJECT_DIR": "${workspaceFolder}" 添加到 env,让工具调用中的相对路径以工作区为基准解析。如果某个密钥变量未设置,且客户端将占位文本原样传递,SonicCraft 会报告密钥缺失,而不会发送占位文本。
Codex
codex mcp add soniccraft -- soniccraft mcp
然后在 ~/.codex/config.toml 中提高工具超时时间(Codex 默认值为 60 s;渲染可能需要更长时间),转发你使用的 API 密钥,并决定如何批准渲染工具:
[mcp_servers.soniccraft]
command = "soniccraft"
args = ["mcp"]
env_vars = ["ELEVENLABS_API_KEY", "OPENAI_API_KEY", "CARTESIA_API_KEY"]
startup_timeout_sec = 20
tool_timeout_sec = 900
default_tools_approval_mode = "approve" # needed for non-interactive `codex exec`, see below
soniccraft_render 会写入文件,因此 Codex 会在运行前询问。交互式会话会提示用户批准;在非交互式 codex exec 中(批准策略为 never),调用会失败并显示 "MCP tool call requires approval",除非服务条目批准了它:为所有 SonicCraft 工具设置 default_tools_approval_mode = "approve",或者仅为渲染工具设置:
[mcp_servers.soniccraft.tools.soniccraft_render]
approval_mode = "approve"
单次运行时:codex exec -c 'mcp_servers.soniccraft.default_tools_approval_mode="approve"' ...。
Agent 技能
skills/soniccraft/ 是一个 Agent Skills 软件包:
SKILL.md(工作流、DSL 基础知识、时长启发式、混音实践、诊断修复表),以及按需参考资料(完整的 DSL 参考、提供商、混音指南、所有诊断代码、MCP 工具)和五个模板。它围绕 CLI 编写,因此适用于任何 Agent,并将 MCP 工具作为替代方案提及。
npx skills add user-github-me/soniccraft # pick agents interactively
npx skills add user-github-me/soniccraft --skill soniccraft -a claude-code -a codex -a cursor -y # project scope
npx skills add user-github-me/soniccraft --skill soniccraft -g -a claude-code -y # global
或者手动复制目录:cp -R skills/soniccraft ~/.claude/skills/(Claude Code,用户级),.claude/skills/soniccraft(Claude Code,项目级),~/.agents/skills/soniccraft 或 .agents/skills/soniccraft(Codex、Cursor 以及其他会读取 .agents/skills 的 Agent)。
Claude Code 插件(一步安装技能和 MCP 服务;需要将 soniccraft 加入 PATH):
claude plugin marketplace add user-github-me/soniccraft
claude plugin install soniccraft@soniccraft
如果插件的 MCP 服务显示为失败,通常是因为 soniccraft 二进制文件不在 PATH 中:请安装它(参见快速入门),然后重启 Claude Code。技能的设置部分会向 Agent 提供相同的说明。
对于 Codex,skills/soniccraft/agents/openai.yaml 声明了 MCP 依赖项,并以 soniccraft-mcp 启动。
提供商
| 提供商 | provider: | 凭据 / 设置 | 默认语音 | 词语时间戳 |
|---|---|---|---|---|
| ElevenLabs | elevenlabs | ELEVENLABS_API_KEY | 无(需要 voice_id) | 是 |
| OpenAI 兼容 | openai | OPENAI_API_KEY;其他服务使用 base_url | alloy | 估算 |
| Cartesia | cartesia | CARTESIA_API_KEY | 无(需要 voice_id) | 是 |
| Kokoro(Kokoro-FastAPI) | kokoro | 本地服务:KOKORO_BASE_URL(默认 http://localhost:8880),可选的 KOKORO_API_KEY | af_heart | 是 |
| Piper | piper | pip install piper-tts;语音模型(voices_dir、PIPER_VOICES_DIR 或时间线旁的目录) | 无(需要 voice_id) | 估算 |
| macOS 语音 | macos_say | macOS | Samantha | 估算 |
| 自定义命令 | command | 你的 argv 模板 | 无(需要 voice_id) | 估算 |
| 模拟 | mock | 无需设置(确定性合成语音) | mock | 精确 |
- ElevenLabs 默认请求原始
pcm_24000音频(如果你配置的格式在当前套餐中不可用,则回退到该格式);eleven_v4仅接受stability和similarity_boost。 openai是通用的 OpenAI 兼容/audio/speech客户端。OpenAI 自有的 TTS 模型将于 2027-01-06 退役;请将base_url指向 Kokoro-FastAPI、Speaches、LocalAI 或其他兼容服务。- Cartesia 使用 API 版本
2026-08-14,默认使用sonic-3.6。 - Kokoro:
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest;词级时间戳来自其带字幕的语音端点。soniccraft providers和validate会通过 300 ms TCP 连接探测本地服务(Kokoro-FastAPI,以及此设备或专用网络上的 OpenAI 兼容服务);未响应的服务不可用(no Kokoro-FastAPI server answered at http://localhost:8880),而 validate 会报告provider_unavailable。 - Piper 由 OHF-Voice/piper1-gpl 维护:先运行
pip install piper-tts,再将语音下载到项目中:python3 -m piper.download_voices en_US-lessac-medium --data-dir voices,并在提供方中设置voices_dir: voices(或将语音下载到时间线文件旁边)。voice_id: en_US-lessac-medium会按以下顺序在voices_dir、$PIPER_VOICES_DIR、时间线目录和~/.local/share/piper/voices中查找;soniccraft voices piper会列出找到的内容,或列出已搜索的目录和下载命令;如果模型缺失,validate 会报告unknown_voice。 - macOS
say遇到未知名称时会静默回退到默认语音,因此 SonicCraft 会先使用say -v '?'检查语音名称(validate 会报告unknown_voice,并给出最接近的已安装语音名称)。 - API 密钥只会发送到提供方自己的 API 主机、此设备上的服务(仅发送提供方自己的密钥变量,例如
OPENAI_API_KEY),或SONICCRAFT_ALLOWED_HOSTS中列出的主机;如果密钥将被发送到其他位置,则会在发出任何请求前拒绝(provider_unavailable)。请参阅安全性。
各提供方的设置、模型、语音、配置和限制: skills/soniccraft/reference/providers.md。
| 环境变量 | 用途 |
|---|---|
ELEVENLABS_API_KEY、OPENAI_API_KEY、CARTESIA_API_KEY | 提供方 API 密钥(可使用 api_key_env 按实例重命名)。 |
KOKORO_BASE_URL、KOKORO_API_KEY | Kokoro-FastAPI 地址和可选密钥。 |
PIPER_VOICES_DIR | 搜索 <voice_id>.onnx 的目录(在提供方的 voices_dir 之后搜索)。 |
SONICCRAFT_ALLOWED_HOSTS | 除各提供方自己的 API 主机和此设备上的服务(这些服务只会收到提供方自己的密钥变量)外,可接收 API 密钥的其他主机(以逗号分隔,支持 *.example.com 模式)。 |
SONICCRAFT_CACHE_DIR | TTS 缓存位置(可由 --cache-dir 覆盖)。 |
SONICCRAFT_MAX_RENDER_GB | 单次渲染的内存预算,单位为 GB(默认值为 8);需要更多内存的时间线会在发出任何 TTS 请求前以 timeline_too_long 失败。 |
CLAUDE_PROJECT_DIR | MCP 服务:当调用未指定 base_dir 时,用作相对路径的基目录。 |
SONICCRAFT_ALLOW_COMMAND | MCP 服务:设为 1 后,时间线可以运行本地程序(command 提供方、piper command);默认关闭,与 soniccraft mcp --allow-command 相同。 |
SONICCRAFT_MCP_MAX_RENDERS | MCP 服务:可同时运行的渲染数量(默认值为 2);后续渲染会等待。 |
字幕与 HyperFrames
output.export_subtitles 接受 true(= vtt + srt)或由 vtt、srt、json 和 transcript 组成的列表。
json(<stem>.words.json)保存字幕和每个单词的时间信息;transcript
(<stem>.transcript.json)是一个以秒为单位的单词数组,格式与 HyperFrames 的 transcribe 命令所需格式一致。要为 HyperFrames 视频添加 SonicCraft 配音:
soniccraft render voiceover.yaml # with output.export_subtitles: [vtt, transcript]
npx hyperframes transcribe voiceover.transcript.json --dir my-video
并在合成中从头开始播放处理完成的音频,例如
<audio id="voiceover" src="assets/voiceover.wav" data-start="0" data-duration="21.04"></audio>。
确定性与缓存
- 确定性输出。 相同的时间线、TTS 缓存和二进制文件会生成逐字节相同的音频、字幕和清单。渲染产物中不会包含墙上时钟时间戳、随机种子、主机名或绝对路径;抖动和模拟语音使用固定种子;所有几何数据均以整数采样帧表示。阶段耗时和缓存统计信息只显示在实时报告中,不会写入清单,因此使用热缓存进行渲染时,写出的清单与全新渲染时相同。
- 内容寻址的 TTS 缓存。 每个提示音的键都是对规范 JSON 计算的 blake3 哈希,其中包含所有影响音频的内容(提供方类型、API 版本、非默认基础 URL、模型、语音、语言、文本、设置、输出格式;对于 command/piper,还包括模板、程序及其内容的哈希、参数所指向的文件和 piper 模型)。缓存条目为
<key>.wav(32 位浮点、提供方原生采样率、未裁剪)和<key>.json(元数据和单词时间信息),并以原子方式写入。更改一行只会重新合成一个提示音;调整时间、重新混音或重新母带处理都无需花费。无法写入缓存时会发出cache_write_failed警告;渲染仍会成功。 - 位置:
--cache-dir>SONICCRAFT_CACHE_DIR><timeline dir>/.soniccraft/cache。soniccraft cache info和soniccraft cache clear可管理缓存;render --no-cache会重新合成,但仍会刷新缓存。 - 免费试运行。
plan会使用可用的缓存时长,在进程内渲染模拟语音(精确),并根据每个提供方的语速(字符数/秒)估算其余时长;它绝不会调用提供方。
安全
时间线属于数据,通常由 Agent 根据其在某处找到的文本编写,因此 SonicCraft 会将其视为不可信内容:
- 时间线中绝不存放密钥。 时间线中的 API 密钥、令牌和密码(名为
api_key/token/secret/password的键、sk-...值、URL 中的密码、提供商command中的密钥)都会触发secret_in_timeline错误,诊断信息绝不会重复显示这些内容(CLI 代码片段会显示<redacted>)。密钥只能来自环境变量(api_key_env)。 - 密钥只能发送到该去的地方: 各提供商自己的 API 主机、本机上的服务(仅限提供商自己的密钥变量:指向本地服务的
openai实例使用OPENAI_API_KEY,Kokoro 使用KOKORO_API_KEY),或你在SONICCRAFT_ALLOWED_HOSTS中列出的主机(在 soniccraft 或 MCP 服务的环境中设置,绝不能写入时间线)。除非主机已列入允许列表,否则时间线不能将自己选择的变量(api_key_env: GITHUB_TOKEN)发送到本地服务,也不能将任何密钥发送到本地网络中的其他设备。若要将密钥用于网络上其他位置或远程的 OpenAI 兼容服务、远程 Kokoro 或区域端点,可设置例如SONICCRAFT_ALLOWED_HOSTS=tts.example.com。其他任何情况都会在发出请求前被拒绝。不会跟随重定向,服务器回显的密钥也会从消息中移除。 - 本地程序:
command提供商(以及使用自身command的 piper)会运行程序。通过 MCP 使用时,除非以soniccraft mcp --allow-command(或SONICCRAFT_ALLOW_COMMAND=1)启动,否则服务会拒绝运行这些程序。程序永远不会获得提供商 API 密钥,在各自的进程组中运行(超时或取消时会整体终止),并通过文件或标准输入获取提示文本:以-开头的参数会被拒绝。 - 文件: 输出会先写入临时文件,只有整个渲染成功后才会放置到目标位置;渲染失败或取消时,先前的输出保持不变。只有同类型的输出才能替换现有文件(例如,
-o notes.txt指向文本文件时会被拒绝)。通过 MCP 使用时,时间线自身的output.path必须位于基础目录内(显式的output_path参数可指向任意位置)。 - 读取: 时间线最多为 5 MB;
/dev/zero、FIFO 或无限标准输入会立即失败。
资源
渲染时,会将母带混音保存在内存中:各音轨按窗口混音,直接写入一份完整时长的母带;分轨流式写入文件,母带处理则在原处完成。实测峰值(立体声,48 kHz):音乐为主时,WAV、MP3、ogg、opus 和 m4a 每分钟输出约占 23 MB(10 分钟的铺底音乐:245 MB);语音贯穿全程时,每分钟约占 40 MB(16 分钟的旁白:615 MB);24 位 FLAC 每分钟约占 85 MB,因为其编码器会保留整个数据流(10 分钟:870 MB)。SONICCRAFT_MAX_RENDER_GB(默认值为
8)会限制渲染资源用量:超过限制的渲染会在发出任何 TTS 请求前因 timeline_too_long 而失败,validate/plan 也会提前发出警告。时间线最长为 24 h。
架构
timeline.yaml / .json
|
v
+----------------+ diagnostics: code, path, line:col, hint
| parse + lower |-------------------------------------------------+
| (core) | |
+-------+--------+ |
| IR (Program): resolved voices, defaults, anchors |
v |
+----------------+ cached / estimated durations +-------------+ |
| synthesis |------------------------------->| layout | |
| (tts + cache) | exact durations (render) | (frames) | |
+-------+--------+ +------+------+ |
| audio + word timings | placements|
v v v
+------------------------------------------------------------+ reports:
| DSP (dsp): decode -> resample -> trim -> normalize -> clips | validate,
| -> pan -> stems -> ducking -> master (R128 + true peak) | plan,
+-------+----------------------------------------------------+ render
|
v
encode (wav/mp3/flac native; ogg/opus/m4a via ffmpeg) + captions (vtt/srt/json/transcript)
+ stems + manifest + preview.html
| Crate / 目录 | 职责 |
|---|---|
soniccraft-core | DSL 原始 AST(serde + schemars)、带源代码范围的 YAML/JSON 解析、诊断、验证及降低为 IR、JSON Schema 生成、静态提供商元数据。纯函数式:除环境变量外不进行 I/O。 |
soniccraft-layout | 以采样帧为单位的时间线几何:调度、语音重叠策略、片段长度、内容结尾和尾部;ASCII 计划示意图。纯函数式。 |
soniccraft-captions | 词语对齐(提供商时间或估算值)、字幕分段、WebVTT/SRT/JSON/转录文本写入器。 |
soniccraft-dsp | AudioBuffer、解码(symphonia;ffmpeg 回退)、重采样(rubato)、分析、片段渲染、声像、闪避、响度(ebur128)、真峰值限制器、母带处理循环、编码器(WAV、LAME MP3、FLAC;ogg/opus/m4a 使用 ffmpeg)。 |
soniccraft-tts | 提供商 trait 和八个内置提供商、内容寻址缓存、时长估算器、重试与并发、凭证检查、语音列表。 |
soniccraft-engine | 编排:validate()、plan()(试运行)、render();环境检查;所有报告类型。 |
soniccraft-mcp | 将引擎作为工具公开的 MCP stdio 服务。 |
soniccraft(crates/soniccraft-cli) | soniccraft 二进制文件(以及 soniccraft-mcp 启动器)。支持人类可读输出和 --json 输出。 |
packages/soniccraft-web-preview | 零依赖 WebAudio 可视化工具;引擎内嵌了一份 vendored 副本(crates/soniccraft-engine/assets/preview.html),供 render --preview 使用。 |
packages/soniccraft-mcp | npm 启动器(npx -y soniccraft-mcp):查找或下载发行版二进制文件,并运行 soniccraft mcp。 |
skills/soniccraft | Agent Skill:SKILL.md、参考资料、模板。 |
examples | 可运行的时间线示例,使用免版税的程序生成素材。 |
依赖关系是单向的:layout → core;tts → {core, dsp};engine → {core, layout、
captions、dsp、tts};mcp → engine;cli → {engine、mcp}。完整规范见
docs/DESIGN.md;贡献者可在
docs/architecture.md 中了解整个处理流程。
路线图
- 阶段 1:DSL 和编译器(已在 v0.1 中实现)
- Timeline DSL v1.0(YAML/JSON)、JSON Schema、严格验证并提供「你是不是想说」提示
- 降级为解析后的 IR:语音、提供方、默认值、锚点、依赖项检查
- 精确到采样点的布局,支持语音重叠策略、试运行计划和 ASCII 图示
- 阶段 2:合成(已在 v0.1 中实现)
- 八种提供方:ElevenLabs、兼容 OpenAI 的服务、Cartesia、Kokoro、Piper、macOS say、command、mock
- 内容寻址缓存、时长估算、并发限制、重试、凭据检查
- 阶段 3:原生 DSP 和母带处理(已在 v0.1 中实现)
- 解码、重采样、静音裁剪、源音频归一化、循环、淡入淡出、交叉淡化、声像
- 侧链和提示驱动的闪避、EBU R128 母带处理循环、过采样真峰值限制器
- WAV/MP3/FLAC 编码器;通过 ffmpeg 支持 ogg/opus/m4a
- 阶段 4:Agent 接入方式和输出(已在 v0.1 中实现)
- WebVTT、SRT、JSON 单词时间戳和 HyperFrames 转录文本
- 支持
--json的命令行、MCP 服务(两代协议)、Agent Skill、Claude Code 插件 - 分轨、清单、网页预览、包含生成资源的示例
- 阶段 5:分发(v0.1)
- 发布工作流:为 macOS、Linux 和 Windows 提供预构建二进制文件(包含或不包含 LGPL MP3
编码器)、
SHA256SUMS、第三方许可证声明以及soniccraft-mcpnpm 启动器 - 包管理器:单行安装程序(
install.sh、install.ps1)、Homebrew tap、Scoop bucket 和容器镜像 - 在项目的 GitHub 所有者名下列出:官方 MCP Registry
(
io.github.user-github-me/soniccraft)、此仓库中的 Claude Code 插件市场,以及用于npx skills add的 Agent Skill - crates.io:
cargo install soniccraft和cargo binstall soniccraft - npm:
npx -y soniccraft-mcp(MCP 服务会下载并验证发布的二进制文件) - 精选目录:Anthropic 插件目录和 Cursor Marketplace
- 发布工作流:为 macOS、Linux 和 Windows 提供预构建二进制文件(包含或不包含 LGPL MP3
编码器)、
贡献
请参阅 CONTRIBUTING.md。每个组件的行为都在 docs/DESIGN.md 中有说明;请同时修改规范和代码。
许可证
SonicCraft 根据你的选择,采用 Apache License, Version 2.0 或 MIT license 许可。除非你明确另行声明,否则根据 Apache-2.0 许可证的定义,任何有意提交以纳入本项目的贡献均按上述双重许可授权,不附加任何条款或条件。
原生 MP3 编码使用 LAME 3.100(LGPL-2.0-or-later),通过 mp3lame-sys 和
mp3lame-encoder crate(LGPL-3.0)静态链接,并由默认启用的 cargo 功能 mp3 控制。使用
--no-default-features 构建即可将其排除(例如:
cargo install --locked --path crates/soniccraft-cli --no-default-features);此时,若有 ffmpeg,MP3 输出会通过 ffmpeg 处理(否则会返回 format_requires_ffmpeg)。-no-mp3 发布归档以这种方式构建,不包含任何 LGPL 代码。其他发布归档会在 licenses/ 中附带许可证文本,licenses/README.md 说明了如何使用修改后的 LAME 重新构建 soniccraft。音频解码使用 symphonia,dirs 使用 option-ext,两者均采用 MPL-2.0(文件级 copyleft;未经修改地使用,源码可在 crates.io 上获取)。其他所有依赖均采用宽松许可证(MIT、Apache-2.0、BSD-3-Clause、ISC、Zlib、Unicode-3.0)。每个发布归档都会在 THIRD-PARTY-LICENSES.txt 中列出其中编译的所有 crate 及其随附的许可证文本,CI 则通过 cargo-deny
(deny.toml) 强制执行此政策。
examples/*/assets/ 中的示例音频由
scripts/generate-example-assets.sh 从头合成,并采用相同的许可证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。