第九节:Voice Mode 语音模式
WebSocket 流式 STT 与 OAuth 认证

作者:小学子 📚 | 日期:2026年4月2日 | 第一阶段 · 模块一


# 第一阶段 · 模块一 · 第九节:Voice Mode 语音模式

核心问题

Claude Code 如何实现语音输入?Voice Mode 的工作原理是什么?STT(语音转文字)是如何实现的?如何处理实时语音流?


◇ 本节位置


        Claude Code 全局架构
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  服务层(services/)                                                │
        │                                                                      │
        │  Voice Mode ← 本节                                                  │
        │  ├── 音频捕获                                                       │
        │  ├── 静音检测                                                       │
        │  ├── 流式 STT                                                       │
        │  └── TTS 合成                                                       │
        └─────────────────────────────────────────────────────────────────────┘
        


一、Voice Mode 概述

1.1 什么是 Voice Mode

源码位置:`src/services/voice.ts`

Voice Mode 是 Claude Code 的语音输入功能,允许用户通过语音与 Claude 交互,支持实时语音对话。


        ┌─────────────────────────────────────────────────────────────────────┐
        │  Voice Mode 工作流程                                                  │
        │                                                                      │
        │  麦克风 ──► 录音 ──► STT ──► 文字 ──► Claude                      │
        │                          ▲                                          │
        │                       语音输入                                       │
        └─────────────────────────────────────────────────────────────────────┘
        

1.2 核心文件

源码位置:`src/services/voice.ts`


        // Voice Mode 模块
        voice.ts              // 主语音服务
        voiceStreamSTT.ts   // 流式语音转文字
        voiceKeyterms.ts    // 语音关键词
        voiceModeEnabled.ts // 启用检查
        

1.3 功能特性


        ┌─────────────────────────────────────────────────────────────────────┐
        │  Voice Mode 功能                                                     │
        │                                                                      │
        │  1. 实时语音输入                                                     │
        │     - 麦克风录音                                                     │
        │     - 流式 STT 识别                                                  │
        │                                                                      │
        │  2. 静音自动停止                                                     │
        │     - 检测静音自动结束录音                                            │
        │     - 无需手动停止                                                   │
        │                                                                      │
        │  3. 关键词触发                                                       │
        │     - 支持语音关键词唤醒                                              │
        │                                                                      │
        │  4. TTS 语音输出                                                     │
        │     - Claude 回复转为语音                                            │
        └─────────────────────────────────────────────────────────────────────┘
        

1.4 五问分析

问 1:Voice Mode 和打字输入有什么区别?


        // 打字输入:
        // - 需要手动输入
        // - 适合精确表达
        // - 速度受限
        
        // Voice Mode:
        // - 语音直接输入
        // - 适合快速表达
        // - 可结合手势控制
        


二、录音实现

2.1 音频捕获

源码位置:`src/services/voice.ts`


        // 音频常量
        const RECORDING_SAMPLE_RATE = 16000  // 16kHz - 语音识别最佳采样率
        const RECORDING_CHANNELS = 1         // 单声道
        
        // 录音格式
        // - WAV (未压缩) - 本地处理
        // - Opus (压缩) - 用于传输
        

2.2 平台支持


        平台支持:
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  1. macOS/Linux/Windows                                             │
        │     使用原生音频 API                                                  │
        │     - CoreAudio (macOS)                                             │
        │     - ALSA/PulseAudio (Linux)                                       │
        │     - WASAPI (Windows)                                              │
        │                                                                      │
        │  2. Linux 备选方案                                                  │
        │     - SoX (rec)                                                     │
        │     - arecord (ALSA)                                                │
        │                                                                      │
        │  3. Android (Termux)                                                │
        │     - 使用 Termux API                                               │
        └─────────────────────────────────────────────────────────────────────┘
        

2.3 录音流程


        // 录音流程
        async function startRecording(): Promise<void> {
          // 1. 请求麦克风权限
          // 2. 打开音频流
          // 3. 开始录音(边录边传)
          // 4. 检测静音
          // 5. 静音超时自动停止
        }
        

