前端离线语音控制SDK,基于 Vosk 实现完全离线的语音识别,内置中文语音模型
npm install echo-voice-sdk
EchoSDK 是一个基于 Vosk 的前端离线语音控制 SDK,支持完全离线的语音识别、VAD 检测、声纹识别、唤醒词检测、TTS 语音合成和指令解析。v1.5.1 修复了浏览器 TTS 播放问题。
- 🎤 连续监听 - 实时监听用户语音输入
- 🎯 精准 VAD - 基于多特征融合算法,准确判断语音开始和结束
- 📝 Vosk 离线识别 - 基于 Vosk WASM,完全离线的中文语音识别
- 🔊 声纹识别 - 基于 MFCC 特征提取,支持说话人识别和验证
- 🗣️ 唤醒词检测 - 基于语音识别的唤醒词检测,无需录制模板,开箱即用
- 📢 TTS 语音合成 - 基于 Web Speech API 的语音合成,支持唤醒回复
- 🎮 指令解析 - 支持模糊匹配、拼音匹配、同义词匹配、参数提取、上下文管理
- 🔤 拼音匹配 - 解决语音识别同音字问题,如"向佐"匹配"向左"
- 📚 同义词匹配 - 识别同义词表达,如"打开"="开启"="启动"
- 🔍 关键词提取 - 优化短句匹配,提取关键词进行智能匹配
- 🧠 智能文本处理 - 自动标准化口语化表达,处理中文数字,修正多音字
- 🔐 权限管理 - 自动检查和请求麦克风权限,智能引导用户授权
- 🚀 完全离线 - 所有功能在浏览器本地运行,无需网络连接
修复了浏览器 TTS 播放一次后无法再次播放的问题
1. 问题描述
- 在某些浏览器(特别是 Chrome)中,使用 speechSynthesis API 播放语音后,再次调用或刷新页面都无法播放
- 这是浏览器 speechSynthesis API 的已知 bug
2. 修复方案
- 播放前调用 cancel() 清理浏览器状态
- 使用 setTimeout 延迟调用 speak(),避免竞态条件
- 在 stop() 和 destroy() 中确保完全清理状态
- 双重 cancel() 调用确保彻底清理
3. 测试验证
- 新增 examples/test-tts-fix.html 测试页面
- 包含连续播放、快速点击、刷新后播放三个测试场景
新增 TTS 回声过滤功能,解决 TTS 播放内容被语音识别捕获的问题
1. 问题描述
- TTS 播放时,声音通过扬声器输出,被麦克风捕获
- 语音识别器会识别 TTS 播放的内容,形成"回声"
2. 解决方案
- 方案3:回声消除 - 使用浏览器的 echoCancellation 选项
- 方案4:TTS 内容过滤 - 记录 TTS 播放的内容,在识别结果中过滤
3. 使用方法
``javascript
// 回声过滤默认启用,可以手动控制
sdk.enableEchoFiltering(); // 启用
sdk.disableEchoFiltering(); // 禁用
// 设置过滤相似度阈值(0-1,越低越严格)
sdk.setEchoFilterSimilarity(0.8);
// 设置过滤超时时间(毫秒)
sdk.setEchoFilterTimeout(10000);
// 手动检查文本是否是 TTS 播放的内容
const isEcho = sdk.isSpokenText('你好');
// 手动过滤文本中的 TTS 内容
const filtered = sdk.filterSpokenText('你好世界');
`
`javascript`
// TTS 回声过滤
sdk.enableEchoFiltering(); // 启用回声过滤
sdk.disableEchoFiltering(); // 禁用回声过滤
sdk.isEchoFilteringEnabled(); // 检查是否启用
sdk.setEchoFilterSimilarity(0.8); // 设置相似度阈值
sdk.setEchoFilterTimeout(10000); // 设置过滤超时
sdk.isSpokenText(text); // 检查是否是 TTS 内容
sdk.filterSpokenText(text); // 过滤 TTS 内容
sdk.getRecentSpokenTexts(); // 获取最近播放的文本
sdk.clearSpokenTexts(); // 清空播放记录
使用建议:
`javascript`
// 如果仍有问题,可以手动重置
window.speechSynthesis.cancel();
await sdk.speak('你好');
---
1. 多音字智能识别
- 根据上下文自动修正多音字
- 如:"向佐飞" → "向左飞","往有转" → "往右转"
- 支持自定义多音字映射规则
2. 同义词匹配
- 内置丰富的同义词库(开关、方向、颜色、设备等)
- 自动识别同义词表达,如"打开"="开启"="启动"
- 支持自定义同义词组
3. 关键词提取优化
- 智能提取关键词进行匹配
- 优化短句识别准确度
- 自动过滤停用词和无用词汇
4. 智能文本标准化
- 自动处理口语化表达(如:"给我"、"帮我"、"麻烦")
- 中文数字自动转换(如:"二十三" → "23")
- 标点符号和空格智能处理
5. 拼音匹配阈值优化
- 默认阈值从 1.0 降低到 0.7,提高匹配成功率
- 支持动态调整阈值
`javascript
// 同义词匹配
sdk.enableSynonymMatch();
sdk.disableSynonymMatch();
sdk.addSynonymGroup('飞行', ['飞', '起飞', '飞起来']);
// 关键词提取
sdk.enableKeywordExtraction();
sdk.disableKeywordExtraction();
`
- 新增 examples/demo-accuracy.html - 识别准确度优化演示
---
1. 自动权限检查
- SDK 初始化时自动检查麦克风和 TTS 权限
- 权限被拒绝时自动弹出引导弹窗
- 根据浏览器类型显示详细的操作步骤
2. 权限管理 API
- checkAllPermissions() - 检查所有权限状态requestPermissions()
- - 请求权限(带弹窗提示)onPermissionChange()
- - 监听权限变化getPermissionStatus()
- - 获取当前权限状态
3. 自定义权限弹窗
- 支持自定义弹窗渲染函数
- 内置美观的默认弹窗样式
- 支持自定义文案和按钮
4. 智能权限引导
- 自动识别浏览器类型(Chrome、Firefox、Safari、Edge)
- 提供针对性的操作指引
- 步骤清晰,易于理解
1. TTS 多次调用问题
- 修复快速连续调用 speak() 导致的 Promise 重复 resolve 问题
- 优化取消逻辑,避免旧任务影响新任务
- 改进错误处理,区分正常取消和真正的错误
2. TTS 自动播放限制
- 优雅处理 not-allowed 错误
- 提供清晰的错误提示和解决方案
- 支持在用户交互后重试
- 新增 examples/demo-permission.html - 权限管理演示
`bash`
npm install echo-voice-sdk
启动本地服务器后访问:
`bash`
npm run demo
然后打开浏览器访问以下 Demo 页面:
| Demo 文件 | 功能说明 | 访问地址 |
|-----------|----------|----------|
| demo.html | 基础语音识别 - Vosk 离线识别 + 指令匹配 + 声纹识别 + 唤醒词 | http://127.0.0.1:8080/examples/demo.html |demo-sdk.html
| | SDK 完整功能 - 使用 SDK 封装的 API,包含拼音匹配功能 | http://127.0.0.1:8080/examples/demo-sdk.html |demo-voiceprint.html
| | 声纹识别专项 - 声纹录制、注册、识别的完整演示 | http://127.0.0.1:8080/examples/demo-voiceprint.html |demo-permission.html
| | 权限管理演示 - 自动权限检查、请求权限、智能引导 | http://127.0.0.1:8080/examples/demo-permission.html |demo-accuracy.html
| | 识别准确度优化 - 多音字、同义词、短句匹配优化演示 | http://127.0.0.1:8080/examples/demo-accuracy.html |
> 💡 拼音匹配功能:SDK 内置拼音匹配,可解决同音字问题(如"向佐"→"向左"),所有 Demo 均已支持
SDK 提供三种版本:
| 文件 | 大小 | 说明 |
|------|------|------|
| echo-sdk.js | ~5.6MB | 完整版,内置 Vosk,推荐使用 |echo-sdk.esm.js
| | ~80KB | ESM 模块版,支持 tree-shaking |echo-sdk.lite.js
| | ~34KB | 轻量版,需单独引入 Vosk |
#### 方式一:完整版(推荐)
`html`
#### 方式二:轻量版(需单独引入 Vosk)
`html`
#### 方式三:ESM 模块
`javascript`
import EchoSDK, { Vosk } from 'echo-voice-sdk';
`javascript
import EchoSDK from 'echo-voice-sdk';
// 创建 SDK 实例
const sdk = new EchoSDK({
debug: true,
speechRecognition: {
// Vosk 模型路径,支持以下方式:
// 1. 本地路径(需要将模型文件放到你的静态资源目录)
voskModelPath: '/models/vosk-model-cn.tar.gz'
// 2. CDN 远程地址
// voskModelPath: 'https://your-cdn.com/vosk-model-cn.tar.gz'
},
// 唤醒词配置(可选)
wakeWord: {
enabled: true, // 启用唤醒词
words: ['小云小云'], // 唤醒词列表
sensitivity: 0.6, // 灵敏度 0-1
response: '我在', // 唤醒后的语音回复
commandTimeout: 10000 // 唤醒后等待指令的超时时间 (ms)
},
// TTS 语音合成配置(可选)
tts: {
enabled: true,
lang: 'zh-CN',
rate: 1.0
},
commands: [
{
name: 'openLight',
triggers: ['打开灯', '开灯'],
handler: (params) => {
console.log('执行: 打开灯');
}
}
]
});
// 注册事件监听
sdk.on('voiceStart', () => console.log('语音开始'));
sdk.on('voiceEnd', (data) => console.log('语音结束,时长:', data.duration, 'ms'));
sdk.on('recognition', (result) => console.log('识别结果:', result.text));
sdk.on('command', (result) => console.log('指令:', result.command));
sdk.on('wake', (result) => console.log('唤醒词:', result.word, '置信度:', result.confidence));
sdk.on('error', (error) => console.error('错误:', error.message));
// 初始化并启动
await sdk.init();
await sdk.start();
`
`javascript
// 初始化 SDK(加载模型、初始化各模块)
await sdk.init();
// 开始语音监听
await sdk.start();
// 停止语音监听(可以重新 start)
sdk.stop();
// 销毁 SDK(释放所有资源,不可恢复)
sdk.destroy();
`
问题原因:vosk-browser 的 acceptWaveform 方法需要 AudioBuffer 对象,而不是 Float32Array。
解决方案:SDK 已在 v1.0.1 版本中修复此问题。如果仍遇到此错误,请确保:
1. 使用最新版本的 SDK:
`bash`
npm install echo-voice-sdk@latest
1. 清除缓存并重新构建:
`bash`
rm -rf node_modules package-lock.json
npm install
npm run build
1. 在 Vue 项目中正确引入:
`javascript
import EchoSDK from 'echo-voice-sdk';
// 在 Vue 组件中使用
export default {
async mounted() {
const sdk = new EchoSDK({
debug: true,
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz',
},
// 唤醒词配置(可选)
wakeWord: {
enabled: true, // 启用唤醒词
words: ['小云小云'], // 唤醒词列表
sensitivity: 0.6, // 灵敏度 0-1
response: '我在', // 唤醒后的语音回复
commandTimeout: 10000 // 唤醒后等待指令的超时时间 (ms)
},
// TTS 语音合成配置(可选)
tts: {
enabled: true,
lang: 'zh-CN',
rate: 1.0
},
commands: [
{
name: 'openLight',
triggers: ['打开灯', '开灯'],
handler: (params) => {
console.log(params);
},
},
],
});
sdk.on('voiceStart', () => console.log('语音开始'));
sdk.on('voiceEnd', (data) => console.log('语音结束,时长:', data.duration, 'ms'));
sdk.on('recognition', (result) => console.log('识别结果:', result.text));
sdk.on('command', (result) => console.log('指令:', result.command));
sdk.on('wake', (result) => console.log('唤醒词:', result.word));
sdk.on('error', (error) => console.error('错误:', error.message));
await sdk.init();
await sdk.start();
}
}
`
问题原因:当 TTS 语音被取消或打断时(例如快速连续调用 speak() 或调用 stop()),Web Speech API 会触发 onerror 事件,错误类型为 canceled 或 interrupted。这是正常的取消行为,不应该被当作真正的错误。
解决方案:SDK 已在最新版本中修复此问题,canceled 和 interrupted 错误会被正常处理,不会抛出异常。如果仍遇到此问题,请更新到最新版本:
`bash`
npm install echo-voice-sdk@latest
修复内容:
- canceled 错误:正常的取消操作(如调用 stop() 或新的 speak() 调用)interrupted
- 错误:被其他语音打断,也是正常情况audio-busy
- 这两种情况现在会正常结束 Promise,不会抛出错误
- 只有真正的错误(如 、network 等)才会触发异常
问题原因:浏览器的自动播放策略(Autoplay Policy)要求 TTS 语音合成必须由用户交互触发(如点击、触摸等),不能在页面加载时自动播放。
错误示例:
`javascript`
// ❌ 错误:在页面加载时直接播放
async function init() {
const sdk = new EchoSDK({ tts: { enabled: true } });
await sdk.init();
await sdk.speak('欢迎使用'); // 抛出 not-allowed 错误
}
解决方案一:在用户交互后播放(推荐)
`javascript
// ✅ 正确:先初始化,在用户点击后播放
let sdk = null;
async function init() {
sdk = new EchoSDK({ tts: { enabled: true } });
await sdk.init();
return sdk;
}
// 在按钮点击事件中播放
button.addEventListener('click', async () => {
if (!sdk) {
await init();
}
await sdk.speak('欢迎使用'); // 正常播放
await sdk.start();
});
`
解决方案二:捕获错误并提示用户
`javascript`
async function init() {
const sdk = new EchoSDK({ tts: { enabled: true } });
await sdk.init();
try {
await sdk.speak('欢迎使用');
} catch (error) {
if (error.code === 'NOT_ALLOWED') {
console.log('语音播放需要用户交互,请点击按钮后再试');
// 显示提示按钮让用户点击
}
}
return sdk;
}
Vue 示例:
`vue
`
React 示例:
`jsx
import { useState } from 'react';
import EchoSDK from 'echo-voice-sdk';
function App() {
const [sdk, setSdk] = useState(null);
const handleStart = async () => {
let instance = sdk;
if (!instance) {
instance = new EchoSDK({
tts: { enabled: true },
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz'
}
});
await instance.init();
setSdk(instance);
}
// 在用户点击后播放,不会报错
await instance.speak('欢迎使用语音助手');
await instance.start();
};
return (
);
}
`
问题原因:Vosk 模型文件路径不正确或文件不存在。
解决方案:
1. 确保模型文件已复制到静态资源目录
2. 检查 voskModelPath 配置是否正确
3. 查看浏览器控制台的网络请求,确认模型文件是否成功加载
问题原因:浏览器需要用户授权才能访问麦克风。
解决方案:
SDK 已在最新版本中自动集成权限检查功能,在初始化时会自动检测权限状态:
1. 自动检查:init() 时自动检查权限
2. 自动弹窗:如果权限被拒绝,自动显示引导弹窗
3. 操作指引:根据浏览器类型显示详细的操作步骤
`javascript
const sdk = new EchoSDK({ / 配置 / });
// 初始化时自动检查权限
try {
await sdk.init(); // 如果权限被拒绝,会自动弹出引导弹窗
} catch (error) {
if (error.message === '麦克风权限被拒绝') {
console.log('用户拒绝了权限或需要手动开启');
}
}
`
手动控制权限检查:
如果你想在初始化前手动检查权限:
`javascript
const sdk = new EchoSDK({ / 配置 / });
// 先检查权限
const permissionResult = await sdk.checkAllPermissions();
if (permissionResult.hasDenied) {
// 显示自定义的权限引导 UI
console.log('权限被拒绝,请手动开启');
} else if (permissionResult.microphone === 'prompt') {
// 请求权限
await sdk.requestPermissions({
showDialog: true,
dialogTitle: '需要授权',
dialogMessage: '为了使用语音功能,需要您授权麦克风权限'
});
}
// 然后初始化
await sdk.init();
`
在 HTTPS 环境下运行:
确保在 HTTPS 环境下运行(localhost 除外),否则浏览器不允许访问麦克风。
| 配置项 | 类型 | 默认值 | 描述 |
|-------|------|--------|------|
| sampleRate | number | 16000 | 音频采样率 |bufferSize
| | number | 4096 | 音频缓冲区大小 |language
| | string | 'zh-CN' | 语言 |debug
| | boolean | false | 调试模式 |autoStart
| | boolean | false | 是否自动开始监听 |vad
| | VADConfig | - | VAD 配置 |speechRecognition
| | SpeechRecognitionConfig | - | 语音识别配置 |voiceprint
| | VoiceprintConfig | - | 声纹识别配置 |wakeWord
| | WakeWordConfig | - | 唤醒词配置 |tts
| | TTSConfig | - | TTS 语音合成配置 |commandParser
| | CommandParserConfig | - | 指令解析器配置 |commands
| | Command[] | [] | 指令列表 |events
| | EventListeners | - | 事件监听器(可在初始化时预设) |
`javascript
const sdk = new EchoSDK({
// 基础配置
sampleRate: 16000,
bufferSize: 4096,
language: 'zh-CN',
debug: true,
autoStart: false,
// VAD 配置
vad: {
mode: 2, // 灵敏度模式 0-3
silenceThreshold: 500, // 静音时长阈值 (ms)
voiceThreshold: 200 // 语音起始阈值 (ms)
},
// 语音识别配置
speechRecognition: {
language: 'zh-CN',
continuous: false,
interimResults: true,
voskModelPath: '/models/vosk-model-cn.tar.gz',
maxDuration: 10000
},
// 声纹识别配置
voiceprint: {
enabled: true,
threshold: 0.88, // 匹配阈值
minEnrollDuration: 5000 // 最小录入时长 (ms)
},
// 唤醒词配置
wakeWord: {
enabled: true,
words: ['小云小云', '你好小云'],
sensitivity: 0.6,
response: '我在',
commandTimeout: 10000,
fuzzyMatch: true,
minSimilarity: 0.8
},
// TTS 配置
tts: {
enabled: true,
lang: 'zh-CN',
rate: 1.0,
pitch: 1.0,
volume: 1.0,
voiceName: 'Microsoft Xiaoxiao'
},
// 指令解析器配置
commandParser: {
enablePinyinMatch: true, // 启用拼音匹配
pinyinMatchThreshold: 0.8, // 拼音匹配阈值
enableSynonymMatch: true, // 启用同义词匹配
enableKeywordExtraction: true // 启用关键词提取
},
// 指令列表
commands: [
{
name: 'openLight',
triggers: ['打开灯', '开灯'],
handler: (params) => console.log('打开灯')
},
{
name: 'closeLight',
triggers: ['关闭灯', '关灯'],
handler: (params) => console.log('关闭灯')
}
],
// 事件监听器(可选,也可以用 sdk.on() 注册)
events: {
onReady: () => console.log('SDK 就绪'),
onVoiceStart: () => console.log('语音开始'),
onVoiceEnd: (data) => console.log('语音结束,时长:', data.duration),
onRecognition: (result) => console.log('识别结果:', result.text),
onCommand: (result) => console.log('指令:', result.command),
onWake: (result) => console.log('唤醒词:', result.word),
onError: (error) => console.error('错误:', error.message),
onStateChange: ({ from, to }) => console.log(状态: ${from} -> ${to})
}
});
await sdk.init();
await sdk.start();
`
`typescript`
interface CommandParserConfig {
enablePinyinMatch?: boolean; // 是否启用拼音匹配,默认 true
pinyinMatchThreshold?: number; // 拼音匹配阈值 0-1,默认 0.8
enableSynonymMatch?: boolean; // 是否启用同义词匹配,默认 true
enableKeywordExtraction?: boolean; // 是否启用关键词提取,默认 true
}
SDK 内置了拼音匹配功能,可以解决语音识别中的同音字问题。例如:
- 用户说"向左飞",但语音识别结果是"向佐非"
- 通过拼音匹配,"向佐非"的拼音 xiang zuo fei 与触发词"向左飞"的拼音相同,可以正确匹配
`javascript
// 拼音匹配默认启用,无需额外配置
const sdk = new EchoSDK({
commandParser: {
enablePinyinMatch: true, // 启用拼音匹配
pinyinMatchThreshold: 0.8 // 匹配阈值(0-1,越高越严格)
},
commands: [
{
name: 'fly_left',
triggers: ['向左', '往左', '向左飞', '往左飞', '左飞'],
handler: () => console.log('向左飞')
},
{
name: 'fly_right',
triggers: ['向右', '往右', '向右飞', '往右飞', '右飞'],
handler: () => console.log('向右飞')
}
]
});
// 即使语音识别结果是"向佐飞"、"往佐转",也能正确匹配到"向左飞"指令
`
#### 拼音匹配 API
`javascript
// 启用拼音匹配(默认已启用)
sdk.enablePinyinMatch();
// 禁用拼音匹配
sdk.disablePinyinMatch();
// 检查拼音匹配是否启用
const enabled = sdk.isPinyinMatchEnabled();
// 设置拼音匹配阈值(0-1,越高要求越严格)
sdk.setPinyinMatchThreshold(0.8);
`
SDK 内置了丰富的同义词库,可以识别不同的表达方式。例如:
- "打开灯" = "开启灯" = "启动灯"
- "关闭灯" = "关掉灯" = "停止灯"
- "向左" = "往左" = "左边" = "左转"
`javascript`
const sdk = new EchoSDK({
commandParser: {
enableSynonymMatch: true // 启用同义词匹配(默认启用)
},
commands: [
{
name: 'open_light',
triggers: ['打开灯', '开灯'], // 会自动匹配"开启灯"、"启动灯"等
handler: () => console.log('打开灯')
}
]
});
#### 同义词匹配 API
`javascript
// 启用同义词匹配(默认已启用)
sdk.enableSynonymMatch();
// 禁用同义词匹配
sdk.disableSynonymMatch();
// 检查同义词匹配是否启用
const enabled = sdk.isSynonymMatchEnabled();
// 添加自定义同义词组
sdk.addSynonymGroup('飞行', ['飞', '起飞', '飞起来', '飞上去']);
`
#### 内置同义词库
SDK 内置了以下同义词组:
- 开关类:打开、开启、启动、关闭、关掉、停止
- 方向类:向左、往左、左边、向右、往右、右边、向前、向后、向上、向下
- 调节类:增加、加大、提高、减少、减小、降低
- 播放控制:播放、暂停、继续、下一首、上一首
- 设备类:灯、空调、电视、音响
- 颜色类:红色、绿色、蓝色、黄色、白色
- 位置类:客厅、卧室、厨房、卫生间
SDK 支持关键词提取功能,可以优化短句匹配准确度。例如:
- "给我打开灯" → 提取关键词"打开灯"
- "麻烦帮我关一下灯" → 提取关键词"关灯"
`javascript`
const sdk = new EchoSDK({
commandParser: {
enableKeywordExtraction: true // 启用关键词提取(默认启用)
}
});
#### 关键词提取 API
`javascript
// 启用关键词提取(默认已启用)
sdk.enableKeywordExtraction();
// 禁用关键词提取
sdk.disableKeywordExtraction();
// 检查关键词提取是否启用
const enabled = sdk.isKeywordExtractionEnabled();
`
SDK 会自动对语音识别结果进行智能标准化处理:
1. 口语化表达处理:自动移除"给我"、"帮我"、"麻烦"等口语词
2. 中文数字转换:自动将"二十三"转换为"23"
3. 多音字修正:根据上下文自动修正多音字(如:"向佐"→"向左")
4. 标点符号处理:自动移除标点符号和多余空格
这些处理都是自动进行的,无需额外配置。
`typescript`
interface VoiceprintConfig {
threshold?: number; // 匹配阈值 0-1,默认 0.88,越高要求越严格
enabled?: boolean; // 是否启用声纹识别,默认 false
minEnrollDuration?: number; // 最小录入时长 (ms),默认 5000
}
`typescript`
interface WakeWordConfig {
enabled?: boolean; // 是否启用唤醒词,默认 false
words?: string[]; // 唤醒词列表,默认 ['小云小云']
sensitivity?: number; // 灵敏度 0-1,默认 0.6,影响模糊匹配阈值
response?: string; // 唤醒后的回复文本,默认 '我在'
autoStartRecognition?: boolean; // 唤醒后是否自动开始语音识别,默认 true
commandTimeout?: number; // 唤醒后等待指令的超时时间 (ms),默认 10000
fuzzyMatch?: boolean; // 是否启用模糊匹配,默认 true
minSimilarity?: number; // 模糊匹配最小相似度 0-1,默认 0.8
}
`typescript`
interface TTSConfig {
enabled?: boolean; // 是否启用 TTS,默认 true
lang?: string; // 语言,默认 'zh-CN'
rate?: number; // 语速 0.1-10,默认 1.0
pitch?: number; // 音调 0-2,默认 1.0
volume?: number; // 音量 0-1,默认 1.0
voiceName?: string; // 首选语音名称
}
SDK 内置了基于 MFCC 特征的离线声纹识别功能,可以识别不同说话人。
- 完全离线:所有计算在浏览器本地完成
- 多特征融合:MFCC + 基频 + 频谱质心 + 过零率等
- 静音过滤:自动过滤静音帧,提高识别准确性
- 本地存储:声纹数据保存在 localStorage
`javascript
const sdk = new EchoSDK({
voiceprint: {
enabled: true,
threshold: 0.88, // 匹配阈值,越高越严格
minEnrollDuration: 5000 // 录入至少需要 5 秒
}
});
await sdk.init();
// 录入声纹(需要至少 5 秒的音频)
const voiceprint = sdk.enrollVoiceprint('张三', audioData);
// 识别声纹
const result = sdk.recognizeVoiceprint(audioData);
console.log(result);
// { matched: true, name: '张三', similarity: 0.92, isUnknown: false }
// 监听声纹匹配事件
sdk.on('voiceprintMatch', (result) => {
if (result.matched) {
console.log(识别到: ${result.name},相似度: ${(result.similarity * 100).toFixed(1)}%);
} else {
console.log('未识别到已知声纹');
}
});
// 获取所有已录入的声纹
const voiceprints = sdk.getVoiceprints();
// 删除声纹
sdk.deleteVoiceprint(voiceprintId);
// 清空所有声纹
sdk.clearVoiceprints();
`
`javascript
// 启用/禁用声纹识别
sdk.enableVoiceprint();
sdk.disableVoiceprint();
// 录入声纹(需要至少 5 秒的音频)
const voiceprint = await sdk.enrollVoiceprint('张三', audioData);
// 添加声纹样本(增强已有声纹的识别准确性)
await sdk.addVoiceprintSample(voiceprintId, audioData);
// 识别声纹
const result = sdk.recognizeVoiceprint(audioData);
// 获取所有已录入的声纹
const voiceprints = sdk.getVoiceprints();
// 获取声纹数量
const count = sdk.getVoiceprintCount();
// 删除声纹
await sdk.deleteVoiceprint(voiceprintId);
// 清空所有声纹
await sdk.clearVoiceprints();
// 设置声纹匹配阈值(0-1,越高要求越严格)
sdk.setVoiceprintThreshold(0.9);
// 获取当前说话人(在语音识别过程中)
const speaker = sdk.getCurrentSpeaker();
// 导出声纹数据(用于备份)
const jsonData = sdk.exportVoiceprints();
// 导入声纹数据
const importedCount = await sdk.importVoiceprints(jsonData);
`
1. 录入时间要长:至少说 5 秒以上,内容丰富一些
2. 多次录入:可以多次录入同一个人的声纹来增强准确性
3. 安静环境:录入和识别时尽量在安静环境下进行
4. 调整阈值:如果误识别率高,可以提高 threshold 值(如 0.90)
SDK 内置了基于 语音识别文本匹配 的唤醒词检测功能,无需录制模板,开箱即用。
- 开箱即用:只需配置唤醒词文本,无需录制音频模板
- 完全离线:基于 Vosk 语音识别,所有计算在浏览器本地完成
- 精确匹配:检测识别结果是否包含唤醒词
- 模糊匹配:支持相似度匹配,容忍识别误差
- TTS 语音回复:唤醒后自动语音回复"我在"
- 连续指令:支持"小云小云打开灯"这样的连续语音
`javascript
// 创建 SDK 实例并启用唤醒词
const sdk = new EchoSDK({
debug: true,
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz'
},
wakeWord: {
enabled: true, // 启用唤醒词检测
words: ['小云小云', '你好小云'], // 唤醒词列表(支持多个)
sensitivity: 0.6, // 灵敏度,越高越容易触发
response: '我在', // 唤醒后的语音回复
commandTimeout: 10000, // 唤醒后 10 秒内等待指令
fuzzyMatch: true, // 启用模糊匹配
minSimilarity: 0.8 // 模糊匹配最小相似度
},
tts: {
enabled: true,
lang: 'zh-CN',
rate: 1.0
},
commands: [
{
name: 'openLight',
triggers: ['打开灯', '开灯'],
handler: () => console.log('执行: 打开灯')
}
]
});
// 初始化并启动
await sdk.init();
await sdk.start();
// 监听唤醒事件
sdk.on('wake', (result) => {
console.log(唤醒词: ${result.word}, 置信度: ${(result.confidence * 100).toFixed(1)}%);
// 唤醒后 SDK 会自动开始监听语音指令
});
// 监听 TTS 事件
sdk.on('speakStart', ({ text }) => console.log('开始朗读:', text));
sdk.on('speakEnd', ({ text }) => console.log('朗读结束:', text));
`
1. 监听模式:SDK 启动后进入唤醒词监听模式,持续进行语音识别
2. 唤醒检测:检测到唤醒词后,触发 wake 事件,播放语音回复
3. 指令模式:进入指令等待模式,此时的语音会被解析为指令
4. 超时休眠:如果超时未收到指令,自动回到唤醒词监听模式
SDK 支持在唤醒词后直接跟随指令,例如:
- "小云小云,打开灯" → 唤醒 + 执行"打开灯"指令
- "小云小云" → 唤醒,等待后续指令
`javascript`
// 用户说:"小云小云打开灯"
// SDK 会:
// 1. 检测到唤醒词"小云小云"
// 2. 触发 wake 事件
// 3. 播放"我在"
// 4. 自动提取并执行"打开灯"指令
`javascript
// 启用/禁用唤醒词检测
sdk.enableWakeWord();
sdk.disableWakeWord();
// 添加唤醒词
sdk.addWakeWord('小助手');
// 移除唤醒词
sdk.removeWakeWord('小助手');
// 获取唤醒词列表
const words = sdk.getWakeWords();
// 设置唤醒词列表
sdk.setWakeWords(['小云小云', '你好小云', '小助手']);
// 设置灵敏度
sdk.setWakeWordSensitivity(0.8);
// 设置是否启用模糊匹配
sdk.setWakeWordFuzzyMatch(true);
// 检查唤醒状态
const isAwake = sdk.getIsAwake();
// 手动设置唤醒状态
sdk.setAwake(true); // 手动唤醒(跳过唤醒词检测)
sdk.setAwake(false); // 手动休眠
`
1. 唤醒词选择:选择 2-4 个音节的词语效果最佳,如"小云小云"、"你好小云"
2. 避免常见词:避免使用日常对话中常见的词语,减少误触发
3. 调整灵敏度:如果误触发多,降低灵敏度;如果难以触发,提高灵敏度
4. 安静环境:在安静环境下使用效果更好
5. 清晰发音:说唤醒词时发音清晰,语速适中
SDK 内置了基于 Web Speech API 的 TTS 语音合成功能。
`javascript
const sdk = new EchoSDK({
tts: {
enabled: true,
lang: 'zh-CN',
rate: 1.0, // 语速
pitch: 1.0, // 音调
volume: 1.0 // 音量
}
});
await sdk.init();
// 朗读文本
await sdk.speak('你好,我是小云');
// 停止朗读
sdk.stopSpeak();
// 检查是否正在朗读
const isSpeaking = sdk.getIsSpeaking();
// 调整参数
sdk.setTTSRate(1.2); // 加快语速
sdk.setTTSPitch(1.1); // 提高音调
sdk.setTTSVolume(0.8); // 降低音量
// 获取可用语音列表
const voices = sdk.getTTSVoices();
console.log('可用语音:', voices.map(v => v.name));
// 设置语音
sdk.setTTSVoice('Microsoft Xiaoxiao');
// 启用/禁用 TTS
sdk.enableTTS();
sdk.disableTTS();
`
SDK 支持动态添加、移除和管理指令。
`javascript
// 添加单个指令
sdk.addCommand({
name: 'turnOff',
triggers: ['关闭', '关掉'],
handler: (params) => console.log('关闭设备')
});
// 批量添加指令
sdk.addCommands([
{
name: 'volumeUp',
triggers: ['大声点', '音量加'],
handler: () => console.log('音量增加')
},
{
name: 'volumeDown',
triggers: ['小声点', '音量减'],
handler: () => console.log('音量减少')
}
]);
// 移除指令
sdk.removeCommand('turnOff');
// 清空指令上下文(重置上下文状态)
sdk.clearContext();
`
SDK 支持在运行时获取和更新配置。
`javascript
// 获取当前配置
const config = sdk.getConfig();
console.log('当前配置:', config);
// 更新配置(支持部分更新)
sdk.updateConfig({
debug: true,
vad: {
silenceThreshold: 600
},
tts: {
rate: 1.2
}
});
`
SDK 使用事件驱动模式,支持注册和移除事件监听器。
`javascript
// 注册事件监听器
sdk.on('recognition', (result) => {
console.log('识别结果:', result.text);
});
// 移除事件监听器
const handler = (result) => console.log(result);
sdk.on('command', handler);
sdk.off('command', handler); // 移除指定的监听器
`
| 事件名 | 描述 | 回调参数 |
|-------|------|---------|
| voiceStart | 语音开始 | 无 |voiceEnd
| | 语音结束 | { duration: number, audioData?: Float32Array } |recognition
| | 语音识别结果 | { text: string, confidence: number, isFinal: boolean } |command
| | 指令识别 | { command: string, params: object, confidence: number } |voiceprintMatch
| | 声纹匹配结果 | { matched: boolean, name: string, similarity: number, isUnknown: boolean } |wake
| | 唤醒词检测 | { word: string, confidence: number, timestamp: number } |speakStart
| | TTS 开始朗读 | { text: string } |speakEnd
| | TTS 朗读结束 | { text: string } |error
| | 错误 | { type: string, message: string } |ready
| | SDK 就绪 | 无 |stopped
| | SDK 停止 | 无 |stateChange
| | 状态变化 | { from: SDKState, to: SDKState } |
SDK 提供了多个方法来检测当前的语音识别状态,方便在 UI 中显示状态指示器。
`javascript
// 检查当前是否正在进行语音识别
const isRecognizing = sdk.getIsRecognizing();
// 检查当前是否检测到语音活动(用户正在讲话)
const isVoiceActive = sdk.getIsVoiceActive();
// 检查当前是否正在监听(麦克风已开启)
const isListening = sdk.getIsListening();
// 获取当前 SDK 状态
const state = sdk.getState();
// 可能的值: 'idle' | 'initializing' | 'ready' | 'running' | 'listening' | 'processing' | 'stopped' | 'error'
// 获取完整状态信息
const status = sdk.getStatus();
console.log(status);
// {
// state: 'listening',
// isInitialized: true,
// isListening: true,
// isRecognizing: false,
// isVoiceActive: false,
// isAwake: false,
// isPinyinMatchEnabled: true,
// ...
// }
`
`javascript状态从 ${from} 变为 ${to}
// 监听状态变化事件
sdk.on('stateChange', ({ from, to }) => {
console.log();`
// 更新 UI 状态指示器
if (to === 'listening') {
showListeningIndicator();
} else if (to === 'running') {
showRecognizingIndicator();
}
});
`javascript
// Vue 3 Composition API 示例
import { ref, onMounted, onUnmounted } from 'vue';
import EchoSDK from 'echo-voice-sdk';
export function useEchoVoice() {
const sdk = ref(null);
const isListening = ref(false);
const isRecognizing = ref(false);
const isVoiceActive = ref(false);
// 定时更新状态
let statusInterval = null;
onMounted(async () => {
sdk.value = new EchoSDK({ / 配置 / });
await sdk.value.init();
// 每 100ms 更新状态
statusInterval = setInterval(() => {
if (sdk.value) {
isListening.value = sdk.value.getIsListening();
isRecognizing.value = sdk.value.getIsRecognizing();
isVoiceActive.value = sdk.value.getIsVoiceActive();
}
}, 100);
});
onUnmounted(() => {
if (statusInterval) clearInterval(statusInterval);
sdk.value?.destroy();
});
return {
sdk,
isListening,
isRecognizing,
isVoiceActive
};
}
`
SDK 提供了完整的麦克风权限检测和引导功能,帮助处理用户拒绝权限的情况。
SDK 在初始化时会自动检查权限,如果检测到权限被拒绝,会自动弹出引导弹窗:
`javascript
const sdk = new EchoSDK({
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz'
}
});
// 初始化时自动检查权限
await sdk.init(); // 如果权限被拒绝,会自动弹出引导弹窗
`
你也可以在初始化前手动检查和请求权限:
`javascript
const sdk = new EchoSDK({ / 配置 / });
// 1. 检查所有权限(麦克风 + TTS)
const permissionResult = await sdk.checkAllPermissions();
console.log('麦克风权限:', permissionResult.microphone); // 'granted' | 'denied' | 'prompt'
console.log('TTS 权限:', permissionResult.tts);
console.log('所有权限已授权:', permissionResult.allGranted);
console.log('有权限被拒绝:', permissionResult.hasDenied);
// 2. 请求权限(带弹窗提示)
if (!permissionResult.allGranted) {
const result = await sdk.requestPermissions({
showDialog: true,
dialogTitle: '需要授权',
dialogMessage: '为了使用语音功能,需要您授权麦克风权限',
confirmText: '授权',
cancelText: '取消'
});
if (result.allGranted) {
console.log('权限已授予');
await sdk.init();
} else {
console.log('权限被拒绝');
}
}
`
你可以使用自定义弹窗替代默认弹窗:
`javascript`
await sdk.requestPermissions({
showDialog: true,
customDialog: async (config) => {
// config 包含:type, permission, title, message, steps, browser, confirmText, cancelText
if (config.type === 'request') {
// 显示请求权限的弹窗
return await showMyCustomRequestDialog(config);
} else if (config.type === 'denied') {
// 显示权限被拒绝的引导弹窗
await showMyCustomDeniedDialog(config);
return false;
}
}
});
` 麦克风权限被拒绝,请按以下步骤手动开启:vue
`
`jsx
import { useState, useEffect } from 'react';
import EchoSDK from 'echo-voice-sdk';
function App() {
const [sdk, setSdk] = useState(null);
const [permissionStatus, setPermissionStatus] = useState('unknown');
const [guidanceSteps, setGuidanceSteps] = useState([]);
useEffect(() => {
const instance = new EchoSDK({
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz'
}
});
// 检查权限
instance.checkAllPermissions().then(result => {
setPermissionStatus(result.microphone);
});
// 监听权限变化
instance.onPermissionChange(result => {
setPermissionStatus(result.microphone);
});
setSdk(instance);
}, []);
const handleRequestPermission = async () => {
const result = await sdk.requestPermissions({
showDialog: true
});
if (result.hasDenied) {
const guidance = await sdk.getMicrophonePermissionGuidance();
if (guidance.guidance) {
setGuidanceSteps(guidance.guidance.steps);
}
}
};
const handleStart = async () => {
await sdk.init();
await sdk.start();
};
if (permissionStatus === 'prompt') {
return ;
}
if (permissionStatus === 'denied') {
return (
麦克风权限被拒绝,请按以下步骤手动开启:
if (permissionStatus === 'granted') {
return ;
}
return
$3
`typescript
enum PermissionStatus {
GRANTED = 'granted', // 已授权
DENIED = 'denied', // 已拒绝
PROMPT = 'prompt', // 待询问(用户尚未做出选择)
UNKNOWN = 'unknown' // 未知(浏览器不支持权限查询)
}
`$3
`typescript
interface PermissionCheckResult {
microphone: PermissionStatus; // 麦克风权限状态
tts: PermissionStatus; // TTS 权限状态
allGranted: boolean; // 是否所有权限都已授权
hasDenied: boolean; // 是否有权限被拒绝
deniedPermissions: string[]; // 拒绝的权限列表
}
`$3
`javascript
// 检查所有权限
const result = await sdk.checkAllPermissions();// 请求权限(带弹窗)
const result = await sdk.requestPermissions(config);
// 监听权限变化
sdk.onPermissionChange((result) => {
console.log('权限状态变化:', result);
});
// 获取当前权限状态
const status = sdk.getPermissionStatus();
console.log('麦克风:', status.microphone);
console.log('TTS:', status.tts);
// 获取麦克风权限引导信息
const guidance = await sdk.getMicrophonePermissionGuidance();
if (guidance.guidance) {
console.log('浏览器:', guidance.guidance.browser);
console.log('操作步骤:', guidance.guidance.steps);
}
`🎤 麦克风权限管理(旧 API,仍然可用)
SDK 提供了完整的麦克风权限检测和引导功能,帮助处理用户拒绝权限的情况。
$3
`typescript
enum MicrophonePermissionState {
GRANTED = 'granted', // 已授权
DENIED = 'denied', // 已拒绝
PROMPT = 'prompt', // 待询问(用户尚未做出选择)
UNKNOWN = 'unknown' // 未知(浏览器不支持权限查询)
}
`$3
`typescript
interface MicrophonePermissionInfo {
state: MicrophonePermissionState; // 权限状态
canRequest: boolean; // 是否可以请求权限
isDenied: boolean; // 是否已被拒绝
isGranted: boolean; // 是否已授权
guidance?: MicrophonePermissionGuidance; // 引导信息(权限被拒绝时提供)
}interface MicrophonePermissionGuidance {
browser: string; // 浏览器类型
title: string; // 引导标题
steps: string[]; // 操作步骤
settingsUrl?: string; // 设置页面 URL(部分浏览器支持)
}
`$3
`javascript
// 检查麦克风权限状态
const permissionInfo = await sdk.checkMicrophonePermission();
console.log('权限状态:', permissionInfo.state);
console.log('是否已授权:', permissionInfo.isGranted);
console.log('是否已拒绝:', permissionInfo.isDenied);
console.log('是否可请求:', permissionInfo.canRequest);// 请求麦克风权限(如果之前被拒绝,不会弹出授权窗口)
const result = await sdk.requestMicrophonePermission();
if (result.isDenied) {
// 显示引导信息
console.log(result.guidance.steps.join('\n'));
}
// 监听权限状态变化
sdk.onMicrophonePermissionChange((state) => {
if (state === 'granted') {
console.log('权限已授予,可以启动');
sdk.start();
} else if (state === 'denied') {
console.log('权限被拒绝');
}
});
// 获取权限引导信息
const info = await sdk.getMicrophonePermissionGuidance();
if (info.guidance) {
console.log(
${info.guidance.browser} 浏览器操作指引:);
info.guidance.steps.forEach(step => console.log(step));
}
`$3
`javascript
async function startWithPermissionCheck() {
const sdk = new EchoSDK({ debug: true });
// 1. 先检查权限状态
const permissionInfo = await sdk.checkMicrophonePermission();
if (permissionInfo.isDenied) {
// 2. 权限已被拒绝,显示引导
const guidance = permissionInfo.guidance;
showPermissionGuideModal({
title: guidance.title,
steps: guidance.steps,
browser: guidance.browser
});
return;
}
// 3. 监听权限变化(用户可能在设置中修改)
sdk.onMicrophonePermissionChange((state) => {
if (state === 'granted') {
hidePermissionGuideModal();
sdk.start();
}
});
// 4. 监听错误事件
sdk.on('error', (error) => {
if (error.type === 'permission_error') {
const info = error.originalError?.permissionInfo;
if (info?.guidance) {
showPermissionGuideModal({
title: info.guidance.title,
steps: info.guidance.steps,
browser: info.guidance.browser
});
}
}
});
// 5. 初始化并启动
try {
await sdk.init();
await sdk.start();
} catch (error) {
if (error.permissionInfo) {
// 权限错误已在 error 事件中处理
} else {
console.error('启动失败:', error);
}
}
}
`🎯 Vosk 模型
本 SDK 使用 Vosk 进行离线语音识别,中文模型已内置在 npm 包中,无需单独下载。
$3
通过 npm 安装后,模型文件位于
node_modules/echo-voice-sdk/models/vosk-model-cn.tar.gz。你需要将模型文件复制到你的静态资源目录(如
public/models/),然后在配置中指定路径:`javascript
const sdk = new EchoSDK({
speechRecognition: {
voskModelPath: '/models/vosk-model-cn.tar.gz'
}
});
`#### Vite 项目配置示例
`javascript
// vite.config.js
import { defineConfig } from 'vite';
import { copyFileSync, mkdirSync, existsSync } from 'fs';export default defineConfig({
plugins: [{
name: 'copy-vosk-model',
buildStart() {
const modelSrc = 'node_modules/echo-voice-sdk/models/vosk-model-cn.tar.gz';
const modelDest = 'public/models/vosk-model-cn.tar.gz';
if (!existsSync('public/models')) {
mkdirSync('public/models', { recursive: true });
}
if (existsSync(modelSrc)) {
copyFileSync(modelSrc, modelDest);
}
}
}]
});
`#### Webpack 项目配置示例
`javascript
// webpack.config.js
const CopyPlugin = require('copy-webpack-plugin');module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: 'node_modules/echo-voice-sdk/models/vosk-model-cn.tar.gz',
to: 'models/vosk-model-cn.tar.gz'
}
]
})
]
};
`$3
如果不想在项目中包含模型文件,也可以使用 CDN:
`javascript
const sdk = new EchoSDK({
speechRecognition: {
voskModelPath: 'https://your-cdn.com/vosk-model-cn.tar.gz'
}
});
`> ⚠️ 注意:模型文件约 42MB,首次加载需要一定时间。建议配置浏览器缓存以提升后续加载速度。
🛠️ 开发
`bash
安装依赖
npm install开发模式
npm run dev构建
npm run build运行 Demo
npm run demo
`📁 项目结构
`
YZ_EchoSDK/
├── src/
│ ├── core/
│ │ ├── EchoSDK.ts # SDK 主类
│ │ └── EventManager.ts # 事件管理器
│ ├── modules/
│ │ ├── AudioProcessor.ts # 音频处理器
│ │ ├── VADDetector.ts # VAD 检测器
│ │ ├── SpeechRecognizer.ts # Vosk 语音识别
│ │ ├── CommandParser.ts # 指令解析器(含拼音匹配)
│ │ ├── VoiceprintRecognizer.ts # 声纹识别器
│ │ ├── WakeWordDetector.ts # 唤醒词检测器
│ │ ├── TTSSpeaker.ts # TTS 语音合成
│ │ └── PermissionManager.ts # 权限管理器
│ ├── utils/
│ │ └── PinyinUtils.ts # 拼音工具类(pinyin-pro)
│ ├── types/
│ │ └── index.ts # 类型定义
│ └── index.ts # 入口文件
├── modules/
│ ├── vosk-model-small-cn-0.22/ # Vosk 中文模型
│ └── vosk-model-cn.tar.gz # 打包后的模型
├── examples/
│ ├── demo.html # 基础语音识别演示(Vosk + 指令 + 声纹 + 唤醒词)
│ ├── demo-sdk.html # SDK 完整功能演示(含拼音匹配)
│ ├── demo-voiceprint.html # 声纹识别专项演示(录制、注册、识别)
│ ├── demo-permission.html # 权限管理演示(自动检查、请求、引导)
│ ├── demo-accuracy.html # 识别准确度优化演示
│ ├── test-tts-fix.html # TTS 修复测试页面(新增)
│ └── server-example/ # 服务端示例
├── dist/ # 构建输出
└── package.json
`🐛 常见问题
$3
问题描述:在浏览器中使用 TTS 语音合成,播放一次后再次调用或刷新页面都无法播放。
原因:这是浏览器
speechSynthesis API 的已知 bug,特别是在 Chrome 浏览器中。如果不正确处理状态,语音合成会"卡住"。解决方案:SDK v1.5.1 已修复此问题,主要改进:
1. 播放前清理状态:在每次播放前调用
cancel() 清理浏览器状态
2. 延迟调用:使用 setTimeout 延迟调用 speak(),避免竞态条件
3. 完全清理:在 stop() 和 destroy() 中确保完全清理状态如果仍有问题,可以尝试:
`javascript
// 手动重置 speechSynthesis
window.speechSynthesis.cancel();// 然后再调用 SDK 的 speak 方法
await sdk.speak('你好');
`$3
问题描述:用户拒绝麦克风权限后,无法再次请求。
解决方案:
1. SDK 会自动检测权限状态并显示引导弹窗
2. 用户需要在浏览器设置中手动开启权限
3. 使用
checkMicrophonePermission() 检查权限状态
4. 使用 requestPermissions() 请求权限(带引导)`javascript
// 检查权限
const permissionInfo = await sdk.checkMicrophonePermission();
if (permissionInfo.state === 'denied') {
console.log('权限被拒绝,请按以下步骤操作:');
console.log(permissionInfo.guidance.steps);
}// 请求权限(带弹窗引导)
await sdk.requestPermissions({
showDialog: true,
dialogTitle: '需要麦克风权限',
dialogMessage: '请允许使用麦克风以启用语音功能'
});
`$3
问题描述:提示 "Failed to load model" 或模型加载超时。
解决方案:
1. 确保模型文件路径正确(默认
/models/vosk-model-cn.tar.gz)
2. 检查模型文件是否存在且完整(约 42MB)
3. 检查服务器 MIME 类型配置(应为 application/gzip)
4. 首次加载需要 10-30 秒,请耐心等待`javascript
// 自定义模型路径
const sdk = new EchoSDK({
speechRecognition: {
voskModelPath: '/your-path/vosk-model-cn.tar.gz'
}
});
`$3
问题描述:语音识别结果不准确,或指令匹配失败。
解决方案:
1. 启用拼音匹配:解决同音字问题
2. 启用同义词匹配:识别同义词表达
3. 启用关键词提取:优化短句匹配
4. 调整匹配阈值:降低阈值提高匹配成功率
`javascript
// 启用所有优化功能
sdk.enablePinyinMatch();
sdk.enableSynonymMatch();
sdk.enableKeywordExtraction();// 调整拼音匹配阈值(默认 0.7)
sdk.setPinyinMatchThreshold(0.6);
// 添加自定义同义词
sdk.addSynonymGroup('飞行', ['飞', '起飞', '飞起来']);
`详细优化指南请查看:识别准确度优化文档
$3
问题描述:说了唤醒词但系统没有响应。
解决方案:
1. 调整灵敏度:降低灵敏度阈值
2. 启用模糊匹配:允许一定的识别误差
3. 添加多个唤醒词:增加唤醒成功率
`javascript
// 降低灵敏度阈值(0-1,越小越灵敏)
sdk.setWakeWordSensitivity(0.5);// 启用模糊匹配
sdk.setWakeWordFuzzyMatch(true);
// 添加多个唤醒词
sdk.setWakeWords(['小云小云', '你好小云', '嘿小云']);
`$3
问题描述:声纹识别匹配失败或误识别。
解决方案:
1. 录入时长充足:确保录入时长至少 3-5 秒
2. 环境安静:录入时保持环境安静,减少噪音
3. 多次录入:为同一用户录入多个样本
4. 调整阈值:根据实际情况调整匹配阈值
`javascript
// 调整声纹匹配阈值(0-1,越高要求越严格)
sdk.setVoiceprintThreshold(0.8);// 为用户添加多个声纹样本
await sdk.addVoiceprintSample(voiceprintId, audioData);
`$3
支持的浏览器:
- ✅ Chrome 90+
- ✅ Edge 90+
- ✅ Safari 14+
- ✅ Firefox 88+
- ❌ IE(不支持)
注意事项:
1. Safari 对 Web Speech API 支持有限,TTS 功能可能受限
2. Firefox 的
speechSynthesis 实现与 Chrome 略有不同
3. 移动端浏览器支持情况因系统而异$3
问题描述:SDK 运行时占用资源较多。
优化建议:
1. 按需启用功能:不需要的功能可以禁用
2. 调整缓冲区大小:减小
bufferSize 可降低延迟但增加 CPU 占用
3. 使用较小的模型:如果对准确度要求不高,可使用更小的 Vosk 模型
4. 限制声纹数量:声纹识别的计算量与声纹数量成正比`javascript
const sdk = new EchoSDK({
bufferSize: 2048, // 减小缓冲区(默认 4096)
voiceprint: {
enabled: false // 不需要时禁用声纹识别
},
wakeWord: {
enabled: false // 不需要时禁用唤醒词
}
});
``MIT License