IndexTTS2-PauseControl
IndexTTS2 精确停顿控制([pause:N])ComfyUI 节点包:句中与句号前后停顿精确调整,平均偏差 13ms;支持批量生成、候选试听验收、SRT 字幕与 seed 复现。Precise pause control ([pause:N]) ComfyUI nodes for IndexTTS2 — waveform-domain pause editing in-sentence and around periods, ±13ms, with batch generation, candidate acceptance and SRT subtitles.
Nodes (7)
IndexTTS2-PauseControl
English: README_EN.md
这是什么
IndexTTS2 的语音合成中,停顿长短由模型自行决定且不可控——同一个逗号,不同次生成可能停顿 200ms 或 500ms,无法按需求指定。
本工具(ComfyUI 节点包)提供精确停顿控制:在文本中直接指定停顿要求:
他停下脚步[pause:800ms]深吸一口气[pause:200ms]然后推开了那扇门[pause:600ms]。
生成后,"停下脚步"后停顿 800ms,"深吸一口气"后 200ms,句号前("那扇门"后)600ms——实测平均偏差 13ms。句中、句号前后均可用同一方式指定。
模型在个别位置可能断句不稳定——应停顿处未停顿、或在无标点处出现停顿。标记不受标点限制:可在任意位置(包括无标点处)指定停顿,生成时由模型在该处产生停顿并精确调整为目标时长。
官方句间静音参数(interval_silence)默认 200ms,短于句中逗号的模型自然停顿(约 300ms)——会出现句号停顿反而比逗号短的倒挂。本项目节点默认400ms(与句号的自然停顿接近),并可对句号处写标记精确覆盖。
无需修改模型、无需重新训练,安装节点即可使用。
安装
方式一:完整包(开箱即用,推荐)
- ComfyUI-Manager 搜索安装:节点已上架官方 Comfy Registry,在 Manager 中搜索
IndexTTS2-PauseControl一键安装。⚠️ 新上架节点可能暂未进入 Manager 的搜索索引(偶尔会搜不到),搜不到时请直接采用下面的手动安装:将本仓库目录(即IndexTTS2-PauseControl/)放到 ComfyUI 的custom_nodes/下,目录名保持IndexTTS2-PauseControl(⚠️ 如已存在同名目录请先备份——覆盖会替换旧内容) - 安装依赖到 ComfyUI 的 Python 环境(见
requirements.txt) - 运行
python install.py(自动装依赖 + 检查模型目录),或手动按requirements.txt安装 - 下载 IndexTTS2 模型权重到
ComfyUI/models/index_tts/(模型来源见官方 index-tts/index-tts,权重不属于本仓库) - 重启 ComfyUI
⚠️ 请以目录方式运行(放
custom_nodes/下),不要pip install .——本项目 包名与官方indextts同名,pip 安装会覆盖官方推理包。
方式二:打补丁(已有官方 indextts 包的用户,非 ComfyUI 也可)
如果你已有官方 IndexTTS2 推理代码(官方整合包 / 官方 ComfyUI 节点 / 自建管线),只需应用本仓库 patch/ 目录下的修改——不限于 ComfyUI:
- ComfyUI 用户:打补丁后直接用本仓库节点(与方式一效果相同)
- 非 ComfyUI 用户(Gradio WebUI 整合包、自建 API 等):打补丁后,在调用
IndexTTS2.infer(...)时传入pause_mode=True即可获得[pause:N]能力 (详见patch/PATCH_GUIDE.md;WebUI 接入方式未经实际部署验证)
- 将
patch/modified/中列出的文件覆盖到你的 indextts 包对应位置 - 将
patch/new_files/中列出的文件复制到对应目录 - 调用
IndexTTS2.infer(...)时传入pause_mode=True即可(见patch/PATCH_GUIDE.md)
补丁采用「完整文件覆盖 + 补丁说明」而非 git diff——官方代码版本会漂移,覆盖文件更可靠。
快速开始
1. 写标记
在文本中想要停顿的位置,直接写 [pause:时长]:
他停下脚步[pause:800ms]深吸一口气[pause:200ms]然后推开了那扇门。
他停下来[pause:1.5s]深吸一口气。
支持的写法:[pause:600ms] / [pause:600] / [pause:1.5s] / [pause:0.8s](也兼容 [wait:]、[stop:] 前缀)。生成时标记会被替换成普通逗号送入模型,不会读出"pause"之类的字。
2. 生成
ComfyUI 中连好工作流(示例见 workflows/):
IndexTTSLoader → IndexTTSSingle(打开 pause_mode) → PreviewAudio
导入示例工作流后,把 spk_ref 改成你的音色参考音频路径即可。
3. 试听对比
examples/audio/ 提供 4 条对比音频(同音色、同 seed,唯一差异是有没有标记):
| 文件 | 内容 | 实测停顿 |
|------|------|---------|
| zh_plain.wav | 他停下脚步,深吸一口气,然后推开了那扇门。 | 469/499/359ms(自然节奏,不规律) |
| zh_pause.wav | 他停下脚步[pause:800ms]深吸一口气[pause:200ms]… | 798ms / 190ms(精确命中) |
| en_plain.wav | He stopped and took a deep breath. | 80/309ms(自然) |
| en_pause.wav | He stopped[pause:800ms]and took a deep breath. | 798ms(精确命中) |
波形对比(点击波形图下载音频试听):
| 中文 | 英文 |
|------|------|
|
<br>zh_plain(无 pause) |
<br>en_plain(无 pause) |
|
<br>zh_pause(有 pause) |
<br>en_pause(有 pause) |
参考音色来自第三方收集音色(非本项目作者声音)。也可用examples/make_compare_demo.py 配合你自己的参考音频重新生成。
标记的更多细节
句号前后(最稳定,两种写法都精确):
他深吸一口气[pause:800ms]。然后推开了门。 ← 句号前
他深吸一口气。[pause:800ms]然后推开了门。 ← 句号后
时长范围:推荐 150ms ~ 5s(下限约 100ms;上限无硬限制,1s/2s/5s 都可以)。
中英文均可:英文句子同样精确(800ms 目标 → 实测 778ms)。
功能一览
核心能力——精确控制停顿:
- 句中停顿(逗号、顿号处):精确调整,±20ms
- 句号前后停顿:句号前、句号后两种写法都支持;即使模型在该处没有自然停顿,也会自动用"句间静音"实现目标时长——模型停不停都能达到你要的时长
- 引号场景:
句号+引号(…。')处同样可控,不用刻意避开 - 统一句号停顿:不写标记时,句号处停顿由
interval_silence统一控制(默认 400ms)。官方默认 200ms 时,段间停顿短于句中逗号的模型自然停顿(约 300ms),会出现句号停顿反而比逗号短的倒挂;400ms 与句号的自然停顿更接近,听感自然。适合先定整体节奏,再对个别句号精确覆盖
配套的生产流程能力(做长篇内容时用得上):
- 批量生成:分句稿(Markdown)或多行文本,一次跑全书;断点续跑
- 候选挑选:每段生成多轮候选(rounds),试听节点里逐轮试听
- 验收标记:听中意的候选,一键标记"第 N 轮通过"(写入 manifest,供后续拼接)
- seed 复现:固定 seed 可精确复现同一条音频;随机时自动记录实际 seed
- 字幕生成:按验收结果生成 SRT 字幕(读实际音频时长,自动对齐)
- 停顿微调:已生成的音频,按"序号"或"时间点"调整/删除某个停顿
- 显存释放:TTS 跑完、切到视频生成流程前,一键卸载模型腾显存
使用进阶
批量生成 + 候选试听 + 验收
工作流:
IndexTTSLoader → IndexTTSBatch(打开 pause_mode,rounds=3) → IndexTTSListen → PreviewAudio×3
IndexTTSBatch按分句稿(segments_md填文件路径)或text多行文本批量生成- 每段生成
rounds轮候选(如001_1.wav、001_2.wav、001_3.wav) IndexTTSListen选片段号试听 3 个候选;accept_round填 1/2/3 标记"第 N 轮通过验收"(写入 manifest.json,供后续拼接/字幕流程选用)
分句稿格式(Markdown)
segments_md 接受分句稿 Markdown 文件,格式:
---
story: 我的故事
voice_ref: references/我的音色/main.wav
emotion_base: references/译制片语气
emotions: [平静, 紧张]
speaking_speed: 1.0
max_text_tokens_per_segment: 120
---
# 片段 001 [叙述 / 平静]
<!-- 标题: 标准同样严苛 -->
标准同样严苛[pause:800ms]不多一分。
<!-- 处理后: 标准同样严苛[pause:800ms]不多一分。 -->
- YAML 头(可选):story / voice_ref / emotion_base / emotions / speaking_speed / max_text_tokens_per_segment
- 片段标题:
# 片段 N [角色 / 情绪]——情绪用于情感参考挑选("目录随机"策略) - 正文:生成文本,
[pause:N]原样保留;若提供<!-- 处理后: ... -->,以其内容为准 - 建议一句一个片段(句号停顿统一由句间静音控制,节奏规整)
- 不填分句稿时,直接在
text框按行写文本(每行 = 一个片段)
批量输出
运行后产生一个任务目录(output/{tag}_{时间戳}/,或自定义 output_dir):
output/批量生成_20260807_120000/
├── 001_1.wav 片段 1 第 1 轮候选
├── 001_1.wav.seed 该轮种子(固定 seed 可复现)
├── 001_2.wav / 001_2.wav.seed
├── 001_3.wav / 001_3.wav.seed
├── 002_1.wav … 片段 2 的三轮候选
└── manifest.json 任务参数 + 每片段每轮的 seed/时长/验收标记
- 命名:
{片段序号:03d}_{轮次}.wav(001_1= 片段 1 第 1 轮) - 再次运行同一任务目录 = 断点续跑(已完成轮次跳过;参数变更则全量重跑)
节点参数
| 节点 | 参数 | 说明 |
|------|------|------|
| IndexTTSSingle | pause_mode | 开启 [pause:N] 精确停顿控制 |
| IndexTTSSingle | detect_cfm_steps | 已弃用(无作用),保留兼容旧工作流 |
| IndexTTSBatch | pause_mode | 批量开启;开启后自动跳过旧版后处理 |
| IndexTTSBatch | rounds | 每片段生成轮次(候选数) |
| IndexTTSBatch | interval_silence | 句号处停顿 ms(未写标记时,默认 400) |
| IndexTTSListen | task_dir | 接收批量节点的 task_dir 输出(连线优先) |
| IndexTTSListen | accept_round | 验收:0=仅试听;1/2/3=标记该轮通过(写入 manifest.json) |
| IndexTTSUnload | model | 释放模型显存(TTS 跑完、进视频流程前调用) |
| IndexTTSFix | marks | 停顿修复串:2:800, 3:0(序号:目标ms,0=删除)或 7.53:500(时间点:目标ms) |
| IndexTTSSrt | chosen | 定版选择:1,2,1,3(每片段轮次);单值 3=全部第 3 轮;空=全第 1 轮 |
建议的文本组织方式
- 分句稿一句一个片段;句号停顿默认统一(
interval_silence),个别要精确的写标记覆盖 - 句内停顿直接写
[pause:N] - 长句(>40 字)多标记时,个别标记可能因模型停顿波动未命中——换 seed 或从多轮候选中挑(rounds=3 通常有全命中的候选)
工作原理(简述)
想了解实现原理的看这里,日常使用不需要:
- 分句:文本按标点句切分(句号=分句边界;句内不切,保持语气连贯)
- 标记分类:句中标记 → 分句内处理;句号前/后标记 → 分句边界处理
- 分句内处理:标记转逗号 → 模型正常生成 → 用能量检测找出音频里的停顿(物理信号,不依赖识别模型)→ 把标记与停顿全局对齐(容忍模型多停/漏停)→ 只对停顿的"静音核心"做延长/缩短/插入(不碰语音,免重新解码)
- 分句边界处理:分句尾标记命中则跳过句间静音(防叠加),未命中则用句间静音补目标时长;最后一个分句未命中时在音频末尾追加静音
- 拼接:句间静音 =
interval_silence(默认 400ms),被标记覆盖的间隙用标记时长
术语:分句(segment)= 按标点切出的标点句(官方
split_sentences输出);片段 = 分句稿中的# 片段 N条目(一个片段可能含多个分句)。
详细方案、参数标定与精度数据见 docs/PAUSE_CONTROL.md;术语与代码符号对照、数据流见 docs/CODE_WALKTHROUGH.md。
已知限制
- 长单句多标记:标记位置按字符比例估算,长句(>40 字)误差可能超过匹配上限,个别标记可能未命中——换 seed 或从多轮候选中挑选即可覆盖
- 分句尾模型无停顿:会改用句间静音/末尾追加实现目标时长(时长仍达成),但停顿位置落在句号处而非标记字后——听感正确,位置略偏
- 长停顿后的换气声:模型自然韵律(长停顿后可能吸气),工具不处理呼吸声,介意可对该段做降噪后处理
- 插入需要真静音:语音连续处无法插入停顿(宁缺毋滥,不切字)
测试
test/ 提供三层测试:
python test/unit_test.py # 核心函数单元测试(无需 GPU/模型,CI 自动跑)
python test/smoke_test.py --model-dir <模型目录> --spk-ref <参考音频> # 中英双语冒烟
python test/regression_test.py --model-dir <模型目录> --spk-ref <参考音频> # 5 片段回归
发布版实测:冒烟中英 PASS;回归 5 片段平均偏差 5ms。
致谢
- bilibili IndexTTS2 团队:模型与推理代码(本项目的
indextts/基于其开源实现修改) - ComfyUI:节点框架
- NVIDIA BigVGAN、Amphion MaskGCT:推理组件
- 序列比对算法:Needleman & Wunsch (1970)、Gotoh (1982)(详见 docs/PAUSE_CONTROL.md §8)
- 示例对比音频的参考音色来自第三方收集音色
致谢不代表上述团队对本项目的认可或背书;对原模型的修改与官方无关(见
THIRD_PARTY_NOTICES.md)。
License
- 本项目原创部分(ComfyUI 节点、pause 方案、文档):MIT License(见
LICENSE) indextts/推理代码:源自 bilibili IndexTTS2,受 bilibili Model Use LicenseAgreement 约束(商用需官方授权等),完整条款见LICENSE.bilibili.txt与THIRD_PARTY_NOTICES.md