go2rtc 的 Wyoming 集成指南:用 Home Assistant 打造本地语音助手
2026/9/14 11:11:38 网站建设 项目流程

go2rtc 的 Wyoming 集成指南:用 Home Assistant 打造本地语音助手

【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc

导读

本文围绕 go2rtc 的 Wyoming 模块(internal/wyoming/README.md)展开,讲解如何将 go2rtc 作为 Wyoming Satellite、Wyoming External Microphone / Sound 接入 Home Assistant 语音助手流水线,覆盖典型语音链路、配置项(listen/name/wake_uri/vad_threshold/mode/event)、基于 expr 的事件脚本编程以及多种端侧部署示例。读完本文,你将掌握用任意支持 PCM(含 PCMA/PCMU)的音频源与支持双向音频(backchannel)的播放源搭建本地语音助手,并用脚本引擎自定义唤醒、TTS 播放等行为。注意:该模块仍处于开发中,官方文档声明格式尚不稳定("The format is under development and does not yet work stably"),生产使用前请谨慎验证。

Wyoming 是什么

Wyoming 是 Home Assistant 生态中用于本地语音助手的通信协议(Home Assistant 官方集成见wyoming集成页)。go2rtc 通过 internal/wyoming/wyoming.go 注册wyoming://协议并启动 TCP 服务端,使 go2rtc 能扮演以下角色:

  • Wyoming Satellite:完整的卫星端,把麦克风音频上送 Home Assistant,并把 TTS 音频回放出来;
  • Wyoming External Microphone:仅提供麦克风输入(mode: mic);
  • Wyoming External Sound:仅提供音频回放(mode: snd);
  • 任何支持 PCM 编解码(含 PCMA/PCMU)的音频源都可以作为音频输入(MIC);
  • 任何支持双向音频(backchannel)且使用 PCM 编解码的源都可以作为音频输出(SND);
  • 桌面/服务器上的麦克风和扬声器可通过 FFmpeg(跨平台)或 Linux 下的 ALSA 源接入;
  • 行为可通过内置的脚本引擎(expr)自定义。

典型语音助手流水线

官方 README 给出的典型流水线为 7 个环节:

  1. 音频流(MIC)——任意支持 PCM(含 PCMA/PCMU)的音频源;
  2. 语音活动检测(VAD)
  3. 唤醒词(WAKE)——如 OpenWakeWord;
  4. 语音转文字(STT)——如 Whisper、Vosk;
  5. 对话智能体(INTENT)——Home Assistant 的 conversation 集成;
  6. 文字转语音(TTS)——如 Google Translate、Piper;
  7. 音频流(SND)——任意支持双向音频(backchannel)且使用 PCM(含 PCMA/PCMU)的源。

其中 WAKE/STT/INTENT/TTS 可以由 Home Assistant 聚合大量不同项目实现;而 MIC/SND 则可以利用 go2rtc 丰富的音视频源技术栈。也就是说,go2rtc 负责"麦克风进、扬声器出"这两端,中间的大脑由 Home Assistant 流水线完成。

配置详解

go2rtc.yamlwyoming配置段下,每个 key 对应一个已定义的 stream(流名),基本结构如下:

wyoming: stream_name_from_streams_section: listen: :10700 name: "My Satellite" # 可选:显示名称,缺省用 stream 名 wake_uri: tcp://192.168.1.23:10400 # 可选:WAKE 服务地址 vad_threshold: 1 # 可选:VAD 阈值(0.1 ~ 3.5)

配置项说明

配置项类型默认值说明
listenstringTCP 监听地址,如:10700,Home Assistant 据此连接
namestringstream 名卫星名称,会在 describe 响应中上报给 Home Assistant
wake_uristringWAKE(唤醒词)服务地址,tcp://host:port,可选
vad_thresholdfloat320VAD 阈值(0.1~3.5),可选;缺省为 0 时按"有声即触发"处理
modestringsatellitemic表示仅麦克风、snd表示仅回放、缺省为完整卫星
eventmap[string]string事件 → expr 脚本映射,用于自定义事件处理

