"给他 up 烤盘子"
在测试语音识别功能时,我对着麦克风说了一句"GitHub Copilot"。
屏幕上显示的是:给他 up 烤盘子。
那一刻,我对语音识别技术产生了深深的敬畏——敬畏它在某些时刻的离谱程度。
但更离谱的事情还在后面:我花了一整天开发的语音插件,在即将完成时,发现 Copilot 本身就已经支持语音输入和朗读了。
这是一篇关于"白忙活"的记录。但正如老话说的——过程比结果重要(至少我是这么安慰自己的)。
项目背景:Hackathon 的冲动
公司举办内部 Hackathon,主题是围绕 AI 编程工具做创新。我脑海里冒出一个"很酷"的想法:
如果能用语音和 Copilot 对话,然后让它把回答念出来,岂不是很方便?
想象一下:
- 🎤 对着麦克风说:"帮我解释这段代码"
- 🤖 Copilot 分析后给出解释
- 🔊 解释内容被朗读出来
解放双手,闭眼编程,完美!
于是,VoicePilot 诞生了——一个旨在为 GitHub Copilot Chat 添加语音交互能力的 VS Code 扩展。
技术探索之旅
架构设计
经过一番 brainstorming,我确定了技术栈:
┌─────────────────────────────────────────────────────────────┐
│ VoicePilot 架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 🎤 语音输入 🔊 语音输出 │
│ ───────── ───────── │
│ Azure Speech SDK Azure Speech SDK │
│ (STT: 语音转文字) (TTS: 文字转语音) │
│ │ ▲ │
│ ▼ │ │
│ ┌─────────────────────────────────────────────┐ │
│ │ @voice Chat Participant │ │
│ │ (VS Code Chat API 集成) │ │
│ └─────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ GitHub Copilot 处理 │
│ │
└─────────────────────────────────────────────────────────────┘
核心技术选型:
- Azure Speech SDK (
microsoft-cognitiveservices-speech-sdk):负责语音识别和语音合成 - VS Code Chat Participant API (
vscode.chat.createChatParticipant):创建@voice聊天参与者 - esbuild:打包依赖,避免 node_modules 体积问题
第一个坑:window is not defined
满怀信心地写完代码,打包,安装,运行——
Error: window is not defined
怎么回事?
原来 Azure Speech SDK 的麦克风输入 API (AudioConfig.fromDefaultMicrophoneInput()) 依赖浏览器环境的 window 对象。而 VS Code 扩展运行在 Node.js 环境中,根本没有 window!
这是一个典型的"环境不匹配"问题。SDK 文档里那些漂亮的示例代码,都是给浏览器用的。
解决方案尝试:
- 使用文件输入替代麦克风(录音 → 识别)—— 太麻烦
- 创建 WebView 来捕获音频 —— 复杂度爆炸
- 寻找替代方案...
第二个坑:VS Code Speech 扩展
在搜索解决方案时,我发现了 VS Code Speech 扩展 (ms-vscode.vscode-speech)——微软官方出品,提供本地语音识别能力。
更关键的是,我检查了一下自己的 VS Code:
code --list-extensions | grep -i speech
输出:
ms-vscode.vscode-speech
ms-vscode.vscode-speech-language-pack-zh-cn
我早就安装了它,只是从来没用过。
这让我开始怀疑:Copilot 是不是已经集成了语音功能?
恍然大悟时刻
抱着试试看的心态,我按下了 Cmd+I(macOS)。
一个语音输入界面出现了。我说了句话,文字自动出现在 Copilot Chat 的输入框里。
然后我又搜索了设置,找到了这个:
"accessibility.voice.autoSynthesize": "on"
开启后,当我用语音提问时,Copilot 的回复会自动被朗读出来。
我坐在电脑前,沉默了三秒。
我花了一天时间开发的功能,VS Code 早就有了。
收获与反思
虽然 VoicePilot 最终被判定为"没必要",但这次探索让我收获颇丰:
📚 技术收获
VS Code 扩展开发全流程
- TypeScript 项目结构
package.json中的contributes配置- 命令注册、状态栏管理、快捷键绑定
Chat Participant API
- 创建自定义的
@xxx聊天参与者 - 与 Copilot 模型交互
- 处理流式响应
- 创建自定义的
esbuild 打包
- 将 node_modules 打包进扩展
- 解决
.vsix文件过大问题 - 处理外部依赖的 require
Azure Speech SDK 的局限性
- 麦克风 API 需要浏览器环境
- 文件输入是 Node.js 环境的替代方案
💡 经验教训
做项目前,先调研现有方案!
如果我一开始就搜索"VS Code Copilot voice",可能 5 分钟就能发现答案,而不是花一天去重复造轮子。
但话说回来,如果不亲自踩坑,我也不会真正理解 VS Code 扩展开发的方方面面。有时候,弯路也是一种学习。
附录:Copilot 语音功能完全指南
既然 VoicePilot 没必要做了,那就把 Copilot 自带的语音功能整理清楚,造福后人:
前置条件
- 安装 VS Code Speech 扩展
- 安装对应语言包(如中文:
ms-vscode.vscode-speech-language-pack-zh-cn) - 确保麦克风权限已授予 VS Code
语音输入
| 功能 | Mac 快捷键 | Windows 快捷键 |
|---|---|---|
| 语音输入到 Chat | Cmd+I(按住说话,松开提交) | Ctrl+I |
| 编辑器听写模式 | Cmd+Alt+V | Ctrl+Alt+V |
使用技巧:按住 Cmd+I 不放,对着麦克风说话,松开后自动提交到 Copilot。
语音输出(朗读)
在设置中开启:
// 当用语音输入时,自动朗读 Copilot 的回复
"accessibility.voice.autoSynthesize": "on",
// 朗读时跳过代码块(推荐开启)
"accessibility.voice.ignoreCodeBlocks": true
语言设置
// 设置语音识别的语言
"accessibility.voice.speechLanguage": "zh-CN"
支持 26 种语言,包括中文、英文、日文、法文等。
尾声
VoicePilot 项目虽然"失败"了,但我收获了:
- 一套完整的 VS Code 扩展开发经验
- 对 Azure Speech SDK 的深入理解
- 以及这篇博文
最重要的是,我终于知道怎么让 Copilot "开口说话"了。
下次 Hackathon,我一定会先花 10 分钟调研。
——大概吧。 😅

