一条 serve 背后的 14 个默认参数,逐个说清楚

2026-08-09

装完 speech-to-speech,README 让你敲的第一条命令短得让人放心:

export OPENAI_API_KEY=...
speech-to-speech serve

然后 README 紧接着给了一条等价命令,把这条裸命令背后的默认值全摊开了——一共 14 个显式参数:

speech-to-speech serve \
    --thresh 0.6 \
    --stt parakeet-tdt \
    --llm_backend responses-api \
    --tts qwen3 \
    --qwen3_tts_model_name Qwen/Qwen3-TTS-12Hz-1.7B-CustomVoice \
    --qwen3_tts_speaker Aiden \
    --qwen3_tts_language auto \
    --qwen3_tts_backend ggml \
    --qwen3_tts_non_streaming_mode True \
    --qwen3_tts_mlx_quantization 6bit \
    --model_name gpt-5.4-mini \
    --chat_size 30 \
    --responses_api_stream \
    --enable_live_transcription

这 14 行不是摆设。它们决定了三件事:你的语音数据往哪儿走、你说中文能不能被识别、这台机器同时能接几个人。下面按功能分组拆,每组末尾我会说清楚「什么情况下你必须改它」。

第一组:VAD 的 --thresh 0.6

--thresh 是 VAD 的触发阈值,取值一般在 0–1 之间,值越高,越要求高置信度才判定为语音。默认 0.6。

值得注意的是,整条流水线的 VAD 参数一共有 19 个(都定义在 src/speech_to_speech/arguments_classes/vad_arguments.py 里),但这条等价命令只把 --thresh 拎了出来。剩下 18 个——--min_silence_ms(默认 64)、--min_speech_ms(默认 384)、--speech_pad_ms(默认 500)、--smart_turn(默认 True)之类——同样在生效,只是 README 认为它们不是你第一天该关心的东西。

判断依据:只有当你怀疑「它总在我还没说完就抢答」或者「我说了它没反应」时,才需要往 VAD 那一层深挖;只想把服务跑起来的话,这一整组保持默认就行。

第二组:--stt parakeet-tdt——中文用户第一个要改的

默认 STT 是 Parakeet TDT,对应模型 nvidia/parakeet-tdt-0.6b-v3。README 的多语言支持表写得很直白:这个默认 STT 覆盖的是 25 种欧洲语言

也就是说,任何要处理中文语音的场景,都必须换掉默认 STT——换成 Whisper 系或者 Paraformer(README 说 Paraformer 走 FunASR,默认偏中文)。README 给出的换法示例是这样的:

speech-to-speech serve \
    --stt whisper-mlx \
    --stt_model_name large-v3 \
    --language zh \
    --llm_backend mlx-lm \
    --model_name mlx-community/Qwen3-4B-Instruct-2507-bf16

顺带说一句 --language:README 明说它的默认值是 en。如果你想让它自动跟着说话人切语言,取值写 auto,STT 会把检测到的语言随转写一起交给 LLM;还有个可选的 --enable_lang_prompt(默认 False),打开后会追加一句 “Please reply to my message in …” 的指令。README 自己给了判断依据:大模型通常能从上下文推断该用哪种语言,但对小模型来说,这种显式指令往往有帮助

判断依据:母语场景决定 STT,模型大小决定要不要开 --enable_lang_prompt。这两件事互相独立,别混在一起调。

第三组:LLM 那四个——项目叫 local,默认却打云端

--llm_backend responses-api--model_name gpt-5.4-mini--chat_size 30--responses_api_stream,这四个参数合起来说的是一件事:开箱即用的这套「本地语音代理」,LLM 那一环默认走的是 OpenAI Responses API

仓库的一句话描述是 “Build local voice agents with open-source models”,但默认配置里真正在本地跑的只有 STT 和 TTS,LLM 默认打的是云端的 gpt-5.4-mini。第一条命令要你 export OPENAI_API_KEY=...,原因就在这里。这不是 bug,README 写得清清楚楚,但确实是最容易被标题带偏的一处。

其中 --chat_size 30 是保留的对话轮数(assistant-user 交互条数),--responses_api_stream 默认为 True,控制是否流式接收。