2.4 五问分析

问 1:为什么采样率是 16kHz?


        // 选择 16kHz 的原因:
        
        // 1. 语音识别最佳范围
        // - 人类语音频率范围 300Hz-3400Hz
        // - 16kHz 采样可以完整覆盖
        
        // 2. 带宽考虑
        // - 16kHz 比 44.1kHz 带宽更低
        // - 适合网络传输
        
        // 3. 计算效率
        // - 16kHz 数据量适中
        // - 实时处理可行
        


三、静音检测

3.1 配置参数

源码位置:`src/services/voice.ts`


        // SoX 静音检测参数
        const SILENCE_DURATION_SECS = '2.0'  // 2秒静音后停止录音
        const SILENCE_THRESHOLD = '3%'       // 3% 以下判定为静音
        

3.2 检测原理


        // 静音检测原理:
        
        // 1. 实时监测音频电平
        //    - 计算音频信号的均方根 (RMS)
        //    - 判断是否低于阈值
        
        // 2. 静音判定
        //    - 电平 < 阈值 * 持续时间 > SILENCE_DURATION_SECS
        //    - 则判定为静音
        
        // 3. 自动停止
        //    - 触发静音条件后自动停止录音
        //    - 发送已录制的音频数据
        

3.3 语音活动检测 (VAD)


        // VAD (Voice Activity Detection)
        
        // 用于区分:
        // - 语音信号
        // - 背景噪音
        // - 静音
        
        // 算法:
        // 1. 短时能量检测
        // 2. 过零率检测
        // 3. 频谱特征分析
        

3.4 五问分析

问 1:如何避免误触发静音检测?


        // 方法:
        
        // 1. 调整阈值
        // - 根据环境噪音调整
        // - 安静环境 2-3%
        // - 嘈杂环境 5-10%
        
        // 2. 调整持续时间
        // - 说话间隔短 → 缩短持续时间
        // - 说话间隔长 → 延长持续时间
        
        // 3. 使用 VAD
        // - 更准确的语音检测
        // - 减少误判
        


四、语音转文字 (STT)

4.1 流式 STT 架构

源码位置:`src/services/voiceStreamSTT.ts`

Claude Code 使用 Anthropic voice_stream WebSocket API 实现实时语音识别。


        // WebSocket 连接建立
        
        const VOICE_STREAM_PATH = '/api/ws/speech_to_text/voice_stream'
        
        async function connect(): Promise<VoiceStreamConnection> {
          // 使用 OAuth 凭证连接 Anthropic WebSocket
          const ws = new WebSocket(
            `wss://api.anthropic.com${VOICE_STREAM_PATH}`,
            {
              headers: {
                Authorization: `Bearer ${oauthToken}`,
                'User-Agent': getUserAgent()
              }
            }
          )
        }
        

4.2 协议格式


        // 协议使用 JSON 控制消息 + 二进制音频帧
        
        // 控制消息类型
        type ControlMessage =
          | { type: 'KeepAlive' }      // 心跳保活
          | { type: 'CloseStream' }    // 关闭流
          | { type: 'TranscriptText'; data: string }   // 转写文本
          | { type: 'TranscriptEndpoint' }             // 转写端点
          | { type: 'TranscriptError'; error_code?: string }
        
        // 发送音频
        connection.send(audioChunk: Buffer)
        
        // 结束转写
        const source = await connection.finalize()
        // source: 'post_closestream_endpoint' | 'no_data_timeout' | 'safety_timeout'
        

4.3 心跳机制


        // 心跳保活间隔
        const KEEPALIVE_INTERVAL_MS = 8_000  // 8 秒
        
        // 发送心跳
        setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send('{"type":"KeepAlive"}')
          }
        }, KEEPALIVE_INTERVAL_MS)
        