参数底层实现

从 internal/wyoming/wyoming.go 可以看到配置解析结构;其中VADThreshold在传给服务端时被放大 1000 倍:int16(1000 * cfg.VADThreshold)(即 1.0 → 1000)。在 pkg/wyoming/satellite.go 的状态机中,处于stateWaitVAD时,若VADThreshold == 0s16le.PeaksRMS(chunk) > VADThreshold则认为检测到语音;注释还说明"测试显示超过 1000 的取值大概率是语音"——也就是说 1.0 是文档推荐的参考起点。VAD 的 RMS 计算实现在 pkg/pcm/s16le/s16le.go。

关于 WAKE 的关键行为:如果未配置wake_uri或无法连接 WAKE 服务,go2rtc 会把所有音频直接转发给 Home Assistant,此时唤醒词必须由 Home Assistant 侧的 Voice Assistant 流水线自己完成。若配置了wake_uri,go2rtc 只有在检测到 VAD 语音后才开始向 WAKE 服务发送音频,唤醒成功后触发后续流水线。

关于音频格式的前提:接入的 stream 必须能提供 PCM 音频(含 PCMA/PCMU)。go2rtc 会在 pkg/wyoming/satellite.go 中把接收到的任意音频轨道通过pcm.TranscodeHandler(见 pkg/pcm/handlers.go)统一转码为 16 kHz、单声道、16 位 PCM(CodecPCML),并按 20ms 一包(2 * 16000 / 50)重组后上送;回放方向则按 22050 Hz 的 PCM 处理(见 pkg/wyoming/snd.go)。

在 Home Assistant 中添加集成

  1. Home Assistant → 设置(Settings)→ 设备与服务(Integrations)→ 添加集成(Add)→Wyoming Protocol
  2. 填写主机(Host)与端口(Port),即go2rtc.yamllisten配置的地址;
  3. 连接后即可选择语音助手流水线。

选择多个唤醒词

默认情况下,wake_uri未携带name参数时,go2rtc 会请求名为ok_nabu_v0.1的默认唤醒词(见 pkg/wyoming/wakeword.go)。可以通过在 URL 中追加多个name参数一次订阅多个唤醒词:

wake_uri: tcp://192.168.1.23:10400?name=alexa_v0.1&name=hey_jarvis_v0.1&name=hey_mycroft_v0.1&name=hey_rhasspy_v0.1&name=ok_nabu_v0.1

pkg/wyoming/README.md 中列出了这些默认唤醒词(alexa_v0.1、hey_jarvis_v0.1、hey_mycroft_v0.1、hey_rhasspy_v0.1、ok_nabu_v0.1),并提供了更多唤醒词模型资源的链接(wyoming-openwakeword、home-assistant-wakewords-collection、micro-wake-word-models 等)。从源码看,每个name参数会作为names列表通过detect事件下发给 WAKE 服务(pkg/wyoming/wakeword.go),唤醒成功后返回的detection事件会记录命中词名称,并触发internal-detection事件(pkg/wyoming/satellite.go)。

事件与脚本引擎

go2rtc 允许用 expr 脚本引擎(文档原链接为../expr/README.md,即仓库内 internal/expr/README.md)处理 Wyoming 事件。开启日志(log.wyoming: trace)可以观察实际发生的事件类型与数据。

官方提供的"默认脚本"如下(等价于 pkg/wyoming/expr.go 中handleEvent的默认行为):

wyoming: script_example: event: run-satellite: Detect() pause-satellite: Stop() voice-stopped: Pause() audio-stop: PlayAudio() && WriteEvent("played") && Detect() error: Detect() internal-run: WriteEvent("run-pipeline", '{"start_stage":"wake","end_stage":"tts"}') && Stream() internal-detection: WriteEvent("run-pipeline", '{"start_stage":"asr","end_stage":"tts"}') && Stream()

