本项目采用模块化架构。核心功能是启动录音子进程,然后把音频流传给 STT 识别。
src/
├── core/ # 核心功能模块
│ ├── AudioRecorder.js # 录音进程管理
│ ├── SpeechRecognizer.js # 语音识别管理
│ └── SystemAudioRecognition.js # 主控制器
├── audio/ # 音频处理模块
│ ├── AudioStream.js # 音频流管理
│ ├── AudioStreamFactory.js # 音频流工厂
│ ├── RiffPcmEncoder.js # PCM编码器
│ └── WavFileReader.js # WAV文件读取
├── utils/ # 工具模块
│ ├── config.js # 配置管理
│ ├── permissions.js # 权限检查
│ └── platform.js # 平台检测
├── index.js # 新的入口文件
└── stt.js # 重构后的STT接口
- 协调录音和语音识别功能
- 提供统一的启动和停止接口
- 管理整个音频识别流程
- 负责启动和管理录音子进程
- 处理平台特定的音频参数解析
- 管理提示音播放和录音状态
- 封装Azure语音识别服务
- 提供连续语音识别功能
- 处理识别结果和错误
- 创建和管理推送流
- 监控文件变化并实时处理音频数据
- 处理平台特定的音频格式转换
- 根据文件类型自动创建合适的音频流
- 支持PCM和WAV文件格式
- 提供统一的音频流创建接口
- 音频重采样和格式转换
- 支持不同采样率之间的转换
- Float32到16位PCM的转换
- 解析WAV文件头信息
- 提取音频格式参数
- 验证文件格式兼容性
- 检测操作系统平台
- 提供平台特定的二进制文件路径
- 统一的平台相关配置
- 检查录音权限(主要针对macOS)
- 处理权限相关的错误
- 验证和标准化配置参数
- 提供默认配置值
- 配置参数类型检查
import { startSystemAudioRecognition } from './src/index.js';
const recognition = await startSystemAudioRecognition({
apiKey: 'your-azure-api-key',
region: 'your-azure-region',
language: 'zh-CN',
output: './audio.pcm', // 可选,默认为 ./cache.pcm
// 新增:可选的事件处理器
eventHandlers: {
onRecognized: (s, e) => {
if (e.result.reason === 3 /* sdk.ResultReason.RecognizedSpeech */ && e.result.text) {
console.log(`[README示例] 已识别: ${e.result.text}`);
}
},
onSessionStopped: (s, e) => {
console.log("[README示例] 语音识别会话已停止。");
},
onCanceled: (s, e) => {
console.error(`[README示例] 识别被取消或出错: ${e.errorDetails}`);
}
}
});
// recognition 是 SystemAudioRecognition 的实例
// 你可以在需要的时候调用 recognition.stop()
// 例如,在一个按钮点击事件或者超时之后
// setTimeout(async () => {
// if (recognition.running) {
// console.log("[README示例] 正在停止识别...");
// await recognition.stop();
// }
// }, 60000); // 示例:60秒后停止
// startSystemAudioRecognition 返回的 Promise 会在识别会话结束后 resolve
// 或者在启动过程中发生无法恢复的错误时 reject
// 注意:如果提供了 onSessionStopped,Promise 的 resolve 与该事件的触发紧密相关
重要提示: 如果您提供了自定义的事件处理器 (如 onRecognized
, onCanceled
, onSessionStopped
等),它们将覆盖库内部的默认行为(例如,默认的控制台日志记录)。错误和识别结果应在您提供的回调中处理。
import { SystemAudioRecognition } from './src/index.js';
// import * as sdk from "microsoft-cognitiveservices-speech-sdk"; // 如果需要访问 sdk.ResultReason 等
const recognition = new SystemAudioRecognition();
const options = {
apiKey: 'your-azure-api-key',
region: 'your-azure-region',
language: 'zh-CN',
output: './audio.pcm',
eventHandlers: {
onRecognized: (s, e) => {
// 假设 sdk.ResultReason.RecognizedSpeech 的值为 3
if (e.result.reason === 3 && e.result.text) {
console.log(`[高级示例] 已识别: ${e.result.text}`);
}
},
onSessionStarted: (s, e) => {
console.log("[高级示例] 会话开始");
},
onSessionStopped: (s, e) => {
console.log("[高级示例] 会话停止");
},
onCanceled: (s, e) => {
console.error(`[高级示例] 取消/错误: ${e.errorDetails}`);
}
}
};
(async () => {
try {
await recognition.start(options);
console.log("[高级示例] SystemAudioRecognition.start 完成 (通常意味着会话已结束)");
} catch (error) {
console.error('[高级示例] 启动或识别过程中出错:', error);
}
})();
// 在适当的时候停止
// setTimeout(async () => {
// if (recognition.running) {
// await recognition.stop();
// }
// }, 30000);
适用于不涉及系统录音,仅处理现有音频文件(如 .pcm
或 .wav
)的场景。
import { SpeechRecognizer } from './src/stt.js'; // 或者从 './core/SpeechRecognizer.js'
// import * as sdk from "microsoft-cognitiveservices-speech-sdk";
const config = {
apiKey: 'your-azure-api-key',
region: 'your-azure-region',
language: 'zh-CN'
};
const eventHandlers = {
onRecognized: (s, e) => {
// 假设 sdk.ResultReason.RecognizedSpeech 的值为 3
if (e.result.reason === 3 && e.result.text) {
console.log(`[SpeechRecognizer示例] 已识别: ${e.result.text}`);
}
},
onSessionStopped: (s, e) => {
console.log("[SpeechRecognizer示例] 会话已停止。");
},
onCanceled: (s, e) => {
console.error(`[SpeechRecognizer示例] 取消/错误: ${e.errorDetails}`);
}
};
const recognizer = new SpeechRecognizer(config);
(async () => {
try {
// 假设 audio.pcm 是一个有效的PCM音频文件
// audioConfig 是必需的,至少包含 sampleRate, bitsPerSample, channels
const audioConfig = { sampleRate: 16000, bitsPerSample: 16, channels: 1 };
await recognizer.start('audio.pcm', audioConfig, eventHandlers);
console.log('[SpeechRecognizer示例] 识别流程已启动并结束。');
} catch (error) {
console.error('[SpeechRecognizer示例] 识别失败:', error);
} finally {
if (recognizer.running) {
await recognizer.stop();
}
}
})();
- 职责分离: 每个模块都有明确的职责,易于理解和维护
- 可测试性: 模块化设计使得单元测试更容易编写
- 可扩展性: 新功能可以通过添加新模块或扩展现有模块来实现
- 平台兼容: 平台特定的逻辑被集中管理
- 错误处理: 更好的错误处理和异常管理,结合事件回调和Promise rejection
-
简洁与灵活的API: 提供直观的接口,并通过
eventHandlers
增强灵活性
- 新功能应该添加到相应的模块中
- 保持模块间的低耦合
- 使用依赖注入来提高可测试性
- 遵循单一职责原则
- 充分利用
eventHandlers
来定制化处理识别过程中的各个事件