# OpenClaw 源码解读（7）： 跨平台语音唤醒实现机制

> 深入 OpenClaw 跨平台语音唤醒架构，解析从本地 VAD 检测、端侧唤醒词引擎到云端流式 ASR 的完整链路，以及多设备统一调度机制。

- 原文链接: https://laojin.blog/blog/20260317_openclaw_source_code_7
- 作者: 老金
- 发布日期: 2026-03-17
- 标签: OpenClaw, 源码解读, AI Agent, 开源项目

---

在前面的篇章中，我们解析了 OpenClaw 的路由、A2UI 和工具链。但作为个人 AI 助手，如果每次都要你掏出手机、打开 App、打字输入，那它充其量只是个“高级搜索引擎”。真正的助手，应该是在你做饭、开车或者敲代码时，只需喊一声，它就能随时待命。

语音交互（Voice UI）是通向 AGI 终极形态的必经之路。但跨平台语音开发是个大坑：macOS、iOS 和 Android 对麦克风权限和后台存活机制的管理完全不同。

今天，我们就来拆解 OpenClaw 的 Nodes（节点）架构，看看它是如何通过 TypeScript、Swift 和 Kotlin 的混编，实现全平台“唤醒与聆听”的。

---

## 语音流转核心：从声波到文字，再到声音

在 OpenClaw 中，所有的硬件设备（Mac、iPhone、安卓机）都被抽象为一个个“Node（节点）”。节点负责收集声音，而 Gateway（网关）负责大脑的思考和转化。

一次完整的语音交互流转如下：

1. **Node（端侧）：** 监听唤醒词 -> 录制音频 -> 通过 WebSocket 将音频流（PCM/WAV）推送到 Gateway。

2. **Gateway（云/局域网端）：** 调用 STT（Speech-to-Text，如 Whisper）将语音转为文字 -> 路由给 Agent -> Agent 生成回复文本。

3. **Gateway（云/局域网端）：** 调用 TTS（Text-to-Speech，如 ElevenLabs 或系统自带 TTS）生成音频流 -> 推送回 Node。

4. **Node（端侧）：** 播放音频。

我们看看 Gateway 是如何处理这段双向音频流的：

```typescript
// src/core/audio/VoicePipeline.ts (源码概念简化版)

import { STTEngine } from './stt';
import { TTSEngine } from './tts';

export class VoicePipeline {
  /**
   * 处理来自 Node 的音频流
   */
  public async handleNodeAudioStream(nodeId: string, audioBuffer: Buffer) {
    // 1. 语音转文本 (STT)
    const transcribedText = await STTEngine.transcribe(audioBuffer);
    
    // 2. 扔给 Agent 处理，获取回复文本
    const agentReply = await AgentManager.routeAndProcess(nodeId, transcribedText);
    
    // 3. 文本转语音 (TTS)，结合 ElevenLabs 实现高度拟人化的声音
    // 注意：这里通常采用流式 (Streaming) 处理来降低首字节延迟 (TTFB)
    const audioStream = await TTSEngine.synthesizeStream(agentReply, {
      voiceId: 'eleven_labs_molty_voice',
      model: 'eleven_turbo_v2'
    });
    
    // 4. 将音频流通过 WebSocket 发送回设备 Node 进行播放
    await GatewayServer.sendAudioToNode(nodeId, audioStream);
  }
}

```

---

## macOS/iOS：轻量级本地唤醒词机制

在苹果生态中，一直开着麦克风把音频传到服务器是不可行的（既耗电，又会被 iOS 的后台机制杀掉）。因此，OpenClaw 在 `apps/apple` 目录下，使用了约 8.9% 的 Swift 原生代码来实现一个**端侧轻量级唤醒监听器**。

端侧只负责一件事：在本地运行一个极小的离线模型（比如基于 Apple 框架或 Porcupine），专门监听唤醒词。

```swift
// apps/apple/OpenClawNode/Speech/WakeWordEngine.swift (源码概念简化版)

import AVFoundation
import Speech

class WakeWordEngine: ObservableObject {
    private let audioEngine = AVAudioEngine()
    private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
    
    func startListening() {
        let inputNode = audioEngine.inputNode
        let recordingFormat = inputNode.outputFormat(forBus: 0)
        
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
            // 本地极速分析音频帧，匹配唤醒词
            if self.detectWakeWord(in: buffer) {
                self.triggerGatewayWakeup()
                self.startRecordingCommand() // 唤醒后开始录制真正的指令
            }
        }
        
        try? audioEngine.start()
    }
    
    private func triggerGatewayWakeup() {
        // 通过 WebSocket 通知 Gateway：主人叫你了！
        WebSocketClient.shared.send(event: "NODE_WAKED", payload: ["nodeId": Device.currentId])
    }
}

```

通过 Swift 原生介入，Mac 和 iPhone 节点可以以极低的功耗在后台常驻。只有听到唤醒词的瞬间，才会打通与 TypeScript 编写的 Gateway 的高耗能长连接。

---

## Android 端侧：持续语音拾音逻辑（Talk Mode）

相比之下，安卓系统的开放性给了 OpenClaw 更多发挥空间。在 `apps/android` 目录下，OpenClaw 利用 2.1% 的 Kotlin 代码实现了一个非常硬核的“Talk Mode（持续对话模式）”。

在这个模式下，Agent 不再是一问一答，而是通过 **VAD（Voice Activity Detection，静音检测）** 算法，像真人打语音电话一样持续沟通。

```kotlin
// apps/android/OpenClawNode/audio/VADManager.kt (源码概念简化版)

class VADManager {
    private val threshold = -40.0 // 分贝阈值
    private var isSpeaking = false
    private val audioBufferChunk = mutableListOf<ByteArray>()

    fun processAudioFrame(frame: ByteArray, dbLevel: Double) {
        if (dbLevel > threshold) {
            // 用户正在说话
            if (!isSpeaking) {
                isSpeaking = true
                WebSocketClient.sendEvent("USER_SPEECH_START")
            }
            audioBufferChunk.add(frame)
        } else {
            // 检测到停顿 (例如超过 1.5 秒没有说话)
            if (isSpeaking && hasSilenceExceeded(1500)) {
                isSpeaking = false
                
                // 将刚才的一整段话打包发给 Gateway
                WebSocketClient.sendAudioStream(audioBufferChunk.toByteArray())
                audioBufferChunk.clear()
            }
        }
    }
}

```

在 Android 端的 Talk Mode 中，VAD 会自动切分你的句子。你停顿思考时，它就把前半句发给云端处理；你继续说，它就继续录。这种体验打破了传统语音助手“说完必须傻等”的僵硬感，实现了真正意义上的全双工（Full-duplex）对话流。

---

## 总结

跨平台开发不应该只是简单的套壳（Webview）。OpenClaw 为我们做了一个极佳的示范：

* **核心业务逻辑** 留在 TypeScript（Gateway）中，保证迭代速度与跨平台复用。

* **高频、底层、敏感的硬件交互**（如 iOS 的唤醒词、Android 的 VAD），果断采用 Swift 和 Kotlin 编写 Native Node，以获取系统级最高权限与最优性能。

正是这种“各司其职”的设计，让那只叫 Open Claw 的空间龙虾真正长出了灵敏的“耳朵”和拟真的“嘴巴”。

当我们用语音唤醒了设备之后，AI 还能对这台设备做些什么？仅仅是聊天吗？
敬请期待下一篇，老金带你看看 Agent 是如何跨端调用你的摄像头、截取屏幕，甚至执行本地终端命令的！我们下期见。

---
