ElevenLabs TTS 转 MP3
通过 ElevenLabs 文本转语音 API 将脚本文本转换为 MP3 语音。
默认设置
- 语音 ID:
K7ewtjKRNtwwt3lKQ6M0(Hoang 的品牌语音 — 锁定) — 可通过ELEVENLABS_VOICE_ID环境变量或--voice_id覆盖 - 模型:
eleven_v3(最具表现力,支持 [excited]、[whisper]、[laugh] 等音频标签;最适合讲故事内容) — 可通过--model_id覆盖。备选:eleven_multilingual_v2(高质量,速度较慢)、eleven_turbo_v2_5(快速,略显平淡)、eleven_flash_v2_5(最快) - 输出格式:
mp3_44100_128(44.1 kHz / 128 kbps) — 可通过--output_format覆盖 - 语音设置:
stability=0.5、similarity_boost=0.75、style=0、use_speaker_boost=true(ElevenLabs 默认值) - 发音映射: 自动从
assets/vn-pronunciation-map.json加载 — 使用--no-pronounce-map禁用,或使用--pronounce-map path.json指向其他文件 - 字符限制: 每次请求最多 5000 字符 (ElevenLabs 硬性限制)。文本超过 5000 字符时,脚本会报错退出,要求用户手动拆分。
快速使用
从文件输入
uv run .claude/skills/mkt-elevenlabs-tts-to-mp3/scripts/text_to_mp3.py \
--file path/to/script.txt \
-o workspace/content/YYYY-MM-DD/voiceover.mp3
从内联文本输入
uv run .claude/skills/mkt-elevenlabs-tts-to-mp3/scripts/text_to_mp3.py \
"Xin chào các bạn, hôm nay mình chia sẻ về AI Agent" \
-o workspace/assets/elevenlabs/sample.mp3
自定义语音 / 模型
uv run .claude/skills/mkt-elevenlabs-tts-to-mp3/scripts/text_to_mp3.py \
--file script.txt \
--voice_id K7ewtjKRNtwwt3lKQ6M0 \
--model_id eleven_turbo_v2_5 \
-o output.mp3
调整语音表现力
uv run .claude/skills/mkt-elevenlabs-tts-to-mp3/scripts/text_to_mp3.py \
--file script.txt \
--stability 0.4 \
--similarity_boost 0.8 \
--style 0.2 \
-o output.mp3
语音设置 — 何时调整
| 设置 | 范围 | 效果 |
|---|---|---|
stability | 0.0–1.0 | 越高 = 越单调/可预测;越低 = 越有情感/多变。旁白推荐 0.5。对于休闲开场可降至 0.3–0.4;正式讲解可提升至 0.7+。 |
similarity_boost | 0.0–1.0 | 克隆参考语音的准确度。默认 0.75。如果语音听上去与原始语音“不符”,可提升至 0.9。 |
style | 0.0–1.0 | 风格夸张程度。默认 0。大于 0 时会增加延迟。适合有表现力的内容 (0.1–0.3)。 |
use_speaker_boost | bool | 增强说话人相似度。为保持品牌语音一致性,建议保持 true。 |
发音映射 (英文单词修复)
ElevenLabs 的多语言模型会尝试以主要语言读取整个文本。在越南语脚本中,英文单词如 doc、chat、git 会被读作越南语音节,听起来不正确。为解决此问题而无需手动编辑每个脚本,该技能会自动从 assets/vn-pronunciation-map.json 加载一个不区分大小写的整词替换映射,并在将文本发送到 API 之前应用。
默认映射:
{
"doc": "đóc",
"chat": "chát",
"git": "gít"
}
工作原理:每个键以不区分大小写方式通过 \b...\b 边界匹配,然后替换为越南语音译值。模型看到的是 "đóc" 而不是 "doc",因此会读作接近 /dɒk/ 的发音。这仅影响音频 — 您的源脚本保持不变。
维护字典 — 先听,再加:
- 对包含候选单词的短测试脚本运行该技能
- 如果模型已正确读出该单词,请不要添加 (过度拟合会破坏效果)
- 注意冲突:添加
"code"会重写Claude Code中的Code(品牌名) → 永远不要这样做 - 对于需要保护的品牌名,完全不要包含
覆盖 / 禁用:
# 为特定项目使用自定义映射
uv run scripts/text_to_mp3.py --file s.txt --pronounce-map workspace/.../map.json -o out.mp3
# 完全跳过替换
uv run scripts/text_to_mp3.py --file s.txt --no-pronounce-map -o out.mp3
脚本会将每个应用的替换打印到 stderr (例如 'doc' -> 'đóc' (4x)),以便您验证更改。
工作流程
- 从项目
.env加载ELEVENLABS_API_KEY - 从
--file或位置参数读取文本,去除空白 - 应用发音映射 (除非使用
--no-pronounce-map) — 不区分大小写的整词替换 - 验证
len(text) <= 5000 POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}?output_format=mp3_44100_128- 请求头:
xi-api-key: <key>、Content-Type: application/json、Accept: audio/mpeg - 请求体:
{ "text": "...", "model_id": "eleven_v3", "voice_settings": { "stability": 0.5, "similarity_boost": 0.75, "style": 0, "use_speaker_boost": true } }
- 请求头:
- 将音频字节直接流式传输到输出 MP3 (无需转码 — 服务器直接返回 MP3)
- 打印
output_path、size_mb、char_count、voice_id、model_id
输出约定
- 简短/测试:
workspace/assets/elevenlabs/<name>.mp3 - 视频制作:
workspace/content/YYYY-MM-DD/video-short/<project>/voiceover.mp3
要求
- 项目
.env文件中包含ELEVENLABS_API_KEY(头部认证:xi-api-key) - 可选:在
.env中设置ELEVENLABS_VOICE_ID以锁定不同的默认语音 - Python 依赖通过 PEP 723 内联元数据管理 (由
uv run自动安装):requests、python-dotenv - 不需要
ffmpeg— ElevenLabs 直接返回 MP3
为什么不进行分块
ElevenLabs 将请求限制为 5000 字符。该技能在超过此限制时会快速失败,而不是自动拆分,因为:
- 单个语音应为连贯的块 — 在脚本中间拆分会导致连接边界处的韵律跳跃
- 用户的内容 (开场、短脚本、视频片段) 通常远小于 5000 字符
- 如果用户确实需要更长的音频,他们应按语义拆分脚本 (段落分隔),然后为每个块调用此技能,再使用 ffmpeg 在自己的流程中连接
API 参考
- 端点:
POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id} - 认证:请求头
xi-api-key: <api_key> - 模型目录:https://elevenlabs.io/docs/models
- 语音目录 (浏览/获取语音 ID):https://elevenlabs.io/app/voice-library
- API 文档:https://elevenlabs.io/docs/api-reference/text-to-speech/convert
- 速率限制:取决于订阅等级 — 参见 https://elevenlabs.io/pricing
- 输出格式:
mp3_44100_128(默认)、mp3_44100_192(更高品质,仅付费版)、pcm_44100、ulaw_8000(电话)