要把 LLM 也搬到本地,README 给了三条路:进程内本地推理(CUDA / CPU 用 --llm_backend transformers,Apple Silicon 用 --llm_backend mlx-lm)、指向自托管服务,或者换别的服务商。后两条共用同一组 --responses_api_* 连接参数,README 的对照表是这样的:

服务商 / 服务--responses_api_base_url--responses_api_api_key
OpenAI省略,用 OpenAI 默认$OPENAI_API_KEY
HF Inference Providershttps://router.huggingface.co/v1$HF_TOKEN
OpenRouterhttps://openrouter.ai/api/v1$OPENROUTER_API_KEY
vLLMhttp://localhost:8000/v1省略或任意字符串
llama.cpphttp://127.0.0.1:8080/v1空字符串

README 里「完全本地」那一节的做法是:另开一个终端跑 llama.cpp,然后让 speech-to-speech 指过去。

# 终端 1:llama.cpp 提供 Gemma 4
llama-server -hf ggml-org/gemma-4-E4B-it-GGUF -np 2 -c 65536 -fa on --swa-full
# 终端 2:speech-to-speech 指向这个本地服务
speech-to-speech serve \
    --stt parakeet-tdt \
    --llm_backend responses-api \
    --tts qwen3 \
    --model_name "ggml-org/gemma-4-E4B-it-GGUF" \
    --responses_api_base_url "http://127.0.0.1:8080/v1" \
    --responses_api_api_key "" \
    --responses_api_stream \
    --enable_live_transcription

这条命令还有个连带影响:想断网离线跑的话,不覆盖 base URL 就等于没离线。默认的 responses-api 后端会去调远程服务,HF_HUB_OFFLINE=1 拦不住它。README 的离线建议是,断网前先用完全相同的配置在联网状态下启动一次,让 STT、LLM、TTS、Silero VAD、NLTK 和 Smart Turn 需要的资源都缓存好。

判断依据:只要你的语音内容不能出内网,--model_name--responses_api_base_url 这两个就是必改项,改一个不够。

第四组:--tts qwen3 和它的六个参数,有几个在你这台机器上不生效

这一组是 --tts qwen3 加上它带出来的六个 Qwen3-TTS 参数,一共七行,占了这条等价命令的一半。--tts 本身只是选实现(默认 qwen3),真正容易看晕的是后面六个,因为它们同时列了两个平台的旋钮

参数默认值在哪个平台上说了算
--qwen3_tts_model_nameQwen/Qwen3-TTS-12Hz-1.7B-CustomVoice全平台
--qwen3_tts_speakerAidenCustomVoice 模型的音色名
--qwen3_tts_languageauto全平台,合成目标语言
--qwen3_tts_backendggml非 macOS;Apple Silicon 自动选 mlx-audio,该项被忽略
--qwen3_tts_non_streaming_modeTruefaster-qwen3-tts 上预填全文;Apple Silicon 上当前被忽略
--qwen3_tts_mlx_quantization6bitApple Silicon 上的量化覆盖项

读这张表的正确姿势是:先确认自己在哪个平台,再看哪几行与自己有关。在 Linux / Windows 侧,--qwen3_tts_backend ggml--qwen3_tts_non_streaming_mode True 是真在起作用的,而 --qwen3_tts_mlx_quantization 6bit 只是躺在那儿;到了 Apple Silicon 上正好反过来——后端自动是 mlx-audio,前两项被忽略,6bit 才是那个真旋钮。GGML 侧对应的量化项是另一个参数 --qwen3_tts_ggml_quantization,默认 BF16

顺带一句:不同后端的量化默认值不一样(GGML 侧 BF16、MLX 侧 6bit),这是两条不同的实现路径各自的默认,不是同一个东西的两种写法。

macOS 上还有个省事的做法是 --mac-optimal-settings 预设,它做四件事:对支持的组件用 MPS 默认值、STT 设为 Parakeet TDT、LLM 后端设为 MLX LM、TTS 设为 Qwen3-TTS 并走 mlx-audio 默认取 6bit 变体。优先级很容易搞反:预设只提供默认值,显式的 --device、组件级设备参数(如 --qwen3_tts_device)以及 --stt--llm_backend--model_name--tts 全部优先于预设。想暴露服务而不启动麦克风客户端时,把它用在 serve 而不是 local 上。

