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


    阿里提供的demo代码都是javascript,自己捏个轮子。参考着自己写了一个阿里巴巴一句话听写Nls的typescript模块。VUE3的组合式API形式

    startClient:开始听写,注意下一步要尽快开启识别和传数据,否则6秒后会关闭

    startRecognition:开始识别事务,传入识别回调,可以打印字符或显示到屏幕

    sendSound:发送二进制PCM数据(格式16MHz16bit)

    stopRecognition:结束识别事务

    1. /**
    2. * 阿里语音,一句话识别模块for ccframe
    3. *
    4. * 无心跳设计,非长连接推送,因此在需要使用的时候才进行连接
    5. *
    6. * @Jim 2024/07/08
    7. */
    8. import * as utils from '@/utils/index'
    9. import { nextTick } from 'vue'
    10. // import Global from '@/utils/constants'
    11. const NLS_SERVER_URL = 'wss://nls-gateway.aliyuncs.com/ws/v1'
    12. const NLS_MODE = 'SpeechRecognizer' // 一句话识别
    13. const WEBSOCKET_MAX_RETRY = 3
    14. const RECONNECT_INTERVAL = 3000
    15. interface INlsConfig {
    16. url?: string
    17. appkey: string // 应用的key
    18. token: string // 从服务器获得,要缓存
    19. }
    20. let client: (UniNamespace.SocketTask & { readyState?: WsState }) | undefined
    21. const clientId = utils.uuid(utils.UUIDFormat.StandardCompact)
    22. let taskId: string = ''
    23. let config: INlsConfig
    24. let reconnectAttempts = 0
    25. let taskStarted = false
    26. enum WsState {
    27. CONNECTING,
    28. OPEN,
    29. CLOSING,
    30. CLOSED
    31. }
    32. /**
    33. *
    34. * @param action
    35. * @returns 请求json
    36. */
    37. const buildMsg: (action: string, payload: Record<string, any>) => string = (
    38. action,
    39. payload = {}
    40. ) => {
    41. if (taskId.length === 0) {
    42. taskId = utils.uuid(utils.UUIDFormat.StandardCompact)
    43. }
    44. const msg = {
    45. header: {
    46. message_id: utils.uuid(utils.UUIDFormat.StandardCompact),
    47. task_id: taskId,
    48. namespace: NLS_MODE,
    49. name: action,
    50. appkey: config.appkey
    51. },
    52. payload,
    53. context: {
    54. sdk: {
    55. name: 'nls-wx-sdk',
    56. version: '0.0.1',
    57. language: 'wxjs'
    58. }
    59. }
    60. }
    61. return JSON.stringify(msg, null, 0)
    62. }
    63. /**
    64. * 开启连接,开启后立即要传,否则会被关闭.
    65. * @param config
    66. * @param callback
    67. */
    68. export const startClient = (
    69. conf?: INlsConfig,
    70. startCallback?: () => void,
    71. recognizedCallback?: (text: string) => void
    72. ) => {
    73. if (client && client.readyState !== WsState.CLOSED) {
    74. // 关闭原连接
    75. client.close({})
    76. }
    77. client = uni.connectSocket({
    78. url: conf.url ?? NLS_SERVER_URL,
    79. tcpNoDelay: true,
    80. header: {
    81. 'X-NLS-Token': conf?.token ?? config.token
    82. },
    83. success: (res) => {
    84. if (!config) config = conf
    85. console.log(`connected to ${NLS_SERVER_URL} success`)
    86. },
    87. fail: (res) => {
    88. console.log(`connect to ${NLS_SERVER_URL} failed:${res.errMsg}`)
    89. }
    90. })
    91. client.readyState = WsState.CONNECTING
    92. client.onMessage((res) => {
    93. if (typeof res.data === 'string') {
    94. const msgObj = JSON.parse(res.data)
    95. switch (msgObj?.header?.name) {
    96. case 'RecognitionStarted': {
    97. console.log('started')
    98. break
    99. }
    100. case 'RecognitionResultChanged': {
    101. if (recognizedCallback) {
    102. const text = msgObj?.payload?.result
    103. if (text) {
    104. recognizedCallback(text)
    105. }
    106. }
    107. console.log('changed')
    108. break
    109. }
    110. case 'RecognitionCompleted': {
    111. const text = msgObj?.payload?.result
    112. if (text) {
    113. recognizedCallback(text)
    114. }
    115. taskStarted = false // 结束识别
    116. break
    117. }
    118. case 'TaskFailed': {
    119. taskStarted = false // 结束识别
    120. break
    121. }
    122. }
    123. }
    124. console.log('recv:' + res.data)
    125. })
    126. client.onOpen(() => {
    127. reconnectAttempts = 0
    128. client.readyState = WsState.OPEN
    129. if (startCallback) nextTick(startCallback)
    130. })
    131. client.onError((error) => {
    132. console.error('WebSocket error:', error)
    133. if (reconnectAttempts < WEBSOCKET_MAX_RETRY) {
    134. setTimeout(() => startClient(), RECONNECT_INTERVAL)
    135. } else {
    136. console.error('Max reconnect attempts reached')
    137. }
    138. })
    139. client.onClose(() => {
    140. client.readyState = WsState.CLOSED
    141. console.log('connection closed')
    142. })
    143. }
    144. export const startRecognition = () => {
    145. if (client && client.readyState === WsState.OPEN)
    146. client.send({
    147. data: buildMsg('StartRecognition', {
    148. format: 'opus',
    149. sample_rate: 16000,
    150. enable_intermediate_result: true,
    151. enable_punctuation_prediction: true,
    152. enable_inverse_text_normalization: true
    153. }),
    154. success: (res) => {
    155. taskStarted = true
    156. }
    157. })
    158. }
    159. export const stopRecognition = () => {
    160. if (client && client.readyState === WsState.OPEN)
    161. client.send({
    162. data: buildMsg('StopRecognition', {
    163. format: 'opus',
    164. sample_rate: 16000,
    165. enable_intermediate_result: true,
    166. enable_punctuation_prediction: true,
    167. enable_inverse_text_normalization: true
    168. }),
    169. complete: () => {
    170. taskStarted = false // 不管是否成功,都不发送音频了
    171. }
    172. })
    173. }
    174. export const sendSound = (msgBytes: ArrayBuffer) => {
    175. if (client && client.readyState === WsState.OPEN && taskStarted)
    176. client.send({
    177. data: msgBytes,
    178. success: (res) => {
    179. console.log('send ' + msgBytes.byteLength + ' success')
    180. }
    181. })
    182. }

    util的uuid工具见我前一篇文章https://mp.csdn.net/mp_blog/creation/editor/140267684icon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor/140267684

  • 相关阅读:
    计算机网络的故事——确保Web安全的Https
    #智能小车项目(五)MPU9250初始化
    Leetcode算法题
    Python Web开发02-django创建图书管理项目
    DNS 系列(一):为什么更新了 DNS 记录不生效?
    JVM系列:JDK、JRE、JVM 的关系
    ubuntu安装配置mysql
    Ansible-任务执行控制
    【从零开始学习 SystemVerilog】8.5、SystemVerilog 约束—— Constraint Examples(约束示例)
    冒泡排序和选择排序的小乐趣
  • 原文地址:https://blog.csdn.net/applebomb/article/details/140320469