脚本中可用的函数与变量

  • Detect()—— 启动 VAD 与唤醒词检测流程(对应 pkg/wyoming/expr.go,内部把状态机置为stateWaitVAD);
  • Stream()—— 开始向客户端(Home Assistant)传输音频(置为stateActive);
  • Stop()—— 停止并断开音频流,但不断开客户端连接(pkg/wyoming/expr.go);
  • Pause()—— 暂停音频传输而不断开流(置为stateIdle);
  • PlayAudio()—— 播放客户端(Home Assistant)最近一次发来的音频(pkg/wyoming/expr.go);
  • WriteEvent(type, data)—— 向客户端(Home Assistant)发送事件;
  • Sleep(duration)—— 暂停脚本执行,如Sleep('1.5s')(pkg/wyoming/expr.go);
  • PlayFile(path)—— 播放wav文件的音频(pkg/wyoming/expr.go);
  • Type—— 事件类型(名称);
  • Data—— 事件数据,JSON 格式,如{"text":"how are you"}
  • 以及 expr 模块提供的其他函数(如fetchfromJSONtoJSONstring等)。

重要行为说明

  1. 覆盖即接管:如果你为某事件编写了脚本,该事件的默认动作将不再执行,需要自己补上必要的步骤;
  2. 两个额外事件
    • internal-run——Detect()之后 VAD 检测到语音、但 WAKE 服务不可用时触发(pkg/wyoming/satellite.go);
    • internal-detection——Detect()之后唤醒词被检测到时触发(pkg/wyoming/satellite.go);
  3. 同步执行PlayFilePlayAudio是同步执行的,后续步骤要等它们完成后才会继续。

事件脚本示例

