Files
note_sync/有趣的项目/AI桌面陪伴助手/P0-Qwen3TTS报告.md
T
ylhan bdd6bfb63d AI桌面陪伴助手:方案更新至 v2.4,代码剥离到独立仓库
代码剥离
- 助手本体、TTS 服务、P0 基准脚本、ESP32 固件移到 ~/workspace/ai-companion
  (独立 git 仓库),本目录只留方案、P0 报告与硬件记录
- 因此删除 esp32_smile_test.ino / esp32_touch_eyes.ino
- 同时移除已失效的 .gitignore(原本只为挡住模型体积,代码已搬走)

方案 v2.4 重大变更:架构从"单机"改为"服务器即助手、本地为客户端"
- 起因:实测 N5095 无 AVX2,跑不动可用的语音模型
- N5095 降为客户端/外设桥,只做 USB 接入、DoA、WebRTC 客户端
- 实施阶段表加进度列(P0/P1/P3/P4a 部分完成),新增三条验收要求
- 采购清单按实际到货更新,标出屏幕形态待确认(2.8寸 vs 原定1.28寸圆屏)

技术栈(实测更新)
- LLM:DeepSeek deepseek-flash(云端,必须关思考);本机 27B 已停用
- TTS:Qwen3-TTS 1.7B(服务器 3090);vits-zh-ll 因音色不满意被替换
- STT:Zipformer int8 未变,中文识别率仍是未闭合项

新增两份 P0 报告
- P0-Qwen3TTS报告.md:TTS 换型过程与实测
- P0-DeepSeek验证报告.md:四条路径验证

两份旧报告加了状态说明(结论仍有效但选型已变),
并修正了随代码移走而失效的引用与复现命令。
2026-09-15 11:08:56 +08:00

5.7 KiB
Raw Blame History

P0 报告 · Qwen3-TTS 选型与部署

日期:2026-09-15。起因:用户试听后反馈 vits-zh-ll 音色不满意, 要求换"体量更大效果更好的模型",并提出 LLM 可以用线上 API、 把 GPU 让给语音。

服务:~/tts-qwen/(服务器)· 模型:~/tts-service/models/Qwen3-TTS-1.7B-CustomVoice

一、为什么选 Qwen3-TTS

查证后的结论(来源见文末):

  • 实时对话场景的首选是 Qwen3-TTS 或 CosyVoice 2/3; IndexTTS2 和 F5-TTS 虽然中文指标也强,但流式不是它们的目标,不做实时助手首选
  • Qwen3-TTS 官方标称流式首包 97ms,RTX 3090 上实测约 130ms
  • 官方推荐硬件就是 RTX 3090/4090 24GB,与现有硬件吻合
  • Apache-2.0,10 种语言 + 中文方言
  • 9 个预置音色 + 自然语言风格指令(这是 vits 那一代没有的能力)

二、部署路上撞到的两个障碍

障碍 1:vLLM-Omni 装不起来能用的服务

原本的打算是走 vLLM-Omni(它提供 OpenAI 兼容的流式 /v1/audio/speech 分块接口,是延迟最优的路径)。两个问题叠加:

  1. --task-type 参数没被注册。vllm-omni 把 CLI 扩展注册在 vllm.general_plugins,但 vllm 0.28 的 serve 解析器没加载它, vllm-omni serve --help 里根本看不到这个参数。
  2. 绕过后仍崩溃。模型架构能正确识别 (Resolved architecture: Qwen3TTSForConditionalGeneration), 但 vLLM 因为模型 config 里的 mrope 参数 (transformers 5.14 报 Unrecognized keys in rope_parameters: {'interleaved', 'mrope_section'})把它当多模态模型走 mm 路径, 崩在 assert isinstance(model, SupportsMRoPE)。

根因是 transformers / vllm / vllm-omni 三者的版本组合问题, 不是配置错误。没有继续深挖。

障碍 2:qwen-tts 与 vllm-omni 依赖互斥

改用厂商自己的 qwen-tts 包后,发现它会把 transformers 从 5.14.1 降到 4.57.3、huggingface_hub 从 1.31.0 降到 0.36.2, 直接破坏 vllm-omni(报 StrictDataclassFieldValidationError)。

结论:两者不能共存于一个 venv。 最终分两个 venv, TTS 跑独立进程,助手通过 HTTP 调用。

三、实测数据

硬件:RTX 3090 24GB,1.7B 模型,非流式,Serena 音色。

文本 音频时长 合成耗时 RTF
好的,我记住了。(8字) 1.52s 1429ms 0.94
今天北京晴转多云…(19字) 3.36s 1881ms 0.56
我查了一下,明天上午…(26字) 4.64s 2527ms 0.55

关键发现:短句 RTF 反而最差。 每次调用有约 1 秒的固定开销,与文本长度无关 (talker 模型自回归解码的启动成本 + 声码器解码)。

这条推翻了"让模型先说个短句来降低首音延迟"的直觉—— 短句单位时间成本更高,反而不划算。

输出:24kHz 单声道(vits-zh-ll 是 16kHz,接播放链路时注意重采样)。

四、用户选定的配置

试听样本见 out/tts_qwen/。用户选定:

音色:Serena —— 温暖柔和的年轻女声
指令:用轻快活泼的语气说

(instruct_7849.wav,1.44s。通过时长比对确认对应关系: 默认 2.56s、轻快活泼 1.44s、温柔关切 1.72s。)

9 个预置音色中 5 个是中文: Vivian(明亮微冷)、Serena(温暖柔和)、Uncle_Fu(低沉男声)、 Dylan(京腔男声)、Eric(成都话男声)。

五、代价:首音延迟涨了 8.6 倍

配置 首音延迟
本地 Qwen3.8-27B + vits-zh-ll 179 ms
DeepSeek + Qwen3-TTS 1545 ms

拆解这 1545ms:DeepSeek 网络往返约 600ms + Qwen3-TTS 固定开销约 900ms。

加上 VAD 判定(200–500ms),总首音落在 2.0–2.2 秒, 方案 P1 目标是 P50≤2 秒——刚好卡线,没有余量。

换来的是音质从"用户不满意"到"用户试听选定"。

六、速度还能救,但都受阻

手段 预估收益 障碍
flash-attn 1.5–2× 预编译 wheel 最高支持 torch 2.9,本机 2.14;源码编译要从 GitHub 拉依赖而该机下 GitHub release 断连
真流式(接管 codes→音频 解码循环) 可绕开约 900ms 固定开销 qwen-tts 封装把解码放在全部 codes 生成完之后,拿不到增量;要自己实现
降 torch 版本装 flash-attn 1.5–2× 会牵动 vLLM 0.28 的依赖

真流式的收益最大——那 900ms 固定开销正是流式能覆盖掉的部分。 但工作量也最大。

七、备份路线(未采用)

若 Qwen3-TTS 的速度最终不可接受,可考虑的替代:

  • CosyVoice 2/3:同为实时对话第一梯队,Apache-2.0,工程成熟度最高, 18+ 中文方言。但搜索结果里首包延迟数据有冲突(150ms vs 1.5s),需实测。
  • 云端 TTS API:最快出效果,但助手要说的话会出网, 与方案"不自动发送音频到第三方"的口径有冲突(发的是文本不是音频, 但内容一样出网),且按量计费。

未测:CosyVoice 的本地部署与本机延迟。

八、来源