一周时间,把「还得东拼西凑」改成「一条命令开聊」 - 张善友

一周时间,把「还得东拼西凑」改成「一条命令开聊」 - 张善友

💡 原文中文,约3300字,阅读约需8分钟。
📝

内容提要

作者反思C#语音项目需用户自行拼凑模型的问题,随后加入固定commit的模型清单与跨平台下载脚本,支持哈希校验、断点续传和镜像回退;让local与serve启动前自动准备并校验模型,修复Docker容器化,默认STT换为SenseVoice,实现一条命令跑通。

🔎

延伸解读

固定 commit 清单:让模型版本不再漂移

作者将五组模型权重统一记录在 models.tsv 中,每行包含 SHA-256、字节数、相对路径和带固定 commit 的下载地址。运行时永远不解析 main 或 master,这意味着上游仓库更新权重时,本地管线行为不会被动改变。对于依赖多个上游模型的项目,这种锁定版本的做法能避免“昨天还能跑,今天就不行”的隐性故障,也让问题复现和差异追踪有据可依。

启动前校验:把静默失败变成明确报错

此前 local 命令在缺模型时仍会启动服务,客户端连接后永远收不到事件,看起来像客户端 bug,实际是服务端在连接构建期悄悄拒绝。现在 local 和 serve 都会在监听前计算所需模型组,只下载缺失或哈希不对的文件,全部校验通过才绑定端口。自定义模型路径缺文件也会在监听前明确报错,不会静默用默认值顶替。这种“先算账再启动”的逻辑,把排查成本从用户侧移回了程序内部。

镜像回退与许可提醒:下载便利不等于授权

针对国内网络环境,作者没有改动清单,而是增加 S2S_MODEL_MIRROR 环境变量,让 huggingface.co 地址先走镜像,拉不动自动回落源站,断点续传两边保留。这降低了“一键下载”对网络条件的依赖。同时文章明确提醒:SenseVoice 权重受 FunASR Model License 约束,并非 Apache-2.0,清单里每个模型许可各不相同,下载不代表授权,商用前需自行核对。

容器化修正与遗留问题:一条命令背后的边界

原 compose 文件要求宿主机另跑 llama.cpp 服务,容器才能工作,作者认为这不算真正的容器化。现在 entrypoint 先跑下载器,五组默认模型约 6.84 GB 落入 named volume,校验通过才 exec 启动 serve,下载失败容器非零退出。文章也交代了未完成项:NuGet 不打算发布,Qwen3-TTS 在 CPU 上整句合成、被打断仍会合成完,真人麦克风听感未系统测试,下载脚本帮助里镜像说明重复打印待修。

❓

Q&A

speech-to-speech-dotnet 项目之前为什么被说成“还得东拼西凑”?

因为项目需要用户自行从 Hugging Face 上找齐五份模型权重(VAD、Whisper、GGUF、TTS 二十几个文件、Smart Turn),README 只写了“不下载,只指路”,没有提供自动下载方式。

现在如何解决模型分散下载的问题?

仓库内放置了固定 commit 的模型清单 tools/models/models.tsv,并提供了 download-models.ps1 和 download-models.sh 两个脚本,支持按清单下载、哈希与大小校验、断点续传,依赖仅 curl 和 sha256 工具。

local 命令之前缺模型时为什么服务能启动但收不到事件?现在怎么修复的?

之前服务在连接构建期悄悄拒绝,导致客户端连上但无事件。现在 local 在监听前会检查所选后端需要的模型组,缺失或哈希不对则自动下载并校验,全部通过才绑定端口;自定义模型路径缺失会明确报错。

Docker 容器化做了哪些改进?

entrypoint 在启动前先运行下载器,将五组默认模型(约 6.84 GB)下载到 named volume 并校验,通过后才 exec 启动 serve;下载失败容器非零退出。LLM 改回容器内本地 GGUF,不再依赖宿主机服务。

默认的语音识别模型换成了什么?有什么好处?

默认 STT 从 whisper-base 换成了 SenseVoice(sherpa-onnx 多语种导出,int8 约 228.5 MiB),中文识别质量更好;Paraformer 也加入清单。想换回 Whisper 可用 --stt whisper。

国内网络环境下如何加速模型下载?

设置环境变量 S2S_MODEL_MIRROR=https://hf-mirror.com 后,所有 huggingface.co 地址优先走镜像,镜像失败自动回退源站,断点续传保留,ModelScope 地址不受影响。

现在从零开始运行项目的步骤是什么?

依次执行:git clone 仓库、cd 进入目录、dotnet build SpeechToSpeech.slnx、dotnet run --project src/SpeechToSpeech.Cli -- local。local 会自动下载模型、校验、启动服务并打开麦克风。

项目还有哪些已知限制或未完成事项?

不发布 NuGet 包;Qwen3-TTS 在 CPU 上整句合成,被打断时仍会合成完(D001);真人麦克风听感未系统测试;下载脚本帮助中镜像说明打印了两遍,下轮修复。

🏷️

标签

➡️

继续阅读