# 配置语音 中文 | [English](en/voice-setup.md) 这份说明带你从一台刚装好的 Mac 开始,配到角色能开口说话。按顺序做就行。 阿哈酒馆不自带语音模型。在苹果芯片的 Mac 上,插件可以替你装好并启动一个本机的语音服务(mlx-audio,默认用 Qwen3-TTS 模型);别的系统,或者你已经有自己的语音服务,也可以只连接它。朗读期间不会调用聊天模型,声音文件只存在你的酒馆文件夹和系统临时目录里。 ## 1. 你需要什么 让插件代为启动本机语音服务,需要: - 苹果芯片的 Mac(M 系列)。 - [uv](https://docs.astral.sh/uv/)。插件用它建 Python 环境,装好后在终端里能运行 `uv` 即可。本机没有 Python 3.12 时 uv 会自己下载一份,放在 uv 自己的目录里(不在下面说的权重目录里),它的包缓存也是。 - 磁盘:运行环境约 0.44GB;模型 0.6B 约 1.9GB,1.7B 约 2.9GB;以后用到音色设计,还要再下约 2.9GB 的设计模型。 - 内存:用 0.6B 模型时,服务稳定运行约占 2.2GB;加载模型和第一次合成时峰值约 8.7GB,其间建议关掉占内存的应用。 - 能联网下载模型(或者设好下载源,见下面)。 Windows 和 Linux 上插件不会代为启动,需要你自己部署语音服务,见第 8 节。 ## 2. 第一步:写 services.yaml 配置文件和生图共用一个: ``` ~/.dsh/aha-tavern/services.yaml ``` 设了 `DSH_HOME` 时放在 `$DSH_HOME/aha-tavern/services.yaml`。目录和文件不存在就自己建。 最短的写法,让插件在本机代为启动: ```yaml voice: endpoint: http://127.0.0.1:18123 launch: mlx ``` 没有这个文件,或者没有 `voice` / `endpoint`,就等于没配置语音。每次用到时才读取,改完不用重启 DSH。 完整的写法,下面每个字段都写了默认值,不想改的可以不写: ```yaml voice: endpoint: http://127.0.0.1:18123 # 必填。语音服务的地址,要是 http:// 或 https:// 开头 launch: none # mlx:允许插件在本机代为启动(endpoint 必须是本机地址);none:只连接,不代为启动 model: 0.6b # 0.6b、1.7b,或完整的模型名 # modelsDir: ~/.dsh/aha-tavern/voice # 运行环境和模型权重放哪里;绝对路径,可以用 ~ 开头 # hfEndpoint: https://hf-mirror.com # 下载模型用的镜像地址;不写用官方源 read: lines # lines:只念台词;all:整段都念 pauseSeconds: 2 # 段间停顿(秒):隔着大约 12 个没念出来的字时停多久;字多停久些,字少停短些;0 表示不停 pauseMinSeconds: 1 # 段间停顿最短多久(秒) pauseMaxSeconds: 4 # 段间停顿最长多久(秒) language: chinese # 传给语音服务的语言 timeoutSeconds: 120 # 单句合成最多等多少秒 ``` 几点说明: - `launch` 默认是 `none`,所以想让插件代为启动,必须写 `launch: mlx`。`endpoint` 不是本机地址(`127.0.0.1`、`localhost` 这类)时,`mlx` 会被改回 `none`。 - 地址的端口就是服务监听的端口,换端口直接改 `endpoint`。地址里不要带用户名和密码。 - `model` 写 `0.6b` 或 `1.7b` 时,对应的完整模型名是 `mlx-community/Qwen3-TTS-12Hz-0.6B-Base-8bit` 和 `mlx-community/Qwen3-TTS-12Hz-1.7B-Base-8bit`。1.7B 音质更好,更占内存。 - `modelsDir` 不写时放在 `~/.dsh/aha-tavern/voice`(设了 `DSH_HOME` 则在 `$DSH_HOME/aha-tavern/voice`)。运行环境在其下的 `env/`,模型在 `hf/`,服务日志是 `server.log`。 - `hfEndpoint` 只影响模型下载。连官方源很慢时可以改成镜像,比如上面写的 `https://hf-mirror.com`。 写错的字段会改用默认值,`/aha 自检 语音` 的卡片里会写明是哪一项。 仓库里的 `examples/services.example.yaml` 是同样内容,可以直接复制。 **也可以在设置页里改。** 在 DSH 的插件页里打开 `aha-tavern`(阿哈酒馆),里面有"语音"和"生图"两节:填写、保存、测试连接,还能直接启动和停止语音服务。页面只会保存你改过的字段,文件里的注释和别的字段都会留着(行内注释前多出来的空格会被收成一个)。设置页只在用 `dsh plugin add` 安装插件时出现;用 `--patch` 调试时看不到。 ## 3. 第二步:启动语音服务 在聊天里输入: ``` /aha 语音 启动 ``` 在任何酒馆模式里都能用。第一次启动时,要先装运行环境、下载模型,所以会先弹出一张卡片,列出要装什么、多大、存哪里、从哪下载,并提醒加载模型时内存占用峰值约 9GB。点"开始"才会动手,点"取消"什么都不会装。 之后的流程是三步:安装运行环境(只有第一次)→ 启动服务 → 下载并加载模型(只有第一次下载)。在我们的实测里,全新安装约 17 秒,服务启动后约 4 秒就能应答;模型下载要多久取决于你的网速。 启动命令最多等 8 秒。8 秒内没完成,就回一句"语音服务正在启动",转到后台继续。用下面的命令看进度: ``` /aha 语音 状态 ``` 不带参数的 `/aha 语音` 等同于状态。启动好后,状态会写明服务由谁启动、用的是哪个模型。 停掉服务: ``` /aha 语音 停止 ``` 要记住几件事: - 插件**不会自己启动**语音服务,每次都要你敲 `/aha 语音 启动`(或在设置页点"启动服务")。 - 服务随 DSH 退出而停止,关终端、强杀 DSH 也一样,不会留下残余进程。 - 只有插件自己启动的服务,`/aha 语音 停止` 才会去停;你自己启动的服务它不会动。 - 下载中途断了,重新 `/aha 语音 启动` 会接着下,不用从头来。 ## 4. 第三步:给角色配声音 声音要在"酒馆:筹备"里配,直接对掌柜说就行。有两种办法。 ### 办法一:自备一段录音 对掌柜说想给某个角色配声音,并告诉他两样东西:录音文件的路径,和录音里说的话。 对录音有要求: - 3 到 15 秒。 - 只有一个人在说话,背景干净。 - 你给的文字必须和录音**逐字一致**,一个字都不要改。拿不准就照着录音听写一遍。 例如: ``` 给白狐配声音,录音在 ~/Downloads/baihu.m4a,里面说的是:"今晚的酒不错,坐下来喝一杯吧。" ``` 路径要写绝对路径,可以用 `~/` 开头;相对路径会被拒绝。mp3、m4a 等格式在 Mac 上会自动转成 wav。转不了的话,先手动转一下: ```bash afconvert -f WAVE -d LEI16@24000 -c 1 输入文件 输出.wav ``` 登记成功后,如果语音服务正在运行,会用新声音念一句"你好,这是我现在的声音。"让你听一下。服务没启动也没关系,声音已经存好了,启动后再听。角色已经有声音时,会先弹卡片让你确认是否覆盖。 ### 办法二:没有录音,让掌柜设计一个 对掌柜说想给某个角色设计声音。他会拿角色卡里 `voice` 一栏的描述(年龄感、音色、语速、语气),加上你的补充,再配一句符合角色口吻的试听台词,生成三段试听给你选。`voice` 栏是空的,他会先和你商量出一句描述。 先决条件: - 语音服务已经启动(先 `/aha 语音 启动`)。 - 这台机器是苹果芯片的 Mac,服务是插件代为启动的(`launch: mlx`)。 过程: 1. 第一次用要下载设计模型(约 2.9GB),会先弹卡片让你确认。设计时内存占用约 5GB,加载时峰值约 10GB。从确认到出现试听卡片,第一次大约要等一两分钟(含下载),期间界面上没有进度提示。 2. 三段试听以卡片的形式给出,每段可以反复听。不满意可以选"重新生成",用同样的描述再来一批(最多重新生成两次)。 3. 选好一段,点"用这一段",它就成了角色的声音。点"取消"则保持原样。 4. 设计结束后,语音服务会自动重启一次,用来释放内存。 不管用哪个办法,声音都存在角色文件夹里:`characters/<角色名>/voice_ref.wav` 和 `voice_ref.txt`(录音和录音里说的话)。想换声音,重新配一次,或者直接替换这两个文件,要换就一起换。 ## 5. 聊天时怎么用 单聊、群聊里都可以: ``` /aha 朗读 ``` 念上一条角色的回复。要念别的话: ``` /aha 朗读 今晚的月色真好 ``` 停下来: ``` /aha 朗读 停 ``` **自动朗读**让角色每轮说完话就自己念: ``` /aha 朗读 开 /aha 朗读 关 ``` 开关按聊天记住,默认是关的。每场聊天各有各的开关,下次接着聊时还是上次的设置。你发出新消息时,上一段还没念完的朗读会被打断。 命令名也可以写成 `/aha 说话`、`/aha speak`,效果一样。 **念哪些字**由 `read` 决定: - `lines`(默认):只念台词。写在括号里的动作描写(`()`、`()`、`【】` 里的内容)、两边加了星号的动作(`*低头倒酒*`)都不念。 - `all`:整段都念,括号里的内容也念,只去掉图片行和 Markdown 标记。 想让动作不被念出来,就让角色把动作写在括号里。 **群聊里**:一轮回复里的旁白和各个角色的台词,按各自的声音分别念,依次播放。 - 旁白用随包自带的旁白声音。想换成自己的,在插件配置 `narratorVoiceDir` 指一个目录,里面放 `voice_ref.wav` 与 `voice_ref.txt`,约定和角色的声音一样。配置写法同使用指南"换主题"一节,加在 group 模式的 `aha-tavern` 的 `config` 里: ```yaml - id: aha-tavern name: aha-tavern config: mode: group narratorVoiceDir: /你的/旁白声音/目录 ``` - 没配声音的角色,那几段跳过不念,回执里会说明。 - `/aha 朗读` 不带文字时,念上一轮的全部内容。 - 自动朗读的开关和单聊一样。 **停顿**:两段要念的话之间,如果隔着没念出来的文字(括号里的动作)或者换了段,会停一会儿再念下一段,留时间给你看那些字。停多久跟没念出来的字数有关:隔着大约 12 个字时停 `pauseSeconds`(默认 2 秒);字多就停得久一些,最长 `pauseMaxSeconds`(默认 4 秒);字少就停得短一些,最短 `pauseMinSeconds`(默认 1 秒);中间是平滑过渡的。按默认值,3 个字约停 1.3 秒,6 个字约 1.6 秒,24 个字约 2.7 秒,40 个字约 3.2 秒;只是换了一段、中间没有跳过的字时约 1.4 秒。三个值都可以在 `services.yaml` 或设置页里改,要满足 最短 ≤ `pauseSeconds` ≤ 最长;`pauseSeconds` 设成 0 就完全不停。同一段话里连着的两句之间固定停 0.5 秒。停顿期间发新消息或 `/aha 朗读 停`,照样立刻停下。 **长度限制**:一次最多念约 1000 字,超出的部分不念,开始朗读时的回执会提示;单句超过 80 字会在逗号、顿号处切开再念;太短的句子会和相邻的句子并在一起。 `/aha 朗读` 不带文字时,最近一条回复没有可念的字(比如只有图片),会改念更早的一条;整场聊天都没有可念的,回执是"这场聊天里还没有角色的话可念。"。`/aha 朗读 <文字>` 给的文字里没有可念的字时,回执是"没有可念的字。"。 ## 6. 自检 自检不会调用聊天模型。 **`/aha 自检`**:状态行里有一段语音小结,常见的几种: - `语音 可用`:已配置、连得上、有播放器。 - `语音 未配置`:没找到 `services.yaml`,或里面没有 `voice.endpoint`。 - `语音 未启动`:配置没问题但连不上,可以用 `/aha 语音 启动`。 - `语音 启动中`:正在启动。 - `语音 不可用:没有播放器`。 **`/aha 自检 语音`**:弹出一张卡片,逐项列出:服务能不能连上、由谁启动、模型有没有加载、运行环境和模型有没有装好、播放器、当前角色有没有声音、最近一次朗读出了什么错。 - 全部通过时,卡片上有"试念一句",点了会真的念一句,最多等一分钟。 - 服务没启动、插件又能代为启动时,卡片上有"启动服务",走的流程和 `/aha 语音 启动` 一样。 - 有问题时,按提示改好,再点"重新检查"。 ## 7. 播放 声音是用系统自带的 `afplay` 播放的,Mac 上不用另装。其他系统需要 `ffplay`、`paplay`、`aplay` 之一。找不到播放器时,自检会写"没有找到播放器"。 合成好的声音文件先放在系统临时目录,念完就删,不会留在酒馆里。 ## 8. 别的平台,或者用自己的语音服务 Windows、Linux 上,插件不能代为启动。你自己部署一个语音服务,然后让插件连上它: ```yaml voice: endpoint: http://你的服务地址:端口 launch: none model: 你的服务里的模型名 ``` 服务需要是 OpenAI 兼容的,并且支持: - `GET /v1/models`:用来探测服务是否在线。 - `POST /v1/audio/speech`:合成语音。请求里会带 `model`、`input`(要念的句子)、`lang_code`、`response_format`(固定 `wav`)、`stream`(固定 `false`,不用流式)、`max_tokens`,以及克隆声音用的 `ref_audio`(参考录音的路径)和 `ref_text`(录音里说的话)。返回完整的 wav 音频。 注意:`ref_audio` 传的是**本机文件路径**,所以语音服务要能读到 DSH 所在机器上的文件。服务在别的机器上时,要做好共享,或者让两边路径一致。 用自己的服务时,`/aha 语音 启动`、`/aha 语音 停止` 不管用(插件只管自己启动的服务),音色设计也用不了,只能用办法一自备录音。 ## 9. 常见问题 **连不上。** 先 `/aha 语音 状态` 看服务有没有在运行。没有就 `/aha 语音 启动`。端口被另一个语音服务占着时,启动会提示换一个端口;被别的程序占着时,回执是"语音服务启动后马上退出了",`server.log` 里能看到端口绑定失败。两种情况都是改 `endpoint` 里的端口。 **启动超时或马上退出。** 看语音目录下的 `server.log`(默认 `~/.dsh/aha-tavern/voice/server.log`),最后几行通常写明了原因。常见的是内存不够、端口冲突、模型没下载完整。 **下载慢,或者中断了。** 在 `services.yaml` 里设 `hfEndpoint` 为一个你能访问的镜像,再重新 `/aha 语音 启动`。已经下载的部分会续传。 **提示没有找到 uv。** 先装 uv(官方安装方法见上面的链接),装好后重开 DSH,让它能在 PATH 里找到。 **念出来的声音很怪。** 先核对角色的录音文字(`voice_ref.txt`)和录音是不是逐字一致,有没有少字、错字、多字。再看录音是不是太长(超过 15 秒)、背景有没有杂音或者不止一个人。重新配一次声音通常能解决。还不行,试试把 `model` 换成 `1.7b`。 **听不到声音。** 先 `/aha 自检 语音` 看播放器、角色的声音和服务都是否正常,再点"试念一句"。确认系统音量、输出设备没问题。自动朗读如果没反应,用 `/aha 朗读 开` 确认开关是开的。 **内存不够。** 加载模型时峰值约 9GB,先关掉别的大应用再启动;稳定运行之后会降到 2.2GB 左右(0.6B)。用 `model: 0.6b` 比 `1.7b` 省内存。音色设计时约占 5GB、峰值约 10GB,设计完服务会自动重启释放。 **想彻底不要语音。** 删掉 `voice` 这一节,或者 `/aha 语音 停止` 后不再启动。