阿里提供的demo代码都是javascript,自己捏个轮子。参考着自己写了一个阿里巴巴一句话听写Nls的typescript模块。VUE3的组合式API形式
startClient:开始听写,注意下一步要尽快开启识别和传数据,否则6秒后会关闭
startRecognition:开始识别事务,传入识别回调,可以打印字符或显示到屏幕
sendSound:发送二进制PCM数据(格式16MHz16bit)
stopRecognition:结束识别事务
/**
* 阿里语音,一句话识别模块for ccframe
*
* 无心跳设计,非长连接推送,因此在需要使用的时候才进行连接
*
* @Jim 2024/07/08
*/
import * as utils from '@/utils/index'
import { nextTick } from 'vue'
// import Global from '@/utils/constants'
const NLS_SERVER_URL = 'wss://nls-gateway.aliyuncs.com/ws/v1'
const NLS_MODE = 'SpeechRecognizer' // 一句话识别
const WEBSOCKET_MAX_RETRY = 3
const RECONNECT_INTERVAL = 3000
interface INlsConfig {
url?: string
appkey: string // 应用的key
token: string // 从服务器获得,要缓存
}
let client: (UniNamespace.SocketTask & { readyState?: WsState }) | undefined
const clientId = utils.uuid(utils.UUIDFormat.StandardCompact)
let taskId: string = ''
let config: INlsConfig
let reconnectAttempts = 0
let taskStarted = false
enum WsState {
CONNECTING,
OPEN,
CLOSING,
CLOSED
}
/**
*
* @param action
* @returns 请求json
*/
const buildMsg: (action: string, payload: Record<string, any>) => string = (
action,
payload = {}
) => {
if (taskId.length === 0) {
taskId = utils.uuid(utils.UUIDFormat.StandardCompact)
}
const msg = {
header: {
message_id: utils.uuid(utils.UUIDFormat.StandardCompact),
task_id: taskId,
namespace: NLS_MODE,
name: action,
appkey: config.appkey
},
payload,
context: {
sdk: {
name: 'nls-wx-sdk',
version: '0.0.1',
language: 'wxjs'
}
}
}
return JSON.stringify(msg, null, 0)
}
/**
* 开启连接,开启后立即要传,否则会被关闭.
* @param config
* @param callback
*/
export const startClient = (
conf?: INlsConfig,
startCallback?: () => void,
recognizedCallback?: (text: string) => void
) => {
if (client && client.readyState !== WsState.CLOSED) {
// 关闭原连接
client.close({})
}
client = uni.connectSocket({
url: conf.url ?? NLS_SERVER_URL,
tcpNoDelay: true,
header: {
'X-NLS-Token': conf?.token ?? config.token
},
success: (res) => {
if (!config) config = conf
console.log(`connected to ${NLS_SERVER_URL} success`)
},
fail: (res) => {
console.log(`connect to ${NLS_SERVER_URL} failed:${res.errMsg}`)
}
})
client.readyState = WsState.CONNECTING
client.onMessage((res) => {
if (typeof res.data === 'string') {
const msgObj = JSON.parse(res.data)
switch (msgObj?.header?.name) {
case 'RecognitionStarted': {
console.log('started')
break
}
case 'RecognitionResultChanged': {
if (recognizedCallback) {
const text = msgObj?.payload?.result
if (text) {
recognizedCallback(text)
}
}
console.log('changed')
break
}
case 'RecognitionCompleted': {
const text = msgObj?.payload?.result
if (text) {
recognizedCallback(text)
}
taskStarted = false // 结束识别
break
}
case 'TaskFailed': {
taskStarted = false // 结束识别
break
}
}
}
console.log('recv:' + res.data)
})
client.onOpen(() => {
reconnectAttempts = 0
client.readyState = WsState.OPEN
if (startCallback) nextTick(startCallback)
})
client.onError((error) => {
console.error('WebSocket error:', error)
if (reconnectAttempts < WEBSOCKET_MAX_RETRY) {
setTimeout(() => startClient(), RECONNECT_INTERVAL)
} else {
console.error('Max reconnect attempts reached')
}
})
client.onClose(() => {
client.readyState = WsState.CLOSED
console.log('connection closed')
})
}
export const startRecognition = () => {
if (client && client.readyState === WsState.OPEN)
client.send({
data: buildMsg('StartRecognition', {
format: 'opus',
sample_rate: 16000,
enable_intermediate_result: true,
enable_punctuation_prediction: true,
enable_inverse_text_normalization: true
}),
success: (res) => {
taskStarted = true
}
})
}
export const stopRecognition = () => {
if (client && client.readyState === WsState.OPEN)
client.send({
data: buildMsg('StopRecognition', {
format: 'opus',
sample_rate: 16000,
enable_intermediate_result: true,
enable_punctuation_prediction: true,
enable_inverse_text_normalization: true
}),
complete: () => {
taskStarted = false // 不管是否成功,都不发送音频了
}
})
}
export const sendSound = (msgBytes: ArrayBuffer) => {
if (client && client.readyState === WsState.OPEN && taskStarted)
client.send({
data: msgBytes,
success: (res) => {
console.log('send ' + msgBytes.byteLength + ' success')
}
})
}
util的uuid工具见我前一篇文章https://mp.csdn.net/mp_blog/creation/editor/140267684https://mp.csdn.net/mp_blog/creation/editor/140267684