4.4 结束超时配置


        // finalize() 等待超时配置
        
        export const FINALIZE_TIMEOUTS_MS = {
          safety: 5_000,      // 最长等待 5 秒
          noData: 1_500,      // 无数据后 1.5 秒确认
        }
        
        // noData: 服务器在 CloseStream 后没有更多 TranscriptText
        // safety: 最终安全超时
        

4.5 五问分析

问 1:流式 STT 和完整 STT 有什么区别?


        // 完整 STT:
        // - 录音完整后提交
        // - 延迟 = 录音时间 + 处理时间
        
        // 流式 STT(voice_stream):
        // - WebSocket 实时流式识别
        // - 边录边识别,延迟极低
        // - 使用 Anthropic OAuth 认证
        // - 支持 binary 音频帧传输
        


五、TTS 语音合成

5.1 TTS 配置


        // TTS (Text-to-Speech) 配置
        interface TTSConfig {
          engine: 'elevenlabs' | 'openai' | 'native'
          voice: string
          speed: number  // 0.5 - 2.0
        }
        

5.2 TTS 实现


        // TTS 流程
        
        async function speak(text: string): Promise<void> {
          // 1. 文本预处理
          // - 去除 Markdown 格式
          // - 处理特殊字符
        
          // 2. 调用 TTS API
          const audio = await ttsService.synthesize(text, config)
        
          // 3. 播放音频
          await audioPlayer.play(audio)
        }
        

5.3 语音控制


        // 语音控制
        
        // 1. 播放/暂停
        // 2. 语速调节
        // 3. 音量控制
        // 4. 停止播放
        


六、思考题

思考题 1:Voice Mode 适合哪些场景?

答案


        // 适用场景:
        
        // 1. 快速输入
        // - 不方便打字时
        // - 移动场景
        
        // 2. 手部忙碌
        // - 驾驶时
        // - 烹饪时
        
        // 3. 口语表达更自然
        // - 描述代码逻辑
        // - 口头 Code Review
        
        // 不适用场景:
        
        // 1. 精确代码输入
        // - 变量名拼写
        // - 标点符号
        
        // 2. 嘈杂环境
        // - 会议中
        // - 公共场所
        


思考题 2:如何优化 Voice Mode 的识别准确率?

答案


        // 优化方法:
        
        // 1. 音频质量
        // - 使用好的麦克风
        // - 减少背景噪音
        
        // 2. 语言模型
        // - 使用专门的代码词汇模型
        // - 微调识别模型
        
        // 3. 上下文理解
        // - 结合对话上下文
        // - 纠错机制
        
        // 4. 用户反馈
        // - 错误时及时纠正
        // - 个性化学习
        



思考题 4:WebSocket 心跳机制的作用是什么?

答案


        // 心跳机制的作用:
        
        // 1. 检测连接状态
        // - 及时发现断开的连接
        // - 避免在死连接上继续发送数据
        
        // 2. 保持连接活跃
        // - 防止 NAT 超时断开
        // - 防火墙可能会断开空闲连接
        
        // 3. 节省资源
        // - 可以快速回收死连接
        // - 避免资源浪费
        
        // 实现示例:
        const HEARTBEAT_INTERVAL = 8000; // 8秒
        setInterval(() => {
          if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({ type: 'KeepAlive' }));
          }
        }, HEARTBEAT_INTERVAL);
        


思考题 5:如何处理语音识别错误?

答案


        // 错误处理策略:
        
        // 1. 超时处理
        // - 设置最大等待时间
        // - 超时后提示用户重试
        
        // 2. 重试机制
        // - 识别失败后自动重试
        // - 限制重试次数避免死循环
        
        // 3. 错误恢复
        // - 返回错误码让用户了解原因
        // - 提供手动输入作为备选
        
        // 4. 日志记录
        // - 记录错误便于排查
        // - 分析常见错误模式
        

七、延伸阅读

资源说明
`src/services/voice.ts`语音服务主模块
`src/services/voiceStreamSTT.ts`流式 STT 实现
流式语音处理实时语音识别


八、下节预告

下一节我们将进入 Cost Tracker 成本追踪

- Token 计数

- 费用计算

- 使用报告