当前位置: 首页 > news >正文

【UNI-APP】阿里NLS一句话听写typescript模块

阿里提供的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 = 3000interface INlsConfig {url?: stringappkey: string // 应用的keytoken: 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 = falseenum 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 = confconsole.log(`connected to ${NLS_SERVER_URL} success`)},fail: (res) => {console.log(`connect to ${NLS_SERVER_URL} failed:${res.errMsg}`)}})client.readyState = WsState.CONNECTINGclient.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?.resultif (text) {recognizedCallback(text)}}console.log('changed')break}case 'RecognitionCompleted': {const text = msgObj?.payload?.resultif (text) {recognizedCallback(text)}taskStarted = false // 结束识别break}case 'TaskFailed': {taskStarted = false // 结束识别break}}}console.log('recv:' + res.data)})client.onOpen(() => {reconnectAttempts = 0client.readyState = WsState.OPENif (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.CLOSEDconsole.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/140267684icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/140267684

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • web后端开发--请求响应
  • QT开发积累——qt中的注释和多行注释的几种方式,函数方法注释生成
  • 阿里云ecs服务器,nginx多域名多项目部署教程,含本地部署教程
  • pytest使用报错(以及解决pytest所谓的“抑制print输出”)
  • 在AvaotaA1全志T527开发板上使用AvaotaOS 部署 Docker 服务
  • 使用Ultralytics YOLO进行模型验证
  • 测试狗:“微观结构表征+理论计算”助力《Science》论文发表
  • 双向链表 -- 详细理解和实现
  • 51单片机(STC8051U34K64)_RA8889_SPI4参考代码(v1.3)
  • VIM模式之间的切换
  • 深圳比创达|EMC与EMI测试整改:打造电磁“绿色”产品的必经之路4
  • virturalBox+K8S部署jaeger-all-in-one
  • CentOS 6.5配置国内在线yum源和制作openssh 9.8p1 rpm包 —— 筑梦之路
  • 跨域解决方案处理
  • 【Linux网络】IP协议{初识/报头/分片/网段划分/子网掩码/私网公网IP/认识网络世界/路由表}
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • android图片蒙层
  • angular2开源库收集
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • Java Agent 学习笔记
  • Java应用性能调优
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Linux后台研发超实用命令总结
  • PAT A1017 优先队列
  • React Transition Group -- Transition 组件
  • react 代码优化(一) ——事件处理
  • 阿里研究院入选中国企业智库系统影响力榜
  • 彻底搞懂浏览器Event-loop
  • 猴子数据域名防封接口降低小说被封的风险
  • 记一次和乔布斯合作最难忘的经历
  • 排序算法之--选择排序
  • 嵌入式文件系统
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 移动端解决方案学习记录
  • 智能合约Solidity教程-事件和日志(一)
  • ​flutter 代码混淆
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​油烟净化器电源安全,保障健康餐饮生活
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #职场发展#其他
  • $().each和$.each的区别
  • (Forward) Music Player: From UI Proposal to Code
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (三)c52学习之旅-点亮LED灯
  • (四)Android布局类型(线性布局LinearLayout)
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (图)IntelliTrace Tools 跟踪云端程序
  • (万字长文)Spring的核心知识尽揽其中
  • (转)c++ std::pair 与 std::make
  • (转)Oracle存储过程编写经验和优化措施
  • (转)我也是一只IT小小鸟
  • .gitignore文件设置了忽略但不生效