关于 tts
tts 是 ListenHub 的文本转语音技能,支持单人快速朗读和多角色脚本音频。它提供快速与脚本模式,并可通过配置管理音色分配和输出偏好。
主要功能
- 01单人快速语音生成
- 02多角色脚本音频生成
- 03按角色分配音色
- 04配置输出方式和语言偏好
- 05可选语速调整
适用场景
- 01朗读一段简短文本
- 02将标注说话人的脚本制作成对话音频
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ marswaveai/ skills --skill tts安装后在 Claude Code 中输入/tts确认已加载。
附带文件references/tts-guide.md
详细介绍
适用场景
- 用户想将文本转换为语音
- 用户要求“朗读”“TTS”“文本转语音”或“语音旁白”
- 用户说“朗读”“配音”或“语音合成”
- 用户想生成多角色脚本音频或对话
不适用场景
- 用户想要带有主题探索的播客风格讨论(使用
/podcast) - 用户想制作带有视觉内容的讲解视频(使用
/explainer) - 用户想生成图片(使用
/image-gen)
用途
将文本转换为自然流畅的语音。分为两种模式:
- 快速模式(
--mode direct):单一语音,低延迟、同步。适用于日常聊天、朗读短文和即时音频。 - 脚本模式(
--mode smart):多角色,可为各片段分别指定语音。适用于对话、有声书和脚本内容。
硬性约束
- 始终按照
shared/cli-authentication.md检查 CLI 身份验证 - 按照
shared/cli-patterns.md执行 CLI 命令、处理错误并遵循交互模式 - 绝不在 CLI 调用中硬编码发言者 ID——仅将
shared/speaker-selection.md中的内置默认值用作备用;用户想更换语音时,应从 speakers CLI 获取 - 进行任何交互前,始终按照
shared/config-pattern.md读取配置 - 始终按照
shared/speaker-selection.md选择发言者(文本表格 + 自由文本输入) - 绝不将文件保存到
~/Downloads/或/tmp/作为主要输出——将生成文件保存到当前工作目录,并使用清晰、与主题相关的文件名(参见shared/config-pattern.md§ Artifact Naming)
模式判定
在提问前,根据用户输入自动判定模式:
| 信号 | 模式 |
|---|---|
| “多角色”“脚本”“对话”“script”“dialogue”“multi-speaker” | 脚本 |
| 提及多个角色的姓名或身份 | 脚本 |
| 输入包含结构化片段(A: …、B: …) | 脚本 |
| 单段文本,没有角色标记 | 快速 |
| “读一下”“read this”“TTS”“朗读”并附有纯文本 | 快速 |
| 不明确 | 快速(默认) |
交互流程
步骤 -1:CLI 身份验证检查
按照 shared/cli-authentication.md 操作。如果未安装 CLI 或用户尚未登录,则自动安装并自动登录——绝不要求用户手动运行命令。
然后按照 shared/cli-authentication.md § Auth Mode Detection 确定 AUTH_MODE 并设置:
if [ "$AUTH_MODE" = "openapi" ]; then
CMD_PREFIX="listenhub openapi tts"
else
CMD_PREFIX="listenhub tts"
fi
后续所有 CLI 调用均使用 $CMD_PREFIX,而不是硬编码的 listenhub tts。
步骤 0:配置设置
按照 shared/config-pattern.md 步骤 0(零提问启动)操作。
如果文件不存在——静默创建默认配置并继续:
mkdir -p ".listenhub/tts"
echo '{"outputMode":"inline","language":null,"defaultSpeakers":{}}' > ".listenhub/tts/config.json"
CONFIG_PATH=".listenhub/tts/config.json"
CONFIG=$(cat "$CONFIG_PATH")
不得询问任何设置问题。 直接进入交互流程。
如果文件存在——静默读取配置并继续:
CONFIG_PATH=".listenhub/tts/config.json"
[ ! -f "$CONFIG_PATH" ] && CONFIG_PATH="$HOME/.listenhub/tts/config.json"
CONFIG=$(cat "$CONFIG_PATH")
设置流程(仅在用户主动要求重新配置时运行)
仅在用户明确要求重新配置时运行。显示当前设置:
当前配置 (tts):
输出方式:{inline / download / both}
语言偏好:{zh / en / 未设置}
默认主播:{speakerName / 使用内置默认}
然后询问:
-
outputMode:按照
shared/output-mode.md§ Setup Flow Question 操作。 -
Language(可选):“默认语言?”
- “中文 (zh)”
- “English (en)”
- “每次手动选择” → 保持
null
收集完答案后,立即保存:
NEW_CONFIG=$(echo "$CONFIG" | jq --arg m "$OUTPUT_MODE" '. + {"outputMode": $m}')
# Save language if user chose one (not "每次手动选择")
if [ "$LANGUAGE" != "null" ]; then
NEW_CONFIG=$(echo "$NEW_CONFIG" | jq --arg lang "$LANGUAGE" '. + {"language": $lang}')
fi
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
生成速度
默认:1.0 倍速(原速)。绝不询问速度。
只有当用户明确要求加快或放慢朗读速度时,才传入 --speed —
“慢一点”、“快一点”、“1.25 倍速”、“read it faster”。否则省略该标记。
- 范围:
0.5到2.0之间的任意值,最多两位小数;这是连续范围,不是固定步长。 - 常用值:
0.5、0.75、1(默认)、1.25、1.5、2;0.85或1.35等中间值也适用。 - 含义:生成音频的语速,不是播放器的播放速度。
- 对含糊的说法采取保守映射:“慢一点” →
0.85、“快一点” →1.25、“慢很多” →0.5、“快很多” →1.75。用户指定的数字原样传入。
只有当速度不是 1 时,才在确认摘要中显示速度。
快速模式 — $CMD_PREFIX create --mode direct
步骤 1:提取文本
获取要转换的文本。如果用户尚未提供,请询问:
“你想让我朗读什么文本?”
步骤 2:确定音色
- 如果已设置
config.defaultSpeakers.{language}[0]→ 静默使用(跳至步骤 4) - 如果未设置 → 使用检测到的语言在
shared/speaker-selection.md中的内置默认值(跳至步骤 4) - 只有用户明确要求更换音色时,才显示音色选择
步骤 3:保存偏好设置
用户明确选择新音色后(使用默认值时不执行):
Question: "Save {voice name} as your default voice for {language}?"
Options:
- "Yes" — update .listenhub/tts/config.json
- "No" — use for this session only
步骤 4:确认
Ready to generate:
Text: "{first 80 chars}..."
Voice: {voice name}
Speed: {speed}x # omit this line when speed is 1
Proceed?
步骤 5:生成
对于较短的文本,直接传入:
RESULT=$($CMD_PREFIX create --text "{text}" --mode direct --speaker "{name}" --lang {lang} [--speed {0.5-2.0}] --json 2>/tmp/lh-err)
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
ERROR=$(cat /tmp/lh-err)
case $EXIT_CODE in
2) echo "Auth error: run 'listenhub auth login'" ;;
3) echo "Timeout: try --no-wait" ;;
*) echo "Error: $ERROR" ;;
esac
rm -f /tmp/lh-err
fi
rm -f /tmp/lh-err
AUDIO_URL=$(echo "$RESULT" | jq -r '.audioUrl')
对于较长的文本,先写入临时文件(参见 shared/cli-patterns.md § 长文本输入):
cat > /tmp/lh-content.txt << 'ENDCONTENT'
Long text content goes here...
ENDCONTENT
RESULT=$($CMD_PREFIX create --text "$(cat /tmp/lh-content.txt)" --mode direct --speaker "{name}" --lang {lang} [--speed {0.5-2.0}] --json)
AUDIO_URL=$(echo "$RESULT" | jq -r '.audioUrl')
rm -f /tmp/lh-content.txt
步骤 6:呈现结果
从配置中读取 OUTPUT_MODE。按照 shared/output-mode.md 中的说明执行。
inline 或 both:将 audioUrl 显示为可点击链接。
呈现:
Audio generated!
在线收听:{audioUrl}
download 或 both:同时下载文件。按照 shared/config-pattern.md § 文件命名,根据文本内容生成主题 slug。
SLUG="{topic-slug}" # e.g. "server-maintenance-notice"
NAME="${SLUG}.mp3"
# Dedup: if file exists, append -2, -3, etc.
BASE="${NAME%.*}"; EXT="${NAME##*.}"; i=2
while [ -e "$NAME" ]; do NAME="${BASE}-${i}.${EXT}"; i=$((i+1)); done
curl -sS -o "$NAME" "$AUDIO_URL"
呈现:
Audio generated!
已保存到当前目录:
{NAME}
脚本模式 — $CMD_PREFIX create --mode smart
步骤 1:获取脚本
确定用户是否已提供脚本数组:
-
已提供(JSON 或清晰的分段):解析并显示以供确认
-
尚未提供:帮助用户整理分段。询问:
“请提供包含说话人分配的脚本。格式:每行写成
SpeakerName: text content。我会为你转换。”用户提供脚本后,将其解析为带有说话人标注的文本。
步骤 2:为每个角色分配音色
对于脚本中的每个不同角色:
- 如果
config.defaultSpeakers.{language}中保存了音色 → 静默自动分配(按顺序为每个角色分配一个) - 如果未设置 → 使用
shared/speaker-selection.md中的内置默认值(第一个角色使用 Primary,第二个角色使用 Secondary) - 只有用户明确要求更换音色时,才显示音色选择
步骤 3:保存偏好设置
分配完所有音色后(如果有新音色):
Question: "Save these voice assignments for future sessions?"
Options:
- "Yes" — update defaultSpeakers in .listenhub/tts/config.json
- "No" — use for this session only
步骤 4:确认
Ready to generate:
Characters:
{name}: {voice}
{name}: {voice}
Segments: {count}
Speed: {speed}x # omit this line when speed is 1
Title: (auto-generated)
Proceed?
步骤 5:生成
使用说话人标记格式化脚本文本并提交。对于多说话人脚本,在文本中内联包含说话人名称。由于脚本模式可能耗时较长,请以 run_in_background: true 运行。
使用 --no-wait 提交(前台):
RESULT=$($CMD_PREFIX create --text "{formatted script with speaker markers}" --mode smart --speaker "{name1}" --speaker "{name2}" --lang {lang} [--speed {0.5-2.0}] --no-wait --json)
ID=$(echo "$RESULT" | jq -r '.id')
echo "Submitted: $ID"
对于较长的脚本,先写入临时文件:
cat > /tmp/lh-content.txt << 'ENDCONTENT'
SpeakerA: First line of dialogue
SpeakerB: Second line of dialogue
...
ENDCONTENT
RESULT=$($CMD_PREFIX create --text "$(cat /tmp/lh-content.txt)" --mode smart --speaker "{name1}" --speaker "{name2}" --lang {lang} [--speed {0.5-2.0}] --no-wait --json)
ID=$(echo "$RESULT" | jq -r '.id')
rm -f /tmp/lh-content.txt
使用 run_in_background: true 和 timeout: 600000 轮询(后台):
ID="<id-from-above>"
for i in $(seq 1 60); do
RESULT=$(listenhub creation get "$ID" --json 2>/dev/null)
STATUS=$(echo "$RESULT" | jq -r '.status // "processing"')
case "$STATUS" in
completed) echo "$RESULT"; exit 0 ;;
failed) echo "FAILED: $RESULT" >&2; exit 1 ;;
*) sleep 10 ;;
esac
done
echo "TIMEOUT" >&2; exit 2
步骤 6:呈现结果
后台任务完成后,解析结果:
AUDIO_URL=$(echo "$RESULT" | jq -r '.audioUrl')
SUBTITLES_URL=$(echo "$RESULT" | jq -r '.subtitlesUrl // empty')
DURATION=$(echo "$RESULT" | jq -r '.audioDuration // empty')
CREDITS=$(echo "$RESULT" | jq -r '.credits // empty')
从配置中读取 OUTPUT_MODE。按照 shared/output-mode.md 中的说明执行。
inline 或 both:将 audioUrl 和 subtitlesUrl 显示为可点击链接。
呈现:
Audio generated!
在线收听:{audioUrl}
字幕:{subtitlesUrl}
时长:{audioDuration / 1000}s
消耗积分:{credits}
download 或 both:同时下载文件。按照 shared/config-pattern.md § 文件命名生成主题 slug。
SLUG="{topic-slug}" # e.g. "welcome-dialogue"
NAME="${SLUG}.mp3"
# Dedup: if file exists, append -2, -3, etc.
BASE="${NAME%.*}"; EXT="${NAME##*.}"; i=2
while [ -e "$NAME" ]; do NAME="${BASE}-${i}.${EXT}"; i=$((i+1)); done
curl -sS -o "$NAME" "$AUDIO_URL"
呈现:
已保存到当前目录:
{NAME}
更新配置
保存偏好设置时,合并到 .listenhub/tts/config.json 中,不要覆盖未更改的键。
- 快速语音:将
defaultSpeakers.{language}[0]设为所选的speakerId - 脚本语音:将
defaultSpeakers.{language}设为本次会话分配的完整数组 - 语言:仅当用户明确指定时,才设置
language
API 参考
- CLI 执行模式:
shared/cli-patterns.md - CLI 身份验证:
shared/cli-authentication.md - 说话人列表:
shared/cli-speakers.md - 说话人选择指南:
shared/speaker-selection.md - 配置模式:
shared/config-pattern.md - 输出模式:
shared/output-mode.md
可组合性
- 调用:speakers CLI(用于选择说话人)
- 由其调用:explainer(用于配音)
示例
快速模式:
“TTS this: The server will be down for maintenance at midnight.”
- 检测:快速模式(纯文本,“TTS this”)
- 读取配置:
defaultSpeakers.en为空 - 使用内置默认说话人:Mars(
cozy-man-english) - 确认 → 用户批准
- 生成:
RESULT=$($CMD_PREFIX create --text "The server will be down for maintenance at midnight." --mode direct --speaker "Mars" --lang en --json) AUDIO_URL=$(echo "$RESULT" | jq -r '.audioUrl') - 呈现:将
audioUrl显示为链接(内联模式)
脚本模式:
“帮我做一段双人对话配音,A说:欢迎大家,B说:谢谢邀请”
- 检测:脚本模式(“双人对话”)
- 解析片段:A -> “欢迎大家”,B -> “谢谢邀请”
- 读取配置:
defaultSpeakers.zh为空 - 使用内置默认说话人:原野(主说话人)+ 高晴(次说话人)
- 确认 → 用户批准
- 生成:
RESULT=$($CMD_PREFIX create --text "A: 欢迎大家 B: 谢谢邀请" --mode smart --speaker "原野" --speaker "高晴" --lang zh --no-wait --json) ID=$(echo "$RESULT" | jq -r '.id') - 在后台轮询,直到完成
- 呈现:
audioUrl、subtitlesUrl、时长