sk-voice-command
v1.0.3
Published
语音指令控制和自动化操作
Maintainers
Readme
sk-voice-command
阿里云语音识别指令模块 for uni-app
一个零依赖的 Vue 2 语音指令模块,基于阿里云实时语音识别技术,让你的 uni-app 应用支持语音控制。
✨ 特性
- 🎤 实时语音识别 - 基于阿里云"一句话识别",低延迟高准确率
- 🎯 智能指令匹配 - 支持模糊匹配,自动识别用户意图
- 🔌 零依赖 - 不依赖 Vuex、uni-ui 等第三方库
- 📦 即插即用 - 5 分钟完成集成
- 📱 跨平台 - 支持微信小程序、H5、App
📦 安装
npm install sk-voice-command🚀 快速开始
1. 安装插件
在 main.js 中注册插件:
import Vue from 'vue'
import SkVoiceCommand from 'sk-voice-command'
Vue.use(SkVoiceCommand, {
// 必需配置
appkey: 'your-aliyun-appkey',
tokenUrl: 'https://your-api.com/api/aliyun/token',
// 可选配置
matchThreshold: 0.8, // 匹配阈值(默认 0.8)
confirmThreshold: 0.6, // 确认阈值(默认 0.6)
enableIntermediateResult: true,// 启用中间结果(默认 true)
debug: false // 调试模式(默认 false)
})2. 注册指令
在 App.vue 中注册全局指令,或在页面组件中注册页面指令。详细的使用示例请参考下方的 registerCommands 方法文档。
3. 使用
export default {
methods: {
// 开始录音
async startVoice() {
try {
await this.$voice.start()
console.log('开始录音')
} catch (error) {
console.error('启动失败:', error)
}
},
// 停止录音
async stopVoice() {
const result = await this.$voice.stop()
console.log('识别结果:', result)
// result.text - 识别文本
// result.matched - 是否匹配到指令
// result.command - 匹配的指令
// result.similarity - 相似度
},
// 手动匹配指令(用于测试)
testMatch(text) {
const result = this.$voice.matchCommand(text)
if (result.matched) {
this.$voice.executeCommand(result.command)
}
}
}
}📚 API 文档
插件配置选项
| 参数 | 类型 | 必需 | 默认值 | 说明 | |------|------|------|--------|------| | appkey | String | ✅ | - | 阿里云 AppKey | | tokenUrl | String | ✅ | - | Token 获取接口地址 | | matchThreshold | Number | ❌ | 0.8 | 自动执行阈值(0-1) | | confirmThreshold | Number | ❌ | 0.6 | 确认执行阈值(0-1) | | enableIntermediateResult | Boolean | ❌ | true | 是否启用中间结果 | | debug | Boolean | ❌ | false | 调试模式 |
实例方法
registerCommands(options)
注册指令
this.$voice.registerCommands({
scope: 'page', // 'page' 或 'global'
route: 'pages/index/index', // 路由路径(scope 为 page 时可用,可选)
commands: [
{
id: 'command-id', // 唯一标识(必需)
keywords: ['关键词1', '关键词2'], // 关键词数组(必需)
action: () => {}, // 执行函数(必需)
description: '指令描述', // 描述(可选)
weight: 10 // 权重(可选,默认 0)
}
]
})参数说明:
scope(string) - 作用域:'page'(页面指令) |'global'(全局指令)route(string) - 路由路径(仅 scope 为 page 时使用)- 指定该指令属于哪个页面
- 如果不传,则使用当前的
currentRoute - 可以在任意页面为其他页面预注册指令
commands(array) - 指令数组
使用示例:
// 方式 1: 在页面中注册(推荐)
export default {
mounted() {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
this.$voice.registerCommands({
scope: 'page',
route: currentPage.route, // 指定当前页面路由
commands: [
{
id: 'submit-form',
keywords: ['提交', '确认提交'],
action: () => this.submitForm()
}
]
})
}
}
// 方式 2: 在 App.vue 中为所有页面预注册指令
export default {
onLaunch() {
// 为首页注册指令
this.$voice.registerCommands({
scope: 'page',
route: 'pages/index/index',
commands: [
{
id: 'refresh-list',
keywords: ['刷新列表', '重新加载'],
action: () => {
// 首页刷新逻辑
}
}
]
})
// 为用户页注册指令
this.$voice.registerCommands({
scope: 'page',
route: 'pages/user/user',
commands: [
{
id: 'edit-profile',
keywords: ['修改资料', '编辑信息'],
action: () => {
// 用户页编辑逻辑
}
}
]
})
// 注册全局指令
this.$voice.registerCommands({
scope: 'global',
commands: [
{
id: 'go-home',
keywords: ['返回首页', '回到主页'],
action: () => uni.switchTab({ url: '/pages/index/index' })
}
]
})
}
}
// 方式 3: 向后兼容(不传 route,使用 currentRoute)
export default {
mounted() {
// 先设置当前路由
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
this.$voice._matcher.setCurrentRoute(currentPage.route)
// 然后注册指令(会自动使用 currentRoute)
this.$voice.registerCommands({
scope: 'page',
commands: [
{
id: 'submit-form',
keywords: ['提交'],
action: () => this.submitForm()
}
]
})
}
}指令作用域规则:
- ✅ 页面指令 - 只在指定页面生效,优先级高于全局指令
- ✅ 全局指令 - 在所有页面生效
- ✅ 优先级 - 页面指令 > 全局指令
- ⚠️ 未设置路由 - 如果未指定路由且未设置
currentRoute,页面指令不会被匹配
unregisterCommands(scope)
注销指令
this.$voice.unregisterCommands('page') // 注销页面指令
this.$voice.unregisterCommands('global') // 注销全局指令start()
开始语音识别
await this.$voice.start()stop()
停止语音识别
const result = await this.$voice.stop()
// result.text - 识别文本
// result.matched - 是否匹配
// result.command - 匹配的指令
// result.similarity - 相似度(0-1)
// result.weight - 指令权重
// result.action - 'auto' | 'confirm' | 'reject'
// result.matchedKeyword - 匹配的关键词
// result.allMatches - 所有匹配结果(调试用)matchCommand(text, options?)
手动匹配指令(用于测试)
// 默认使用相似度匹配
const result = this.$voice.matchCommand('测试文本')
// 使用基于位置的匹配(新增)
const result = this.$voice.matchCommand('帮我提交然后返回首页', { mode: 'position' })
if (result.matched) {
this.$voice.executeCommand(result.command)
}参数:
text(string) - 要匹配的文本options.mode(string) - 匹配模式:'similarity'(默认) |'position'options.caseSensitive(boolean) - 是否区分大小写(仅 position 模式)
matchCommandInText(text, options?)
从文本中识别第一个匹配的指令(基于关键词位置)⚡ 高性能
const result = this.$voice.matchCommandInText('帮我提交然后返回首页')
// result.matched - 是否匹配
// result.command - 匹配的指令
// result.position - 关键词在文本中的位置
// result.matchedText - 匹配的关键词文本
// result.weight - 指令权重
if (result.matched) {
console.log(`找到指令: ${result.matchedText}, 位置: ${result.position}`)
this.$voice.executeCommand(result.command)
}参数:
text(string) - 要搜索的文本options.caseSensitive(boolean) - 是否区分大小写,默认 false
匹配策略:
- 遍历所有已注册的关键词
- 在文本中搜索每个关键词的首次出现位置
- 返回最早出现的关键词对应的指令
- 支持大小写不敏感匹配
性能优势:
- 使用
indexOf字符串搜索,时间复杂度 O(n×m) - 比相似度匹配快 2-5 倍
- 典型场景(50关键词×200字)< 0.02ms
- 极限场景(100关键词×500字)< 0.05ms
executeCommand(command)
执行指令
this.$voice.executeCommand(command)状态对象
通过 this.$voice.state 访问:
{
isRecording: false, // 是否正在录音
recognitionText: '', // 识别文本
lastCommand: null, // 最后执行的指令
error: null, // 错误信息
status: 'idle', // 当前状态
recordDuration: 0, // 录音时长(毫秒)
isRecognizing: false // 是否正在识别
}事件监听
// 监听状态变化
this.$voice.on('state-change', (state) => {
console.log('状态变化:', state)
})
// 监听录音开始
this.$voice.on('recording-started', () => {
console.log('开始录音')
})
// 监听录音停止
this.$voice.on('recording-stopped', (result) => {
console.log('识别结果:', result)
})
// 移除监听
this.$voice.off('state-change', callback)🔧 高级用法
全局指令
在 App.vue 中注册全局指令:
export default {
onLaunch() {
this.$voice.registerCommands({
scope: 'global',
commands: [
{
id: 'go-home',
keywords: ['返回首页', '回到主页'],
action: () => {
uni.switchTab({ url: '/pages/index/index' })
},
description: '返回首页'
}
]
})
}
}指令优先级
- 页面指令 > 全局指令
- 当页面指令和全局指令有相同关键词时,优先执行页面指令
- 权重优先级:当多个指令相似度相同或相近(差异 ≤ 5%)时,优先执行权重高的指令
匹配策略
- 相似度 ≥ 80%: 自动执行
- 60% ≤ 相似度 < 80%: 弹出确认对话框
- 相似度 < 60%: 提示未识别,不执行
权重系统
权重用于处理多个指令相似度接近的情况:
// 示例:三个指令相似度都在 85%-90% 之间
{
id: 'command-a',
keywords: ['提交'],
action: () => console.log('A'),
weight: 10 // 权重最高,优先执行
}
{
id: 'command-b',
keywords: ['确认'],
action: () => console.log('B'),
weight: 5
}
{
id: 'command-c',
keywords: ['发送'],
action: () => console.log('C'),
weight: 8
}权重规则:
- 默认权重为 0
- 当多个指令相似度差异 ≤ 5% 时,按权重降序排列
- 权重越高,优先级越高
📝 配置 Token 获取接口
模块需要提供一个 Token 获取接口,返回阿里云访问 Token:
// 示例:后端接口
GET /api/aliyun/token
Response:
{
"token": "your-aliyun-token"
}后端实现示例(Node.js):
const Core = require('@alicloud/pop-core')
// 获取 Token
async function getToken() {
const client = new Core({
accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,
accessKeySecret: process.env.ALIYUN_ACCESS_KEY_SECRET,
endpoint: 'https://nls-meta.cn-shanghai.aliyuncs.com',
apiVersion: '2019-02-28'
})
const params = {
"Action": "CreateToken"
}
const result = await client.request('POST', params)
return result.Token.Id
}🌐 微信小程序配置
在微信小程序后台配置以下合法域名:
request: https://nls-meta.cn-shanghai.aliyuncs.com
socket: wss://nls-gateway-cn-shanghai.aliyuncs.com🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可证
🔗 相关链接
💡 常见问题
1. 如何获取阿里云 AppKey?
- 访问 阿里云控制台
- 开通"智能语音交互"服务
- 创建项目并获取 AppKey
2. Token 如何获取?
推荐方式:通过后端接口获取,避免暴露 AccessKey。
开发测试:可以使用 AccessKey 直接获取(不推荐生产环境)。
3. 支持哪些平台?
- ✅ 微信小程序
- ✅ H5
- ✅ Android App
- ✅ iOS App
4. 指令匹配不准确怎么办?
- 调整
matchThreshold和confirmThreshold配置 - 为指令添加更多关键词同义词
- 启用
debug: true查看匹配详情
Made with ❤️ by sk-voice-command team