第五组:--enable_live_transcription,和一个名字几乎一样的参数

这是这 14 个里最容易写错的一个。模块级的 --enable_live_transcription 默认是 True,配合 parakeet-tdt 在用户说话过程中显示实时转写。而 VAD 那边还有一个 --enable_realtime_transcription,默认是 False

两个名字长得极像,默认值相反,归属文件也不同——一个在模块级参数里,一个在 vad_arguments.py 里。写脚本、写配置、写文档的时候,任何时候引用它们都值得回 --help 输出里核一遍拼写,因为它们互相不是别名。

三个没写进这条命令、却常常决定成败的默认值

等价命令展开的是流水线组件,但 Realtime 服务端自己还有几个默认值,它们不在这 14 个里:

  • --host 默认 127.0.0.1。help 原文的说法是:要把这个未鉴权的 API 暴露到网络上,得显式传 0.0.0.0
  • --port 默认 8765,默认服务地址是 ws://localhost:8765/v1/realtime。README 的 Docker 一节提到,docker compose up 会起一个跑 Gemma 4 的 llama.cpp 服务和实时服务,暴露 8080 与 8765 两个端口。
  • --num_pipelines 默认 1。help 写得很明确:一个 uvicorn 服务监听 --port,把每个进来的客户端路由到下一个空闲流水线,每条流水线有自己的 VAD / STT / LM / TTS handler 和会话状态;最大并发 WebSocket 会话数就等于 num_pipelines,再多的连接会被拒绝。默认 1 意味着默认只服务一个人。

另外还有个默认关着的 --enable_llm_proxy(默认 False)。这里必须原样带出官方口径:服务端自身不做认证、也不做限流--host 0.0.0.0 和 LLM proxy 这类开关只应在受信网络里或者放在网关之后启用。我们没有部署过它,也不会给你「这样配就安全了」的结论——这类判断只能结合你自己的环境做。

最后一句警告:默认值不是延迟

这套流水线的参数里有一堆毫秒值,很容易让人产生一个错觉:把它们加起来就是端到端延迟。不是。

那些毫秒数是流水线自己引入的、可配置的等待,不包含 STT 推理、LLM 首 token、TTS 首包这三段真正吃算力的时间——而后三段完全取决于你的模型和硬件,本文没有任何测量数据,也不会给估计值。README 自己的定性判断是:LLM 是流水线里计算最重、延迟最高的组件,一次前向就可能主导端到端响应时间,所以按硬件与延迟预算选后端很重要。这句话是文档观点,不是我们的实测结论。

还有一个行为值得提前知道:CLI 只为选中的后端构造配置,未激活后端的已知选项仍然被接受,只是带着警告被忽略。**所以你把某个后端专属参数写错了地方,程序不会报错停下,只会警告一声照跑。**自查方法是 speech-to-speech serve -h 看当前组合的默认值;想看另一种组合的参数,把选择器放在 -h 前面,比如 speech-to-speech serve --stt mlx-audio-whisper -h

以上组合命令均为按官方参数语义整理与引用,未逐项实测,以官方文档与 --help 的实际输出为准。

一张决策清单

回到最初那条 speech-to-speech serve,问自己三个问题就知道该动哪几个默认值:

  1. 要处理中文吗? 要 → 必改 --stt(Whisper 系或 Paraformer),并考虑 --language
  2. 语音内容能出内网吗? 不能 → 必改 --model_name--responses_api_base_url,指向本机的 vLLM 或 llama.cpp;打算离线跑就更要提前缓存一次。
  3. 不止一个人用吗? 是 → 必改 --num_pipelines,否则第二个连接直接被拒。

三个都是「否」的话,默认值确实可以直接用——前提是你接受 LLM 那一环走云端。

延伸阅读


本文依据 speech-to-speech 官方仓库(github.com/huggingface/speech-to-speech)的 README、 src/speech_to_speech/arguments_classes/ 下的参数定义与 Realtime Engine 架构文档整理,核对日 2026-08-09。 本文内容为仓库源码与文档口径,我们没有安装、部署或调用过该服务,文中毫秒值均为参数默认值而非实测延迟。 参数与默认值随版本变动,请以 speech-to-speech serve -h 的实际输出为准。

安全相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。