Hugging Face Speech-to-Speech:把语音 Agent 完整跑在本地

如果你想给产品加上实时语音对话,最先遇到的问题通常不是 “大模型够不够聪明”,而是整条链路怎么接:什么时候判定用户说完了,音频如何转文字,模型怎样流式回答,合成语音又如何尽快开始播放。任何一环多等几百毫秒,对话都会显得迟钝。

今天 GitHub Trending 上的 huggingface/speech-to-speech,正是为这类问题准备的开源方案。项目目前约有 9.4k stars,当天新增超过 600 stars。它把语音 Agent 拆成清晰、可替换的模块,并通过兼容 OpenAI Realtime 的 WebSocket API 对外提供服务。

它解决的不是一个模型,而是一条链路

语音 Agent 常见的工程方案是一条级联流水线:

1
2
3
4
5
6
麦克风音频
→ VAD 判断说话起止
→ STT 转成文字
→ LLM 生成回答或工具调用
→ TTS 合成语音
→ 扬声器播放

自己从零拼装时,开发者还要处理线程、队列、流式数据、打断、会话历史和网络协议。speech-to-speech 已经把这些基础设施组织好。四个主要组件各自运行在线程中,通过队列衔接,既能流式传递中间结果,也能独立替换后端。

项目默认使用 Silero VAD v5 判断语音边界,Parakeet TDT 做语音识别,OpenAI 兼容接口连接语言模型,Qwen3-TTS 生成语音。默认组合只是起点,并不会把应用锁死在某一家模型或云服务里。

这套后端也不只停留在演示阶段。仓库说明它已经用于数千台 Reachy Mini 机器人的对话后端,这比单纯展示一段录音更能说明工程成熟度。

五个值得关注的核心能力

1. STT、LLM、TTS 都能替换

项目最大的价值是模块化。语音识别可选择 Parakeet TDT、Whisper、Faster Whisper、Lightning Whisper MLX 或 Paraformer;语言模型可接 OpenAI 兼容服务、Transformers、vLLM、llama.cpp 或 MLX;语音合成则支持 Qwen3-TTS、Kokoro、Pocket TTS、ChatTTS 和 MMS。

这意味着你可以按场景组合:中文客服选择 Paraformer 与 Qwen3-TTS,Mac 本地实验选择 MLX 后端,服务器部署则使用 CUDA 版本的识别和合成模型。

2. 兼容 OpenAI Realtime API

服务默认暴露:

1
ws://localhost:8765/v1/realtime

已有的 OpenAI Realtime 客户端可以直接接入,应用层无需理解每个底层模型的接口差异。以后从云端模型切到本地模型,客户端也不必大改。这一点把它与 “若干模型脚本拼在一起” 的示例项目区分开了。

3. 支持完全本地运行

STT、LLM 和 TTS 都可以放在自己的机器上运行。音频、转写和对话内容不必发送给第三方 API,适合对隐私敏感的业务,也能减少按分钟或按 token 计费带来的长期成本。

本地运行并不代表零成本。模型下载、显存、内存、散热和延迟都需要评估,但至少部署位置和模型选择掌握在自己手里。

4. 同时照顾 macOS、CPU 与 CUDA

Apple Silicon 可以使用 MLX 版的 Parakeet、Whisper、语言模型和 TTS;Linux 服务器可以走 CUDA;没有独立显卡时也有 CPU 后端可选。项目还为常见 CUDA 版本提供对应的 Qwen3-TTS wheel,降低环境不匹配的概率。

5. 不只有一种运行模式

realtime 模式提供标准 WebSocket API;local 模式直接使用本机麦克风和扬声器;websocketsocket 模式适合自定义轻量客户端或远程部署。先用本地模式验证模型组合,再切到 Realtime API 接产品,是比较稳妥的路径。

五分钟跑起第一个语音 Agent

项目要求 Python 3.10 以上。最简安装方式是:

1
2
3
python -m venv .venv
source .venv/bin/activate
pip install speech-to-speech

如果 LLM 使用 OpenAI 兼容服务,设置密钥后启动:

1
2
export OPENAI_API_KEY="你的密钥"
speech-to-speech

服务会监听 ws://localhost:8765/v1/realtime。另开一个终端,使用仓库自带的监听与播放脚本连接:

1
2
3
python scripts/listen_and_play_realtime.py \
--host 127.0.0.1 \
--port 8765

想让 LLM 也完全本地化,可以先启动 llama.cpp:

1
2
3
4
5
6
llama-server \
-hf ggml-org/gemma-4-E4B-it-GGUF \
-np 2 \
-c 65536 \
-fa on \
--swa-full

再让语音流水线连接本地 OpenAI 兼容端点:

1
2
3
4
speech-to-speech \
--model_name "ggml-org/gemma-4-E4B-it-GGUF" \
--responses_api_base_url "http://127.0.0.1:8080/v1" \
--responses_api_api_key ""

在 Apple Silicon 上,可以先尝试项目提供的本地优化配置,再根据内存容量调整模型。正式接入产品前,建议分别记录 VAD 判停、STT 首字、LLM 首 token 和 TTS 首包的耗时。只看总耗时,很难判断瓶颈究竟在哪里。

与同类方案的差异

端到端 speech-to-speech 模型直接从音频生成音频,理论上能减少中间环节,并保留更多语气信息,但模型选择、可观测性和文字级控制通常更弱。speech-to-speech 采用级联架构,每一步都能查看输出、替换模型和单独调优,更适合需要工具调用、审计记录或精确话术控制的应用。

Pipecat、LiveKit Agents 等框架也能构建实时语音 Agent,它们更偏向完整的通信与 Agent 编排生态。Hugging Face 这个项目的特点是紧贴开源模型生态,重点解决本地模型组合与 OpenAI Realtime 兼容问题。若你需要电话网络、多人房间或复杂媒体传输,成熟 RTC 框架可能更合适;若目标是快速测试不同开源 STT、LLM、TTS 的组合,它会更直接。

适用场景

它适合以下几类项目:

  • 在机器人、智能硬件或展台中加入自然语音交互;
  • 构建不上传录音的本地知识库助手;
  • 为客服、预约、问答系统验证语音原型;
  • 比较不同 STT 与 TTS 模型的速度、语言覆盖和音质;
  • 用统一 Realtime API 封装公司内部的语音模型服务。

使用前要知道的限制

级联方案会累积各阶段延迟,STT 的识别错误还会继续影响 LLM。嘈杂环境、多人同时说话、方言和频繁打断,都需要真实音频测试,不能只在安静房间里验收。

依赖组合也要留意。仓库明确提示 DeepFilterNet 需要 numpy<2,而 Pocket TTS 需要 numpy>=2,两者会发生版本冲突。Qwen3-TTS 的预编译 wheel 还与 CUDA 版本有关。生产部署最好固定 Python、CUDA、模型版本和 lockfile,不要每次启动都安装最新版。

全本地运行也不等于低配置运行。较大的 LLM 与 TTS 同时占用显存时,可能需要量化、拆分到不同设备,或保留云端 LLM 作为折中方案。

总结

Hugging Face Speech-to-Speech 的吸引力不在于发明了新的语音模型,而在于把 VAD、STT、LLM、TTS 和实时协议整理成一条可运行、可替换、可部署的工程流水线。

如果你正在做语音 Agent,先用它跑通默认配置,再逐项替换模型并测量各阶段延迟,比一开始就自己处理所有音频和并发细节更省时间。对于重视隐私、希望控制成本,或需要在 Apple Silicon 与本地服务器上实验开源模型的团队,它值得加入技术选型清单。

项目地址:https://github.com/huggingface/speech-to-speech