示例 1:唤醒词命中时播放提示音(仅支持wav

wyoming: script_example: event: internal-detection: PlayFile('/media/beep.wav') && WriteEvent("run-pipeline", '{"start_stage":"asr","end_stage":"tts"}') && Stream()

示例 2:在 Home Assistant 媒体播放器上播放 TTS

每个事件都带Type和 JSON 格式的Data,可在脚本中取用:

  • synthesize(TTS 开始)步骤中读取text字段,调用 HA 的 REST API 让指定媒体播放器发声;
  • audio-stop(TTS 结束)步骤中读取 TTS 时长(秒),等待该时长后重新启动流水线。
wyoming: script_example: event: synthesize: | let text = fromJSON(Data).text; let token = 'eyJhbGci...'; fetch('http://localhost:8123/api/services/tts/speak', { method: 'POST', headers: {'Authorization': 'Bearer '+token,'Content-Type': 'application/json'}, body: toJSON({ entity_id: 'tts.google_translate_com', media_player_entity_id: 'media_player.google_nest', message: text, language: 'en', }), }).ok audio-stop: | let timestamp = fromJSON(Data).timestamp; let delay = string(timestamp)+'s'; Sleep(delay) && WriteEvent("played") && Detect()

部署示例

1. Windows 服务器上的卫星(FFmpeg + FFplay)

用 FFmpeg(dshow)采集 Windows 麦克风,用 FFplay 播放 22050 Hz 的 16 位 PCM 回放流(-#backchannel=1#audio=s16le/22050是 go2rtc 的双向音频语法):

streams: satellite_win: - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav - - exec:ffplay -hide_banner -nodisp -probesize 32 -f s16le -ar 22050 -#backchannel=1#audio=s16le/22050 wyoming: satellite_win: listen: :10700 name: "Windows Satellite" wake_uri: tcp://192.168.1.23:10400 vad_threshold: 1

2. 支持双向音频的大华(Dahua)摄像头作为卫星

摄像头自带的麦克风/扬声器(经 RTSP 双向音频)直接作为 MIC 与 SND,无需额外声卡设备:

streams: dahua_camera: - rtsp://admin:password@192.168.1.123/cam/realmonitor?channel=1&subtype=1&unicast=true&proto=Onvif wyoming: dahua_camera: listen: :10700 name: "Dahua Satellite" wake_uri: tcp://192.168.1.23:10400 vad_threshold: 1

3. 使用外部 Wyoming 麦克风与声音组件作为卫星

由 wyoming-mic-external / wyoming-snd-external 提供音频,go2rtc 聚合二者成为一个卫星:

streams: wyoming_external: - wyoming://192.168.1.23:10600 # wyoming-mic-external - wyoming://192.168.1.23:10601?backchannel=1 # wyoming-snd-external wyoming: wyoming_external: listen: :10700 name: "Wyoming Satellite" wake_uri: tcp://192.168.1.23:10400 vad_threshold: 1

作为 Wyoming External Microphone / Sound

想单独使用 rhasspy 的 wyoming-satellite 项目的进阶用户,可以让 go2rtc 只承担"外部麦克风"或"外部声音"角色。服务端根据mode参数分发到HandleMic/HandleSnd(internal/wyoming/wyoming.go)。

go2rtc.yaml

streams: wyoming_mic_external: - exec:ffmpeg -hide_banner -f dshow -i "audio=Microphone (High Definition Audio Device)" -c pcm_s16le -ar 16000 -ac 1 -f wav - wyoming_snd_external: - exec:ffplay -hide_banner -nodisp -probesize 32 -f s16le -ar 22050 -#backchannel=1#audio=s16le/22050 wyoming: wyoming_mic_external: listen: :10600 mode: mic wyoming_snd_external: listen: :10601 mode: snd

docker-compose.yml(运行 wyoming-satellite 并分别连接两个 go2rtc 端口):

version: "3.8" services: satellite: build: wyoming-satellite # https://github.com/rhasspy/wyoming-satellite ports: - "10700:10700" command: - "--name" - "my satellite" - "--mic-uri" - "tcp://192.168.1.23:10600" - "--snd-uri" - "tcp://192.168.1.23:10601" - "--debug"

作为 Wyoming External Source

反过来,go2rtc 也能通过wyoming://协议把外部的 wyoming-mic-external / wyoming-snd-external 当作普通音视频源接入自己的 stream(协议注册与backchannel=1参数解析见 pkg/wyoming/wyoming.go,backchannel 模式实现见 pkg/wyoming/backchannel.go)。

go2rtc.yaml

streams: wyoming_external: - wyoming://192.168.1.23:10600 - wyoming://192.168.1.23:10601?backchannel=1

docker-compose.yml(以 Docker 运行 mic 与 playback 两个外部组件并暴露端口):

version: "3.8" services: microphone: build: wyoming-mic-external # https://github.com/rhasspy/wyoming-mic-external ports: - "10600:10600" devices: - /dev/snd:/dev/snd group_add: - audio command: - "--device" - "sysdefault" - "--debug" playback: build: wyoming-snd-external # https://github.com/rhasspy/wyoming-snd-external ports: - "10601:10601" devices: - /dev/snd:/dev/snd group_add: - audio command: - "--device" - "sysdefault" - "--debug"

调试

开启 wyoming 模块的 trace 日志即可观察事件收发与脚本执行情况:

log: wyoming: trace

在源码中,服务端通过Trace/Error回调输出日志(internal/wyoming/wyoming.go),脚本执行时也会打印event=... data=... payload size=...以及脚本求值结果或错误(pkg/wyoming/expr.go),方便排查事件类型与数据格式。

协议与源码导读

Wyoming 协议采用"JSON 头 + 换行 + 可选数据/负载"的帧格式:头部含typeversiondata_lengthpayload_length字段,实现于 pkg/wyoming/api.go,协议版本号Version = "1.5.4"。事件类型如describerun-satellitedetectaudio-startaudio-chunkaudio-stop等在 pkg/wyoming/expr.go 中都有注释标明其 Home Assistant 侧语义。卫星状态机(stateNewstateIdlestateWaitVADstateWaitWakeWordstateActive,见 pkg/wyoming/satellite.go)是整个模块的核心:VAD 过滤 → 唤醒词确认 → 音频上送 Home Assistant → 回放 TTS。有兴趣深入的朋友可以从 internal/wyoming/wyoming.go 的Init()入口、pkg/wyoming/satellite.go、pkg/wyoming/wakeword.go 三个文件开始阅读。

【免费下载链接】go2rtcUltimate camera streaming application项目地址: https://gitcode.com/GitHub_Trending/go/go2rtc

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询