Skip to content

About

一个通过本地API(如CosyVoice3)将文本转换为语音的 AstrBot 插件,支持多种音色和情绪配置。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

🎙️ TTS 语音生成插件

让 AstrBot 用你喜欢的声音说话。

连接本地语音服务,将文字回复转换为语音;按会话选择声音、风格和接口。

自定义接口 · 动态参数 · 会话分组 · 语音附原文

快速开始 · 命令用法 · 参数配置 · 会话设置 · 常见问题


功能一览

功能 可以做什么
自定义提供商 保存多个 TTS 接口,选择一个全局默认,也可为会话单独指定
参数占位符 用固定文本、LLM 生成文本或随机数填入请求参数,支持中文名称
会话分组 为一组群聊或私聊设置专属音色、风格和自动转换规则
两种转换方式 用命令朗读指定文本,或按概率自动转换机器人的短回复
语音后附原文 自动转换时,语音发送成功至少 0.5 秒后,由主框架处理和发送原回复
权限与缓存 统一限制命令权限,按时间、容量和数量清理音频缓存

快速开始

1. 准备语音服务

你需要:

  • AstrBot 4.16 或更高版本(不设大版本上限;新大版本仍需确认实际兼容性)。
  • 一个 AstrBot 能访问的 TTS 服务,支持 GET 请求并直接返回音频。
  • 服务支持的音色名称,以及它的接口地址和参数说明。

插件负责连接服务,不包含语音模型。通过“自定义 GET 接口”模板添加服务,实际参数请以所用服务为准。

地址提示:localhost 指 AstrBot 所在的运行环境。如果 AstrBot 在容器中、TTS 在宿主机上,请填写容器可以访问的宿主机地址。

2. 添加接口和音色

在 AstrBot 的插件管理中使用本仓库地址安装插件,然后打开插件设置。

按以下步骤连接服务:

  1. 在 提供商列表 中添加 自定义 GET 接口 模板。

  2. 将名称填写为 本地语音,按实际部署修改 URL 中的主机和端口:

    http://localhost:7865/api?text={text}&speed=1.0&speaker={speaker}&seed=-1&cfg=1&instruct={instruct}
    
  3. 在 全局占位符 中找到 {speaker},将固定值填为服务支持的音色名称。

  4. 点击 保存,等待插件重载,关闭并重新打开设置页。

  5. 在顶部 全局 TTS 提供商 下拉框选择 本地语音,再次保存。

先保存提供商,再在顶部选择。 下拉框读取已保存的名称;没有添加提供商时显示为空。

3. 发出第一条语音

在聊天中发送:

TTS 你好,很高兴认识你。

查看当前会话的实际设置:

TTS帮助

是否需要在命令前加 / 或先 @机器人,取决于 AstrBot 的唤醒配置。本文示例均省略唤醒前缀。

4. 按需开启更多功能

想要的效果 设置位置
只使用命令生成语音 将 主动调用配置 → 主动转换概率 设为 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。

理解 URL 与占位符

提供商定义“向哪里请求、发送哪些参数”,占位符定义“参数值从哪里来”。

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,再编辑 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帮助,确认会话已启用、全局或会话提供商已选择。再检查:

  1. 命令是否满足 AstrBot 的唤醒要求,以及你是否具有使用权限。
  2. TTS 服务是否启动,AstrBot 能否访问所填地址。
  3. 音色名称和请求参数是否符合服务要求。
  4. URL 中是否引用了未定义的占位符。
手动可以生成,为什么回复没有自动变成语音?

检查自动概率是否为 0、文本是否超长、是否限定 LLM 回复,以及消息是否包含图片、引用等其他内容。需要自动转换时,请关闭对应会话的流式输出。

配置了情绪提示词,为什么 LLM 没有调用?

确认已选择“插件内置 LLM”,调用概率大于 0,且 URL 确实引用了该占位符。会话或命令已经为它赋值时,不会再调用模型。未命中概率或生成失败时,会使用备用值;备用值为空则省略参数。

更换音色或会话参数后,为什么效果没变?

检查实际使用的提供商与占位符名称,再按“命令 → 会话 → 全局”的顺序排查覆盖。只改了占位符名称、却没改 URL,或拼错了覆盖名称,都可能使设置无法按预期生效。

提示接口返回的不是音频?

HTTP 请求成功不代表返回了音频。服务可能返回错误页面、JSON 或下载地址。请确认接口直接返回受支持的音频数据,而非需要再次下载的链接。

设置保存成功,却提示配置无效?

保存后还会检查提供商重名、失效引用、重复 SID、占位符名称及随机数范围。使用 TTS帮助 查看错误提示,回到设置页修正后重新保存。

About

一个通过本地API(如CosyVoice3)将文本转换为语音的 AstrBot 插件,支持多种音色和情绪配置。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages