让 AstrBot 用你喜欢的声音说话。
连接本地语音服务,将文字回复转换为语音;按会话选择声音、风格和接口。
自定义接口 · 动态参数 · 会话分组 · 语音附原文
| 功能 | 可以做什么 |
|---|---|
| 自定义提供商 | 保存多个 TTS 接口,选择一个全局默认,也可为会话单独指定 |
| 参数占位符 | 用固定文本、LLM 生成文本或随机数填入请求参数,支持中文名称 |
| 会话分组 | 为一组群聊或私聊设置专属音色、风格和自动转换规则 |
| 两种转换方式 | 用命令朗读指定文本,或按概率自动转换机器人的短回复 |
| 语音后附原文 | 自动转换时,语音发送成功至少 0.5 秒后,由主框架处理和发送原回复 |
| 权限与缓存 | 统一限制命令权限,按时间、容量和数量清理音频缓存 |
你需要:
- AstrBot 4.16 或更高版本(不设大版本上限;新大版本仍需确认实际兼容性)。
- 一个 AstrBot 能访问的 TTS 服务,支持 GET 请求并直接返回音频。
- 服务支持的音色名称,以及它的接口地址和参数说明。
插件负责连接服务,不包含语音模型。通过“自定义 GET 接口”模板添加服务,实际参数请以所用服务为准。
地址提示:
localhost指 AstrBot 所在的运行环境。如果 AstrBot 在容器中、TTS 在宿主机上,请填写容器可以访问的宿主机地址。
在 AstrBot 的插件管理中使用本仓库地址安装插件,然后打开插件设置。
按以下步骤连接服务:
-
在 提供商列表 中添加
自定义 GET 接口模板。 -
将名称填写为
本地语音,按实际部署修改 URL 中的主机和端口:http://localhost:7865/api?text={text}&speed=1.0&speaker={speaker}&seed=-1&cfg=1&instruct={instruct} -
在 全局占位符 中找到
{speaker},将固定值填为服务支持的音色名称。 -
点击 保存,等待插件重载,关闭并重新打开设置页。
-
在顶部 全局 TTS 提供商 下拉框选择
本地语音,再次保存。
先保存提供商,再在顶部选择。 下拉框读取已保存的名称;没有添加提供商时显示为空。
在聊天中发送:
TTS 你好,很高兴认识你。
查看当前会话的实际设置:
TTS帮助
是否需要在命令前加 / 或先 @机器人,取决于 AstrBot 的唤醒配置。本文示例均省略唤醒前缀。
| 想要的效果 | 设置位置 |
|---|---|
| 只使用命令生成语音 | 将 主动调用配置 → 主动转换概率 设为 0 |
| 只转换大模型回复 | 保持 自动转换仅对 LLM 回复生效 开启(默认) |
| 自动转换时保留文字 | 开启 语音后附原文,或发送 TTS原文 开启 |
| 用小模型判断说话情绪 | 选择 插件内置 LLM,配置 LLM 占位符 |
| 只在指定群聊使用 | 在 启用的会话 中添加会话组 |
| 不允许普通用户修改设置 | 开启 TTS 命令仅允许管理员使用 |
默认行为:全部会话启用;自动转换概率为 80%,长度上限为 75 字符;默认仅转换 LLM 回复,不附原文,未选择内置 LLM。管理员限制默认关闭,公共群聊中请按需开启。
TTS 今天也是美好的一天。
格式:
TTS {占位符}=值&{另一个占位符}=值 要朗读的文本
例如,使用默认的占位符名称:
TTS {speaker}=女孩&{instruct}=温柔地说 晚安,做个好梦。
女孩 仅为示例,请替换为服务支持的音色。临时参数只影响这一次,不会修改已保存的设置;手动指定某个 LLM 占位符后,本次不再调用模型生成它。
输入规则:
- 命令、参数块、正文之间用空格分隔。
- 多个赋值用
&连接,参数块内部不要额外加空格。 - 值包含空格或
&时,用英文双引号包住。 - 占位符名称必须与配置一致,同一个名称不能重复赋值。
TTS {speaker}="Little Girl"&{instruct}="温柔 克制地说" 你好。
如果已经将占位符改为中文名称,也可以这样输入:
TTS {人物}=女孩&{情感}=高兴 今天有个好消息!
特殊输入:清空参数、朗读赋值语句、输入引号
本次不指定某个参数:
TTS {instruct}= 你好。
空值会让使用这个占位符的整个请求参数被省略。
正文恰好以 {名称}=值 开头:
TTS -- {人物}=女孩 是一个配置示例。
-- 表示后面的内容全部用于朗读,不再识别参数。
双引号内如需输入双引号或反斜杠,分别使用 \"、\\。
| 命令 | 用途 |
|---|---|
TTS帮助 |
查看本会话实际设置、当前使用的占位符及常用命令,未启用会话仅显示必要提示 |
TTS帮助 详细 |
查看当前使用的占位符、覆盖来源和完整用法 |
TTS提供商 |
查看已保存的提供商,标注全局默认和当前会话使用项 |
TTS切换 名称 |
切换并保存全局默认提供商,使用完整名称 |
TTS原文 开启 |
开启自动转换后的原文发送 |
TTS原文 关闭 |
关闭自动转换后的原文发送 |
TTS原文 状态 |
查看全局开关状态 |
TTS本组原文 开启/关闭/跟随 |
修改当前匹配会话组的附原文设置,仅限 AstrBot 管理员 |
TTS本组原文 状态 |
查看所属组、实际开关及生效会话数量;无参数也可查询 |
TTS清理 |
清理音频缓存,跳过正在使用的文件 |
所有命令均受管理员限制开关控制;本组原文的修改操作额外要求 AstrBot 管理员身份,即使关闭限制也不向普通用户开放(QQ群管理员不等同于 AstrBot 管理员)。手动命令保留输入错误、权限和生成失败提示;未启用 TTS 的会话仍不执行生成。关闭限制后,普通用户也能切换全局提供商、修改原文开关和清理缓存。 管理命令的回复始终为文字。命令产生的文字回复由 AstrBot 统一处理,跟随主框架的“回复时引用发送人消息”设置;语音本身不自动添加引用。
普通帮助与详细帮助都使用纯文本,不依赖 Markdown 排版。当前使用的占位符在简版中也会展示;需要辅助 LLM 时显示其实际模型名,仅读取模型信息,不发起模型调用。帮助中的命令前缀取当前会话配置中的第一个非空唤醒前缀;未配置时不加前缀。未启用会话即使请求详细帮助,也只返回启用方法提示。管理员限制开启时,未启用会话的非管理员仍保持静默。
在每个提供商内部设置 任务并行上限,可填 1~64 的整数,默认 1 表示串行。所有使用同一提供商的会话共享名额,不同提供商独立计数。名额覆盖辅助 LLM 参数生成、TTS 请求及缓存落盘,不包含平台消息发送和附原文等待;超出名额的任务排队,排队时间不计入提供商请求超时。保存并重载后生效。
即使两个提供商条目指向同一个后端服务,也分别计数。如果服务只能串行处理,建议只创建一个对应条目并设置为 1。
提供商定义“向哪里请求、发送哪些参数”,占位符定义“参数值从哪里来”。
http://localhost:7865/api?text={text}&speaker={人物}&instruct={情感}
| URL 中的内容 | 含义 |
|---|---|
text={text} |
将本次朗读的文字传给接口的 text 参数 |
speaker={人物} |
将名为 {人物} 的占位符值传给 speaker |
instruct={情感} |
将名为 {情感} 的占位符值传给 instruct |
text、speaker、instruct 是接口要求的参数名;花括号里的名称则由插件配置决定。除了固定的 {text},其他占位符都可以自定义名称。
固定参数可以直接写进 URL,例如 speed=1.0、cfg=1、seed=-1。希望它们能够动态变化或被会话覆盖时,再改为占位符。
| 类型 | 默认名称 | 配置方法 |
|---|---|---|
| 朗读文本 | {text} |
系统自动填入,不可改名、删除或覆盖 |
| 固定文本 | {speaker} |
手动填写一个值,例如音色、语言或速度 |
| LLM 生成文本 | {instruct} |
填写提示词、调用概率和可选备用值 |
| 范围随机数 | {random} |
选择整数或小数,设置范围及小数位数 |
初始已提供后三种占位符条目,可直接编辑或继续添加。{speaker} 初始为空,需要按服务要求填写。
名称支持中文,不能重复,也不能包含空格、花括号、& 或 =。修改名称后,需要同步修改 URL 和会话中的引用。
占位符名称:{speaker}
固定值:女孩
配合 speaker={speaker},即可设置默认音色。它也可以用来填写任何其他接口参数,并非只能表示音色。
先选择 插件内置 LLM,再编辑 LLM 占位符:
占位符名称:{instruct}
生成提示词:判断{text}这句话的情绪,只返回一个词,不要加任何多余说明
调用概率:0.5
备用值:留空
0:不调用模型;1:每次需要这个值时都调用;0.5:有 50% 概率调用。- 未触发、模型不可用或生成失败时,使用备用值。
- 备用值留空,就省略对应请求参数,不额外指定风格。
- URL 未使用这个占位符,或会话/命令已指定它的值时,不调用模型。
所有 LLM 占位符共用所选模型,各自独立判断调用概率。提示词只支持引用 {text},不携带主会话历史;每次调用最多等待 15 秒,空结果或超过 256 字符的结果视为无效。
启用此功能后,待分析的朗读文本会发送给所选 LLM 服务。请根据文本的隐私要求选择模型。
将接口中的 seed=-1 改为 seed={random},再设置:
占位符名称:{random}
数值类型:整数
最小值:0
最大值:10000
小数模式可设置 0~8 位小数。例如范围 1.01~1.03、保留两位小数,可能得到 1.01、1.02 或 1.03。范围包含两端,必须至少有一个符合精度的数值;边界绝对值不超过 10¹²。
同一次请求中,同名占位符只求值一次,重复引用得到相同结果。
假设模板是:
?text={text}&speaker={speaker}&instruct={instruct}&speed=1.0
本次 {instruct} 没有生成值,也没有备用值,则请求变为:
?text=你好&speaker=女孩&speed=1.0
省略整个 instruct 参数,不留下 instruct=,其他参数不受影响。 固定占位符留空、会话或命令明确赋空值,也遵循这个规则。
注意:
- 一个参数引用了多个占位符,其中任何一个无值,整个参数都会省略。
instruct=使用四川话,{情感}也会整体省略。想始终保留四川话,可让 LLM 生成完整指令,并把备用值填成使用四川话。- URL 引用了未定义且未被会话或命令赋值的名称,会报错,不按空值处理。
- 确实需要发送固定空参数时,可直接在 URL 中填写
instruct=。
接口配置注意事项
- 占位符只支持放在 URL 查询参数的值中,不支持主机、端口、路径或参数名;模板必须包含
{text}。 - 在占位符配置和命令里直接填写原始文字,插件会自动编码。不要提前把文字转成 URL 编码。
- 直接写在 URL 中的固定值需要遵守 URL 编码规则,例如文字里的
&写成%26、+写成%2B、#写成%23。 - 提供商名称不可重复。添加或改名后,保存并重新打开设置页刷新下拉框;改名不会影响已有会话引用。
- 删除提供商前,请先更改引用它的全局和会话设置。失效引用会导致配置错误,不会自动改用其他接口。
- 请求超时默认 60 秒,可设置为
1~600秒。 - 当前支持直接返回 WAV、MP3、OGG、FLAC、AAC 的 GET 接口,不支持 POST、JSON 下载地址、异步任务、鉴权请求头或重定向。插件不转码,实际播放还取决于消息平台支持的格式。
- 单次音频响应最多 32 MB。请使用受信任的服务,不在 URL 或普通占位符中放置敏感凭据。
“启用的会话”既控制使用范围,也允许不同群聊或私聊使用不同配置。
| 列表状态 | 生效范围 |
|---|---|
| 没有添加会话模板 | 所有会话启用,使用全局设置 |
| 已添加会话模板 | 仅模板中列出的会话启用 |
| 某条模板没有填写 SID | 该条不匹配任何会话 |
| 设置项 | 填写说明 |
|---|---|
| 会话 SID 列表 | 一项一个完整 SID,可添加多个;重复 SID 从上到下仅采用第一个匹配组 |
| 会话备注 | 便于识别的名称,例如“日常聊天” |
| 本组提供商 | 默认跟随全局,也可单独选择 |
| 占位符覆盖 | 一项一个 {名称}=值,留空则全部继承 |
| 主动转换概率 | 留空跟随全局;填写 0~1,其中 0 表示关闭 |
| 文本长度上限 | 留空跟随全局;填写正整数,最大 100000 |
| 语音后附原文 | 跟随全局设置(默认)/开启/关闭,仅自动转换生效 |
| LLM赋值调用概率 | 留空沿用全局各 LLM 占位符原有概率;填写 0~1 则统一本组概率,仍各自独立抽样 |
SID 是 AstrBot 用来识别会话的完整标识,例如 napcat:GroupMessage:123456。请以 AstrBot 实际提供的 SID 为准,不要只填写群号。
同一 SID 出现多次时,第一个匹配组的整组设置生效,不合并后面的组;首组某项选择继承时直接跟随全局,不向后查找。调整组顺序会改变生效设置;重复项会在加载日志中给出简短提醒,不导致整个插件停止生成。
TTS本组原文 修改的是当前 SID 首次匹配的整个组,影响所有实际采用该组的会话。没有所属组时只给提示,既不改全局,也不自动建组。特别是会话列表为空时,自动建组会改变“全部会话启用”的范围,因此需要管理员在设置页主动配置。
LLM赋值概率与主动转换概率不同:例如全局 {情绪} 的概率是 0.5、{语气} 是 0.8,本组留空则保持这两个概率;本组填写 0.3,两者各自以 30% 概率调用。0 明确关闭调用。此覆盖适用于手动和自动 TTS,但不影响备用值规则;未被 URL 使用或已由会话/命令直接赋值的占位符仍不调用 LLM。
在占位符覆盖列表中,分别添加:
{speaker}=男孩
{instruct}=温柔地说
这一组会话将使用指定的固定值,{instruct} 不再调用 LLM。音色名称仍须得到服务支持。
- 列表留空:继承全局占位符。
{instruct}=:明确不传该参数,不是继承。- 名称未被 URL 使用的覆盖项不会生效;如果设置没有效果,先检查拼写。
最终优先级:
提供商 会话指定 → 全局默认
占位符 本次命令 → 会话覆盖 → 全局占位符
自动转换规则 会话填写值 → 全局值
附原文 会话开启/关闭 → 全局开关
LLM赋值概率 会话填写值 → 全局各占位符的概率
切换全局提供商只影响“跟随全局”的会话。每次生成只调用一个提供商,失败时不切换其他接口。
主动调用配置决定机器人回复是否自动变为语音:
| 选项 | 作用 |
|---|---|
| 主动转换概率 | 0~1,默认 0.8;设为 0 关闭自动转换 |
| 文本长度上限 | 默认 75 字符,超过上限保持文字 |
| 自动转换仅对 LLM 回复生效 | 开启后,只处理被标记为 LLM 回复的消息 |
| 语音后附原文 | 语音成功至少 0.5 秒后,原回复继续按主框架的切分、前缀等规则处理和发送 |
自动转换只处理单个纯文本消息,不处理图文混合、引用、多组件消息或流式输出。自动生成或语音发送接口报错时,原回复及其原有标记保持不变,继续由主框架处理,不由插件另行补发文字,也不向聊天发送报错。手动 TTS 是明确的操作请求,输入有误或生成失败时会返回错误提示;也可使用 TTS帮助 检查配置。
手动 TTS 不受自动概率、长度上限和“仅 LLM 回复”开关限制,但仍受会话范围和命令权限限制。**手动 TTS 成功只返回语音,不重复发送命令中已有的正文,也不发送成功提示。语音后附原文开关仅对自动转换生效。**0.5 秒间隔只用于两条消息之间,不是平台级限流,也不保证免于平台风控。
自动转换在主框架的回复处理钩子中先尝试生成并发送语音,只有发送接口成功返回后,才根据“附原文”设置保留或移除原文字回复。不重新执行事件、不重新调用主 LLM,也不复制主框架的切分规则。自动语音在后续回复修饰之前发送,不经过之后的主框架文本修饰或其他插件处理;需要这些处理的文字仍交给主框架。与其他会改写/阻止回复的插件同时使用时,应检查组合效果。
平台发送接口报错不一定意味着用户端完全没有收到语音;极端情况下可能同时看到语音和继续发送的文字。生成或发送超时也会延迟原回复。开启附原文时,“交给主框架”不保证最终一定是一条完整文字,仍受主框架的切分、引用、渲染等设置控制。
自动转换概率与 LLM 占位符概率彼此独立:前者决定“是否发语音”,后者决定“生成语音时是否让小模型填写这个参数”。
生成的语音会保存在本地。可在 缓存管理 中设置:
| 限制 | 填写方式 |
|---|---|
| 最长保留时间 | 正数,单位小时,支持小数 |
| 总大小上限 | 正数,单位 MB,支持小数;1 MB = 1024 × 1024 字节 |
| 文件数量上限 | 正整数 |
每项留空表示不限制,三项均空则关闭自动清理。不要填写 0、负数或无效内容,否则会暂停自动清理。
任意一项超限都会优先清理较旧文件;正在使用的音频会暂时跳过,因此可能短暂超限。也可使用 TTS清理 手动清理。
astrbot_plugin_local_TTS/
├─ main.py # 插件入口、聊天命令与消息处理
├─ configuration.py # 配置校验、会话规则与提供商下拉选项
├─ request_template.py # URL 模板、占位符名称与命令参数解析
├─ placeholders.py # 固定文本、LLM 文本与随机数求值
├─ tts_client.py # TTS 接口请求与音频格式检查
├─ delivery.py # 语音生成、发送顺序与并发控制
├─ audio_cache.py # 音频保存、在用文件保护与缓存清理
├─ help_text.py # 当前会话的帮助信息
├─ _conf_schema.json # 插件设置页的配置项与模板定义
├─ metadata.yaml # 插件名称、版本与兼容性信息
├─ requirements.txt # Python 依赖
├─ .gitignore # 版本控制忽略规则
├─ README.md # 使用说明
└─ LICENSE # 开源协议
以下为典型部署下的相对路径,以 AstrBot 实际使用的数据目录为准:
data/
├─ config/
│ └─ astrbot_plugin_local_TTS_config.json # 已保存的插件配置
└─ plugin_data/
└─ astrbot_plugin_local_TTS/
└─ audio/ # 生成的音频缓存
配置与音频缓存独立于插件代码。日常设置通过插件设置页修改,缓存可通过自动清理规则或 TTS清理 管理。
每次转换有一个短编号,用于关联请求、发送和故障。开启 DEBUG 日志后,正常情况下可看到:
[TTS/GET][a12f34bc] 200 | 1.23s | 0.045MB | 实际GET请求URL
[TTS/发送][a12f34bc] 语音发送成功 | 来源=自动 | 内容="你好。\n晚安。" | {instruct}=Weary care
[TTS/发送][a12f34bc] 原回复交由主框架处理 | 间隔≥0.5s
第三行为 DEBUG 日志,仅在自动转换且开启附原文时出现,表示交还主框架,不代表原文已送达。GET 成功表示已经取回音频,语音发送成功表示平台发送方法正常返回,不代表用户已收听。
| 级别 | 标签 | 内容 |
|---|---|---|
| INFO | [TTS/配置] |
配置加载摘要、提供商数量及自动转换设置 |
| DEBUG | [TTS/GET] |
实际编码后的完整请求 URL、状态码、耗时与音频大小 |
| INFO | [TTS/发送] |
语音发送结果(原回复交还主框架记录为 DEBUG) |
| INFO | [TTS/命令] |
全局提供商切换、附原文开关修改 |
| INFO | [TTS/缓存] |
清理原因、删除数量、释放大小、在用跳过数 |
| WARNING | 对应阶段标签 | 配置、请求、LLM、发送或缓存异常及处理结果 |
| DEBUG | [TTS/跳过]、[TTS/生成]、[TTS/LLM] |
未命中概率、文本超长及参数求值等过程信息 |
缓存清理区分“何时检查”和“为什么删除”,例如:
[TTS/缓存] 清理完成 | 检查=定时 | 原因=容量超限(100MB)、数量超限(200个) | 删除=8个/15.20 MB | 在用跳过=1个
清理原因包括超过保留时间、容量超限、数量超限和手动命令。没有需要清理的文件时,自动检查不输出 INFO;持续相同的缓存警告最多每五分钟一次。暂时无法删除的在用文件会标记为“部分暂缓”。清理释放大小小于 1 MB 时显示 KB,否则显示 MB,保留两位小数;手动清理回复使用相同格式。容量限制配置仍以 MB 填写,1 KB = 1024 字节,1 MB = 1024 × 1024 字节。
只有主动转换失败时不向聊天发送故障提示;手动命令仍返回错误反馈。插件自身异常最高记录为 WARNING,不输出异常堆栈或服务返回正文;AstrBot 及平台适配器自己的日志级别由它们决定。
日志包含朗读原文和请求参数。 请妥善保存日志,分享前检查隐私。URL 中按参数名识别的密钥、token、密码等值会脱敏,因此这类字段不会原样展示;不要将凭据藏在普通参数或 URL 路径中。
添加提供商后,顶部下拉框没有出现名称?
先保存配置,等待插件重载,再关闭并重新打开设置页。提供商名称不能为空。下拉框不会读取尚未保存的输入,也不会自动选中第一项。
发送 TTS 后没有语音,应该先查什么?
先发送 TTS帮助,确认会话已启用、全局或会话提供商已选择。再检查:
- 命令是否满足 AstrBot 的唤醒要求,以及你是否具有使用权限。
- TTS 服务是否启动,AstrBot 能否访问所填地址。
- 音色名称和请求参数是否符合服务要求。
- URL 中是否引用了未定义的占位符。
手动可以生成,为什么回复没有自动变成语音?
检查自动概率是否为 0、文本是否超长、是否限定 LLM 回复,以及消息是否包含图片、引用等其他内容。需要自动转换时,请关闭对应会话的流式输出。
配置了情绪提示词,为什么 LLM 没有调用?
确认已选择“插件内置 LLM”,调用概率大于 0,且 URL 确实引用了该占位符。会话或命令已经为它赋值时,不会再调用模型。未命中概率或生成失败时,会使用备用值;备用值为空则省略参数。
更换音色或会话参数后,为什么效果没变?
检查实际使用的提供商与占位符名称,再按“命令 → 会话 → 全局”的顺序排查覆盖。只改了占位符名称、却没改 URL,或拼错了覆盖名称,都可能使设置无法按预期生效。
提示接口返回的不是音频?
HTTP 请求成功不代表返回了音频。服务可能返回错误页面、JSON 或下载地址。请确认接口直接返回受支持的音频数据,而非需要再次下载的链接。
设置保存成功,却提示配置无效?
保存后还会检查提供商重名、失效引用、重复 SID、占位符名称及随机数范围。使用 TTS帮助 查看错误提示,回到设置页修正后重新保存。