Showing
20 changed files
with
1059 additions
and
5 deletions
| @@ -888,4 +888,11 @@ export class HttpUrlUtils { | @@ -888,4 +888,11 @@ export class HttpUrlUtils { | ||
| 888 | let url = HttpUrlUtils.getHost() + HttpUrlUtils.VISITOR_COMMENT_LIST_DATA_PATH | 888 | let url = HttpUrlUtils.getHost() + HttpUrlUtils.VISITOR_COMMENT_LIST_DATA_PATH |
| 889 | return url | 889 | return url |
| 890 | } | 890 | } |
| 891 | + | ||
| 892 | + ///获取语音识别授权token | ||
| 893 | + static getVoiceRecognizerSDKAuthToken() { | ||
| 894 | + let url = HttpUrlUtils.getHost() + "/api/rmrb-search-api/zh/c/display/search/token" | ||
| 895 | + return url | ||
| 896 | + } | ||
| 897 | + | ||
| 891 | } | 898 | } |
| @@ -181,4 +181,6 @@ export { TopicDetailData,GroupItem } from './src/main/ets/bean/content/TopicDeta | @@ -181,4 +181,6 @@ export { TopicDetailData,GroupItem } from './src/main/ets/bean/content/TopicDeta | ||
| 181 | export { FeedbackTypeBean } from './src/main/ets/bean/detail/FeedbackTypeBean'; | 181 | export { FeedbackTypeBean } from './src/main/ets/bean/detail/FeedbackTypeBean'; |
| 182 | export { FeedBackParams } from './src/main/ets/bean/content/FeedBackParams'; | 182 | export { FeedBackParams } from './src/main/ets/bean/content/FeedBackParams'; |
| 183 | 183 | ||
| 184 | +export { NetLayerVoiceRecoginizerToken } from './src/main/ets/bean/voicerecoginizer/NetLayerVoiceRecoginizerToken'; | ||
| 185 | + | ||
| 184 | 186 |
| 1 | import { inputMethodEngine } from '@kit.IMEKit' | 1 | import { inputMethodEngine } from '@kit.IMEKit' |
| 2 | import { commentInfo } from 'wdBean/Index' | 2 | import { commentInfo } from 'wdBean/Index' |
| 3 | +import { VoiceRecoginizer } from 'wdHwAbility' | ||
| 3 | import { ToastUtils } from 'wdKit/Index' | 4 | import { ToastUtils } from 'wdKit/Index' |
| 4 | import { HttpUtils } from 'wdNetwork/Index' | 5 | import { HttpUtils } from 'wdNetwork/Index' |
| 5 | import { commentItemModel } from '../model/CommentModel' | 6 | import { commentItemModel } from '../model/CommentModel' |
| 6 | import { publishCommentModel } from '../model/PublishCommentModel' | 7 | import { publishCommentModel } from '../model/PublishCommentModel' |
| 7 | import commentViewModel from '../viewmodel/CommentViewModel' | 8 | import commentViewModel from '../viewmodel/CommentViewModel' |
| 8 | import { VoiceInputView } from './VoiceInputView' | 9 | import { VoiceInputView } from './VoiceInputView' |
| 10 | +import { common, UIAbility } from '@kit.AbilityKit' | ||
| 9 | 11 | ||
| 10 | export interface CommentDialogInputContent { | 12 | export interface CommentDialogInputContent { |
| 11 | comment?: string | 13 | comment?: string |
| @@ -126,6 +128,7 @@ export struct CommentCustomDialog { | @@ -126,6 +128,7 @@ export struct CommentCustomDialog { | ||
| 126 | .width(30) | 128 | .width(30) |
| 127 | .height(30) | 129 | .height(30) |
| 128 | .onClick(() => { | 130 | .onClick(() => { |
| 131 | + VoiceRecoginizer.checkPemmission(getContext(this) as common.UIAbilityContext) | ||
| 129 | this.positionInfo = this.textInputController.getCaretOffset() | 132 | this.positionInfo = this.textInputController.getCaretOffset() |
| 130 | this.voiceSwitch = !this.voiceSwitch | 133 | this.voiceSwitch = !this.voiceSwitch |
| 131 | this.emojiSwitch = false | 134 | this.emojiSwitch = false |
| @@ -193,7 +196,7 @@ export struct CommentCustomDialog { | @@ -193,7 +196,7 @@ export struct CommentCustomDialog { | ||
| 193 | } | 196 | } |
| 194 | if (this.voiceSwitch) { | 197 | if (this.voiceSwitch) { |
| 195 | VoiceInputView({voiceRecoginizerResult:(result: string) => { | 198 | VoiceInputView({voiceRecoginizerResult:(result: string) => { |
| 196 | - this.publishCommentModel.commentContent += result; | 199 | + this.publishCommentModel.commentContent = result; |
| 197 | }}).height(150) | 200 | }}).height(150) |
| 198 | 201 | ||
| 199 | } | 202 | } |
| 1 | +import Lottie from '@ohos/lottie' | ||
| 1 | import { LottieView } from '../../lottie/LottieView' | 2 | import { LottieView } from '../../lottie/LottieView' |
| 2 | import lottie from '@ohos/lottie'; | 3 | import lottie from '@ohos/lottie'; |
| 4 | +import { CommonConstants } from 'wdConstant'; | ||
| 5 | +import { common} from '@kit.AbilityKit'; | ||
| 6 | +import { VoiceRecoginizer } from 'wdHwAbility/src/main/ets/voiceRecognizer/VoiceRecoginizer'; | ||
| 3 | 7 | ||
| 4 | @Component | 8 | @Component |
| 5 | export struct VoiceInputView { | 9 | export struct VoiceInputView { |
| @@ -10,8 +14,19 @@ export struct VoiceInputView { | @@ -10,8 +14,19 @@ export struct VoiceInputView { | ||
| 10 | 14 | ||
| 11 | @State private tips:string = "长按开始语音输入" | 15 | @State private tips:string = "长按开始语音输入" |
| 12 | 16 | ||
| 17 | + voiceRe: VoiceRecoginizer = VoiceRecoginizer.sharedManager() | ||
| 18 | + | ||
| 13 | voiceRecoginizerResult?:(result: string) => void | 19 | voiceRecoginizerResult?:(result: string) => void |
| 14 | 20 | ||
| 21 | + aboutToAppear(): void { | ||
| 22 | + this.initVoiceRecoigzer() | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + aboutToDisappear(): void { | ||
| 26 | + this.voiceRe.stop() | ||
| 27 | + this.voiceRe.voiceRecoginizerResult = undefined | ||
| 28 | + } | ||
| 29 | + | ||
| 15 | build() { | 30 | build() { |
| 16 | Column() { | 31 | Column() { |
| 17 | Stack() { | 32 | Stack() { |
| @@ -39,17 +54,18 @@ export struct VoiceInputView { | @@ -39,17 +54,18 @@ export struct VoiceInputView { | ||
| 39 | .gesture( | 54 | .gesture( |
| 40 | LongPressGesture() | 55 | LongPressGesture() |
| 41 | .onAction((event: GestureEvent) => { | 56 | .onAction((event: GestureEvent) => { |
| 57 | + // this | ||
| 42 | this.playAnimationOne = true | 58 | this.playAnimationOne = true |
| 43 | this.tips = "" | 59 | this.tips = "" |
| 60 | + this.voiceRe.startDialog() | ||
| 44 | }) | 61 | }) |
| 45 | 62 | ||
| 46 | .onActionEnd((event: GestureEvent) => { | 63 | .onActionEnd((event: GestureEvent) => { |
| 47 | this.tips = "长按开始语音输入" | 64 | this.tips = "长按开始语音输入" |
| 48 | - if (this.voiceRecoginizerResult) { | ||
| 49 | - this.voiceRecoginizerResult!(this.tips) | ||
| 50 | - } | ||
| 51 | - // lottie.destroy("voice_input_one") | ||
| 52 | this.playAnimationOne = false | 65 | this.playAnimationOne = false |
| 66 | + this.voiceRe.stop() | ||
| 67 | + // this.voiceRe.voiceRecoginizerResult = undefined | ||
| 68 | + | ||
| 53 | }) | 69 | }) |
| 54 | ) | 70 | ) |
| 55 | } | 71 | } |
| @@ -59,4 +75,18 @@ export struct VoiceInputView { | @@ -59,4 +75,18 @@ export struct VoiceInputView { | ||
| 59 | .fontColor("#222222") | 75 | .fontColor("#222222") |
| 60 | } | 76 | } |
| 61 | } | 77 | } |
| 78 | + | ||
| 79 | + initVoiceRecoigzer() { | ||
| 80 | + let context = getContext(this) as common.UIAbilityContext | ||
| 81 | + let resoureDir = context.resourceDir | ||
| 82 | + | ||
| 83 | + this.voiceRe.AsrInit(context.resourceDir, context.filesDir) | ||
| 84 | + | ||
| 85 | + this.voiceRe.voiceRecoginizerResult = (result: string) => { | ||
| 86 | + if (this.voiceRecoginizerResult) { | ||
| 87 | + this.voiceRecoginizerResult(result) | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + } | ||
| 62 | } | 92 | } |
| @@ -4,3 +4,5 @@ export { HWLocationUtils } from './src/main/ets/location/HWLocationUtils' | @@ -4,3 +4,5 @@ export { HWLocationUtils } from './src/main/ets/location/HWLocationUtils' | ||
| 4 | 4 | ||
| 5 | // export { WDPushNotificationManager } from "./src/main/ets/notification/WDPushNotificationManager" | 5 | // export { WDPushNotificationManager } from "./src/main/ets/notification/WDPushNotificationManager" |
| 6 | export { GetuiPush } from "./src/main/ets/getuiPush/GetuiPush" | 6 | export { GetuiPush } from "./src/main/ets/getuiPush/GetuiPush" |
| 7 | + | ||
| 8 | +export {VoiceRecoginizer} from './src/main/ets/voiceRecognizer/VoiceRecoginizer' |
| @@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
| 8 | "packageType": "InterfaceHar", | 8 | "packageType": "InterfaceHar", |
| 9 | "dependencies": { | 9 | "dependencies": { |
| 10 | "library": "file:./src/main/ets/getuiPush/GT-HM-1.0.4.har", | 10 | "library": "file:./src/main/ets/getuiPush/GT-HM-1.0.4.har", |
| 11 | + "neonui":"file:./src/main/ets/voiceRecognizer/neonui.har", | ||
| 11 | "wdConstant": "file:../../commons/wdConstant", | 12 | "wdConstant": "file:../../commons/wdConstant", |
| 12 | "wdLogin": "file:../../features/wdLogin", | 13 | "wdLogin": "file:../../features/wdLogin", |
| 13 | "wdKit": "file:../../commons/wdKit", | 14 | "wdKit": "file:../../commons/wdKit", |
| 1 | +import { audio } from '@kit.AudioKit' | ||
| 2 | +import { ArkTSUtils } from '@kit.ArkTS' | ||
| 3 | +import {getVoicebufferDataLengthByte} from 'neonui' | ||
| 4 | +import process from '@ohos.process' | ||
| 5 | +import { NativeNui } from 'neonui' | ||
| 6 | + | ||
| 7 | +let TAG:string = "AudioCapturer" | ||
| 8 | +//音频采集器类,主要用于采集音频,写入文件 | ||
| 9 | +export default class AudioCapturer{ | ||
| 10 | + static lock_:ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock() | ||
| 11 | + //static voiceBuffer2:Int16Array=new Int16Array(0); | ||
| 12 | + static voiceBuffer1:ArrayBuffer[] = []; | ||
| 13 | + //static voiceBuffer:ArrayBuffer[] =[]; | ||
| 14 | + static async clearVoiceArrayBuffer(){ | ||
| 15 | + await AudioCapturer.lock_.lockAsync( ()=>{ | ||
| 16 | + if (AudioCapturer.voiceBuffer1!==undefined){ | ||
| 17 | + AudioCapturer.voiceBuffer1= [] | ||
| 18 | + } | ||
| 19 | + console.info(`AudioCapturer clearVoiceArrayBuffer, then voiceBuffer1 size ${AudioCapturer.voiceBuffer1.length}`); | ||
| 20 | + }) | ||
| 21 | + } | ||
| 22 | + static async setVoiceArrayBuffer(voice:ArrayBuffer){ | ||
| 23 | + console.info(`AudioCapturer setVoiceArrayBuffer, 1 voiceBuffer1 size ${AudioCapturer.voiceBuffer1.length}`); | ||
| 24 | + AudioCapturer.lock_.lockAsync( ()=>{ | ||
| 25 | + if (AudioCapturer.voiceBuffer1==undefined){ | ||
| 26 | + AudioCapturer.voiceBuffer1= [] | ||
| 27 | + } | ||
| 28 | + AudioCapturer.voiceBuffer1.push(voice) | ||
| 29 | + console.info(`AudioCapturer setVoiceArrayBuffer, 3 voiceBuffer1 size ${AudioCapturer.voiceBuffer1.length}`); | ||
| 30 | + }) | ||
| 31 | + console.info(`AudioCapturer setVoiceArrayBuffer, 2 voiceBuffer1 size ${AudioCapturer.voiceBuffer1.length}`); | ||
| 32 | + } | ||
| 33 | + static async getVoiceArrayBuffer(buffer:ArrayBuffer):Promise<number>{ | ||
| 34 | + let ret:number; | ||
| 35 | + let outbuferleng=buffer.byteLength; | ||
| 36 | + let buffer_out_typedarray = new Int8Array(buffer) | ||
| 37 | + let offset = 0 | ||
| 38 | + console.log("AudioCapturer enter getVoiceArrayBuffer"); | ||
| 39 | + | ||
| 40 | + return await AudioCapturer.lock_.lockAsync( ()=>{ | ||
| 41 | + console.info(`AudioCapturer womx getVoiceArrayBuffer, outbuferleng ${buffer.byteLength}.with length ${AudioCapturer.voiceBuffer1.length}`); | ||
| 42 | + // while(AudioRenderer.voiceBuffer1.length <= 0){ | ||
| 43 | + // if(AudioRenderer.flagVoiceEnd==true) { | ||
| 44 | + // } | ||
| 45 | + // } | ||
| 46 | + if (AudioCapturer.voiceBuffer1.length > 0) { | ||
| 47 | + let voice_length = getVoicebufferDataLengthByte(AudioCapturer.voiceBuffer1) | ||
| 48 | + if (voice_length>=outbuferleng) { | ||
| 49 | + let bytes_need = outbuferleng | ||
| 50 | + while(bytes_need>0){ | ||
| 51 | + let voice1st = AudioCapturer.voiceBuffer1.shift() | ||
| 52 | + if (voice1st==undefined ){ | ||
| 53 | + } else { | ||
| 54 | + let out_typedbuffer:Int8Array; | ||
| 55 | + console.info(`AudioCapturer womx voice1st.byteLength=${voice1st.byteLength} vs bytes_need=${bytes_need}`); | ||
| 56 | + | ||
| 57 | + if (voice1st.byteLength > bytes_need) { | ||
| 58 | + let out_buffer = voice1st.slice(0,bytes_need) | ||
| 59 | + out_typedbuffer = new Int8Array(out_buffer) | ||
| 60 | + | ||
| 61 | + let save_buffer = voice1st.slice(bytes_need) | ||
| 62 | + AudioCapturer.voiceBuffer1.unshift(save_buffer) | ||
| 63 | + } else { | ||
| 64 | + out_typedbuffer = new Int8Array(voice1st) | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + for (let i = 0; i < out_typedbuffer.byteLength; i++) { | ||
| 68 | + buffer_out_typedarray[offset + i] = out_typedbuffer[i] | ||
| 69 | + } | ||
| 70 | + bytes_need -= out_typedbuffer.byteLength | ||
| 71 | + offset += out_typedbuffer.byteLength | ||
| 72 | + | ||
| 73 | + console.info(`AudioCapturer womx bytes_need=${bytes_need}`); | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + } else { | ||
| 77 | + ret = 0 | ||
| 78 | + console.error(`AudioCapturer error getVoiceArrayBuffer, outbuferleng 0.with ringbuffer voicebytes length ${voice_length}`); | ||
| 79 | + } | ||
| 80 | + } else { | ||
| 81 | + ret = 0; | ||
| 82 | + console.error(`AudioCapturer error getVoiceArrayBuffer, outbuferleng 0.with ringbuffer.length ${AudioCapturer.voiceBuffer1.length}<=0`); | ||
| 83 | + } | ||
| 84 | + return ret | ||
| 85 | + }) | ||
| 86 | + } | ||
| 87 | + static getVoiceArrayBuffer1(buffer:ArrayBuffer):number{ | ||
| 88 | + let ret:number=0; | ||
| 89 | + let outbuferleng=buffer.byteLength; | ||
| 90 | + let buffer_out_typedarray = new Int8Array(buffer) | ||
| 91 | + let offset = 0 | ||
| 92 | + console.log("AudioCapturer enter getVoiceArrayBuffer"); | ||
| 93 | + | ||
| 94 | + console.info(`AudioCapturer womx getVoiceArrayBuffer, outbuferleng ${buffer.byteLength}.with length ${AudioCapturer.voiceBuffer1.length}`); | ||
| 95 | + // while(AudioRenderer.voiceBuffer1.length <= 0){ | ||
| 96 | + // if(AudioRenderer.flagVoiceEnd==true) { | ||
| 97 | + // } | ||
| 98 | + // } | ||
| 99 | + if (AudioCapturer.voiceBuffer1.length > 0) { | ||
| 100 | + let voice_length = getVoicebufferDataLengthByte(AudioCapturer.voiceBuffer1) | ||
| 101 | + if (voice_length>=outbuferleng) { | ||
| 102 | + let bytes_need = outbuferleng | ||
| 103 | + while(bytes_need>0){ | ||
| 104 | + let voice1st = AudioCapturer.voiceBuffer1.shift() | ||
| 105 | + if (voice1st==undefined ){ | ||
| 106 | + break | ||
| 107 | + } else { | ||
| 108 | + let out_typedbuffer:Int8Array; | ||
| 109 | + console.info(`AudioCapturer womx voice1st.byteLength=${voice1st.byteLength} vs bytes_need=${bytes_need}`); | ||
| 110 | + | ||
| 111 | + if (voice1st.byteLength > bytes_need) { | ||
| 112 | + let out_buffer = voice1st.slice(0,bytes_need) | ||
| 113 | + out_typedbuffer = new Int8Array(out_buffer) | ||
| 114 | + | ||
| 115 | + let save_buffer = voice1st.slice(bytes_need) | ||
| 116 | + AudioCapturer.voiceBuffer1.unshift(save_buffer) | ||
| 117 | + } else { | ||
| 118 | + out_typedbuffer = new Int8Array(voice1st) | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + for (let i = 0; i < out_typedbuffer.byteLength; i++) { | ||
| 122 | + buffer_out_typedarray[offset + i] = out_typedbuffer[i] | ||
| 123 | + } | ||
| 124 | + bytes_need -= out_typedbuffer.byteLength | ||
| 125 | + offset += out_typedbuffer.byteLength | ||
| 126 | + | ||
| 127 | + console.info(`AudioCapturer womx bytes_need=${bytes_need}`); | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + ret = outbuferleng - bytes_need | ||
| 132 | + } else { | ||
| 133 | + ret = 0 | ||
| 134 | + console.error(`AudioCapturer error getVoiceArrayBuffer, outbuferleng 0.with ringbuffer voicebytes length ${voice_length}`); | ||
| 135 | + } | ||
| 136 | + } else { | ||
| 137 | + ret = 0; | ||
| 138 | + console.error(`AudioCapturer error getVoiceArrayBuffer, outbuferleng 0.with ringbuffer.length ${AudioCapturer.voiceBuffer1.length}<=0`); | ||
| 139 | + } | ||
| 140 | + return ret; | ||
| 141 | + } | ||
| 142 | + //定义音频流信息 | ||
| 143 | + static audioStreamInfo:audio.AudioStreamInfo = { | ||
| 144 | + //彩样率 | ||
| 145 | + samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000, | ||
| 146 | + //通道数 | ||
| 147 | + channels:audio.AudioChannel.CHANNEL_1, | ||
| 148 | + //采样格式 | ||
| 149 | + sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, | ||
| 150 | + //编码格式 | ||
| 151 | + encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW | ||
| 152 | + } | ||
| 153 | + //定义音频采集器信息 | ||
| 154 | + static audioCapturerInfo:audio.AudioCapturerInfo={ | ||
| 155 | + //音源类型 | ||
| 156 | + source:audio.SourceType.SOURCE_TYPE_MIC, | ||
| 157 | + //音频采集器标志 | ||
| 158 | + capturerFlags:0 | ||
| 159 | + } | ||
| 160 | + //定义音频采集器 | ||
| 161 | + static audioCapturer:audio.AudioCapturer | ||
| 162 | + static g_asrinstance:NativeNui | ||
| 163 | + //初始化音频采集器 | ||
| 164 | + static async init(asrinstance:NativeNui){ | ||
| 165 | + AudioCapturer.g_asrinstance = asrinstance | ||
| 166 | + AudioCapturer.audioCapturer = await audio.createAudioCapturer({ | ||
| 167 | + //需要音频流信息和音频采集器信息 | ||
| 168 | + streamInfo:AudioCapturer.audioStreamInfo, | ||
| 169 | + capturerInfo:AudioCapturer.audioCapturerInfo | ||
| 170 | + }) | ||
| 171 | + if (AudioCapturer.audioCapturer !== undefined) { | ||
| 172 | + await AudioCapturer.audioCapturer.on('readData', AudioCapturer.readDataCallback); | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + static readDataCallback = (buffer: ArrayBuffer) => { | ||
| 178 | + console.log(`${TAG} read data bytelength is ${buffer.byteLength}. uid[${process.uid}] pid[${process.pid}] tid[${process.tid}]`); | ||
| 179 | + //AudioCapturer.setVoiceArrayBuffer(buffer) | ||
| 180 | + AudioCapturer.g_asrinstance.updateAudio(buffer,false) | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + //开始采集音频 | ||
| 184 | + static async start(){ | ||
| 185 | + await AudioCapturer.clearVoiceArrayBuffer() | ||
| 186 | + if (AudioCapturer.audioCapturer) { | ||
| 187 | + let stateGroup = [audio.AudioState.STATE_PREPARED, | ||
| 188 | + audio.AudioState.STATE_PAUSED, | ||
| 189 | + audio.AudioState.STATE_STOPPED]; | ||
| 190 | + if (stateGroup.indexOf(AudioCapturer.audioCapturer.state.valueOf()) === -1) { | ||
| 191 | + // 当且仅当状态为STATE_PREPARED、STATE_PAUSED和STATE_STOPPED之一时才能启动采集 | ||
| 192 | + console.error(`${TAG}: start failed`); | ||
| 193 | + console.error('Capturer is not STATE_PREPARED or STATE_PAUSED or STATE_STOPPED'); | ||
| 194 | + return; | ||
| 195 | + } | ||
| 196 | + | ||
| 197 | + //开始录音 | ||
| 198 | + await AudioCapturer.audioCapturer.start() | ||
| 199 | + console.log(`${TAG} start done`); | ||
| 200 | + } else { | ||
| 201 | + console.log(`${TAG} start with AudioCapturer.audioCapturer is null`); | ||
| 202 | + return | ||
| 203 | + } | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + //停止采集音频 | ||
| 207 | + static async stop(){ | ||
| 208 | + if (AudioCapturer.audioCapturer) { | ||
| 209 | + // 只有采集器状态为STATE_RUNNING或STATE_PAUSED的时候才可以停止 | ||
| 210 | + if (AudioCapturer.audioCapturer.state === audio.AudioState.STATE_RUNNING || | ||
| 211 | + AudioCapturer.audioCapturer.state === audio.AudioState.STATE_PAUSED | ||
| 212 | + ) { | ||
| 213 | + console.error(`Capturer state is ${AudioCapturer.audioCapturer.state}`); | ||
| 214 | + await AudioCapturer.audioCapturer.stop()/*.then( (value)=>{ | ||
| 215 | + console.log("result of Capturer stop is " + value); | ||
| 216 | + }); // 停止采集*/ | ||
| 217 | + console.error('Capturer stop done'); | ||
| 218 | + } else { | ||
| 219 | + console.error('Capturer is not running or paused'); | ||
| 220 | + return; | ||
| 221 | + } | ||
| 222 | + } else { | ||
| 223 | + console.log(`${TAG} stop with AudioCapturer.audioCapturer is null`); | ||
| 224 | + return | ||
| 225 | + } | ||
| 226 | + await AudioCapturer.clearVoiceArrayBuffer() | ||
| 227 | + } | ||
| 228 | + // 释放资源 | ||
| 229 | + static async release() { | ||
| 230 | + if (AudioCapturer.audioCapturer) { | ||
| 231 | + | ||
| 232 | + // 采集器状态不是STATE_RELEASED或STATE_NEW状态,才能release | ||
| 233 | + if (AudioCapturer.audioCapturer.state === audio.AudioState.STATE_RELEASED || | ||
| 234 | + AudioCapturer.audioCapturer.state === audio.AudioState.STATE_NEW) { | ||
| 235 | + console.info('Capturer already released'); | ||
| 236 | + return; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + await AudioCapturer.audioCapturer.release() | ||
| 240 | + } | ||
| 241 | + } | ||
| 242 | +} |
| 1 | + | ||
| 2 | +import {NativeNui,Constants,MapToJson,INativeNuiCallback, AsrResult, KwsResult} from 'neonui' | ||
| 3 | +import { PermissionUtils,DeviceUtil, Logger, DateTimeUtils } from 'wdKit'; | ||
| 4 | +import AudioCapturer from './AudioCapture'; | ||
| 5 | +import { common, Permissions } from '@kit.AbilityKit'; | ||
| 6 | +import { NetLayerVoiceRecoginizerToken } from 'wdBean'; | ||
| 7 | +import { HttpUrlUtils,ResponseDTO } from 'wdNetwork' | ||
| 8 | +import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest' | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +class NativeNuiCallbackHandle implements INativeNuiCallback { | ||
| 12 | + asrspeechrealtimeResultOld:string="" | ||
| 13 | + asrmessage:string; | ||
| 14 | + message:string; | ||
| 15 | + nuiCallback?:(result: string) => void | ||
| 16 | + constructor() { | ||
| 17 | + this.asrmessage="" | ||
| 18 | + this.message="" | ||
| 19 | + } | ||
| 20 | + onNuiEventCallback(event:Constants.NuiEvent, resultCode:number, arg2:number, kwsResult:KwsResult, | ||
| 21 | + asrResult:AsrResult):void { | ||
| 22 | + let asrinfo:string = "" | ||
| 23 | + // console.log("onUsrNuiEventCallback last this.asrmessage is " + this.asrmessage) | ||
| 24 | + // console.log("onUsrNuiEventCallback this is " + JSON.stringify(this)) | ||
| 25 | + // console.log("onUsrNuiEventCallback event is " + event) | ||
| 26 | + | ||
| 27 | + if (event === Constants.NuiEvent.EVENT_ASR_RESULT){ | ||
| 28 | + this.message = "EVENT_ASR_RESULT" | ||
| 29 | + this.asrspeechrealtimeResultOld="" | ||
| 30 | + } else if (event === Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT || event === Constants.NuiEvent.EVENT_SENTENCE_END){ | ||
| 31 | + if (event === Constants.NuiEvent.EVENT_ASR_PARTIAL_RESULT ) { | ||
| 32 | + this.message = "EVENT_ASR_PARTIAL_RESULT" | ||
| 33 | + } else if(event === Constants.NuiEvent.EVENT_SENTENCE_END){ | ||
| 34 | + this.message = "EVENT_SENTENCE_END" | ||
| 35 | + } | ||
| 36 | + } else if (event === Constants.NuiEvent.EVENT_ASR_ERROR){ | ||
| 37 | + this.message = "EVENT_ASR_ERROR" | ||
| 38 | + } else if (event === Constants.NuiEvent.EVENT_MIC_ERROR){ | ||
| 39 | + this.message = "EVENT_MIC_ERROR" | ||
| 40 | + } else if (event === Constants.NuiEvent.EVENT_DIALOG_EX){ | ||
| 41 | + this.message = "EVENT_DIALOG_EX" | ||
| 42 | + } | ||
| 43 | + if (asrResult) { | ||
| 44 | + asrinfo = asrResult.asrResult | ||
| 45 | + //console.log(`asrinfo string is ${asrinfo}`) | ||
| 46 | + if (asrinfo) { | ||
| 47 | + try { | ||
| 48 | + let asrresult_json:object|null = JSON.parse(asrResult.asrResult) | ||
| 49 | + //console.log(JSON.stringify(asrresult_json)) | ||
| 50 | + if (asrresult_json) { | ||
| 51 | + let payload:object|null = asrresult_json["payload"]; | ||
| 52 | + if (payload) { | ||
| 53 | + //console.log(JSON.stringify(payload)) | ||
| 54 | + this.asrmessage = this.asrspeechrealtimeResultOld + payload["result"]; | ||
| 55 | + | ||
| 56 | + if(event === Constants.NuiEvent.EVENT_SENTENCE_END){ | ||
| 57 | + // console.info("onUsrNuiEventCallback EVENT_SENTENCE_END") | ||
| 58 | + this.asrspeechrealtimeResultOld = this.asrmessage | ||
| 59 | + } | ||
| 60 | + if (this.nuiCallback) { | ||
| 61 | + this.nuiCallback(this.asrmessage) | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + } catch (e){ | ||
| 66 | + // console.error("got asrinfo not json, so donot fresh asrinfo." + JSON.stringify(e)) | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + // console.info(`womx onUsrNuiEventCallback(${event}, ${resultCode},${arg2}, kwsResult:${kwsResult},asrResult:"${this.asrmessage}") done`) | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + onNuiNeedAudioData(buffer:ArrayBuffer):number { | ||
| 74 | + // console.info(`womx onUsrNuiNeedAudioData(buffer length = ${buffer.byteLength})`) | ||
| 75 | + // console.log(`womx onUsrNuiNeedAudioData uid[${process.uid}] pid[${process.pid}] tid[${process.tid}]`); | ||
| 76 | + let num:number = 0; | ||
| 77 | + | ||
| 78 | + if (true){ | ||
| 79 | + if (true){ | ||
| 80 | + //由于录音回调是异步的,所以此处获取共享数据需要加锁/并保持同步 是较难的,需要修改asr回调为用户主动推送方式 | ||
| 81 | + num = AudioCapturer.getVoiceArrayBuffer1(buffer) | ||
| 82 | + } else { | ||
| 83 | + | ||
| 84 | + let flag_returned:boolean = false | ||
| 85 | + try { | ||
| 86 | + AudioCapturer.getVoiceArrayBuffer(buffer).then( (result:number)=>{ | ||
| 87 | + console.log("womx onUsrNuiNeedAudioData getVoiceArrayBuffer done, result="+result) | ||
| 88 | + num = result | ||
| 89 | + flag_returned=true | ||
| 90 | + }) | ||
| 91 | + } catch(e ){ | ||
| 92 | + flag_returned=true | ||
| 93 | + | ||
| 94 | + } | ||
| 95 | + while(flag_returned==false){ | ||
| 96 | + console.log("womx onUsrNuiNeedAudioData waiting ... num="+num) | ||
| 97 | + | ||
| 98 | + } | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + | ||
| 103 | + // console.info(`womx onUsrNuiNeedAudioData(buffer length = ${buffer.byteLength}) return ${num}}`) | ||
| 104 | + return num;//buffer.byteLength; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + onNuiAudioStateChanged(state:Constants.AudioState):void { | ||
| 108 | + // console.info(`womx onUsrNuiAudioStateChanged(${state})`) | ||
| 109 | + if (state === Constants.AudioState.STATE_OPEN){ | ||
| 110 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder start`) | ||
| 111 | + //AudioCapturer.init(g_asrinstance) | ||
| 112 | + AudioCapturer.start() | ||
| 113 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder start done`) | ||
| 114 | + } else if (state === Constants.AudioState.STATE_CLOSE){ | ||
| 115 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder close`) | ||
| 116 | + AudioCapturer.stop() | ||
| 117 | + //AudioCapturer.release() | ||
| 118 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder close done`) | ||
| 119 | + } else if (state === Constants.AudioState.STATE_PAUSE){ | ||
| 120 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder pause`) | ||
| 121 | + AudioCapturer.stop() | ||
| 122 | + //AudioCapturer.release() | ||
| 123 | + // console.info(`womx onUsrNuiAudioStateChanged(${state}) audio recorder pause done`) | ||
| 124 | + } | ||
| 125 | + } | ||
| 126 | + onNuiAudioRMSChanged(val:number):number{ | ||
| 127 | + // console.info(`womx onNuiAudioRMSChanged(${val})`) | ||
| 128 | + return 0; | ||
| 129 | + } | ||
| 130 | + clearAsrInfo(){ | ||
| 131 | + this.asrmessage = "" | ||
| 132 | + } | ||
| 133 | +} | ||
| 134 | + | ||
| 135 | +const TAG = 'VoiceRecoginizer' | ||
| 136 | + | ||
| 137 | +export class VoiceRecoginizer { | ||
| 138 | + private static MICROPHONEMISSION: Permissions = 'ohos.permission.MICROPHONE' | ||
| 139 | + private static READMEDIA: Permissions = 'ohos.permission.READ_MEDIA' | ||
| 140 | + private static INTENT: Permissions = "ohos.permission.INTERNET" | ||
| 141 | + private static WRITE_MEDIA: Permissions = "ohos.permission.WRITE_MEDIA" | ||
| 142 | + | ||
| 143 | + private static appKey = "EospGmM6mdPljjjm" | ||
| 144 | + private static url = "wss://nls-gateway.cn-shanghai.aliyuncs.com:443/ws/v1" | ||
| 145 | + private authToken?: NetLayerVoiceRecoginizerToken | ||
| 146 | + | ||
| 147 | + private vadMode: boolean = false | ||
| 148 | + | ||
| 149 | + private cbhandle: NativeNuiCallbackHandle = new NativeNuiCallbackHandle() | ||
| 150 | + | ||
| 151 | + private g_asrinstance: NativeNui = new NativeNui(Constants.ModeType.MODE_DIALOG, "asr1") | ||
| 152 | + | ||
| 153 | + private static manager: VoiceRecoginizer | ||
| 154 | + | ||
| 155 | + public static sharedManager(): VoiceRecoginizer { | ||
| 156 | + if (!VoiceRecoginizer.manager) { | ||
| 157 | + VoiceRecoginizer.manager = new VoiceRecoginizer() | ||
| 158 | + } | ||
| 159 | + return VoiceRecoginizer.manager | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + voiceRecoginizerResult?:(result: string) => void | ||
| 163 | + // public voiceRecoginzerResult:(result: string) => void | ||
| 164 | + genParams():string { | ||
| 165 | + let params:string = ""; | ||
| 166 | + let nls_config:Map<string, string|number|boolean|object> = new Map(); | ||
| 167 | + nls_config.set("enable_intermediate_result", true); | ||
| 168 | + | ||
| 169 | + //参数可根据实际业务进行配置 | ||
| 170 | + //接口说明可见: https://help.aliyun.com/document_detail/173298.html | ||
| 171 | + //查看 2.开始识别 | ||
| 172 | + | ||
| 173 | + //由于对外的SDK不带有本地VAD模块(仅带有唤醒功能的SDK具有VAD模块), | ||
| 174 | + //若要使用VAD模式,则需要设置nls_config参数启动在线VAD模式(见genParams()) | ||
| 175 | + if (this.vadMode) { | ||
| 176 | + nls_config.set("enable_voice_detection", true); | ||
| 177 | + nls_config.set("max_start_silence", 10000); | ||
| 178 | + nls_config.set("max_end_silence", 800); | ||
| 179 | + } else { | ||
| 180 | + nls_config.set("enable_voice_detection", false); | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + nls_config.set("enable_punctuation_prediction", true); | ||
| 184 | + nls_config.set("enable_inverse_text_normalization", true); | ||
| 185 | + // nls_config.set("customization_id", "test_id"); | ||
| 186 | + // nls_config.set("vocabulary_id", "test_id"); | ||
| 187 | + // nls_config.set("sample_rate", 16000); | ||
| 188 | + // nls_config.set("sr_format", "opus"); | ||
| 189 | + | ||
| 190 | + let parameters:Map<string, string|number|boolean|object> = new Map(); | ||
| 191 | + parameters.set("nls_config", Object( JSON.parse(MapToJson(nls_config)) ) ); | ||
| 192 | + | ||
| 193 | + //一句话识别 | ||
| 194 | + // console.log("start asr for 一句话识别") | ||
| 195 | + parameters.set("service_type", Constants.kServiceTypeASR); // 必填 | ||
| 196 | + //如果有HttpDns则可进行设置 | ||
| 197 | + //parameters.put("direct_ip", Utils.getDirectIp()); | ||
| 198 | + | ||
| 199 | + params = MapToJson(parameters);//parameters.toString(); | ||
| 200 | + console.log("configinfo genParams" + params) | ||
| 201 | + return params; | ||
| 202 | + } | ||
| 203 | + genInitParams(workpath:string, debugpath:string):string { | ||
| 204 | + let str:string = ""; | ||
| 205 | + //获取token方式: | ||
| 206 | + | ||
| 207 | + let object:Map<string, string|number|boolean|object> = new Map(); | ||
| 208 | + | ||
| 209 | + //账号和项目创建 | ||
| 210 | + // ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html | ||
| 211 | + object.set("app_key",VoiceRecoginizer.appKey); // 必填 | ||
| 212 | + | ||
| 213 | + //方法1: | ||
| 214 | + // 首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html | ||
| 215 | + // 然后请看 https://help.aliyun.com/document_detail/466615.html 使用其中方案一获取临时凭证 | ||
| 216 | + // 此方案简介: 远端服务器生成具有有效时限的临时凭证, 下发给移动端进行使用, 保证账号信息ak_id和ak_secret不被泄露 | ||
| 217 | + // 获得Token方法(运行在APP服务端): https://help.aliyun.com/document_detail/450255.html?spm=a2c4g.72153.0.0.79176297EyBj4k | ||
| 218 | + | ||
| 219 | + if (this.authToken) { | ||
| 220 | + object.set("token", this.authToken.accessToken) | ||
| 221 | + } | ||
| 222 | + //方法2: | ||
| 223 | + // STS获取临时凭证方法暂不支持 | ||
| 224 | + | ||
| 225 | + //方法3:(强烈不推荐,存在阿里云账号泄露风险) | ||
| 226 | + // 参考Auth类的实现在端上访问阿里云Token服务获取SDK进行获取。请勿将ak/sk存在本地或端侧环境。 | ||
| 227 | + // 此方法优点: 端侧获得Token, 无需搭建APP服务器。 | ||
| 228 | + // 此方法缺点: 端侧获得ak/sk账号信息, 极易泄露。 | ||
| 229 | + // JSONObject object = Auth.getAliYunTicket(); | ||
| 230 | + | ||
| 231 | + object.set("device_id", DeviceUtil.clientId()/*Utils.getDeviceId()*/); // 必填, 推荐填入具有唯一性的id, 方便定位问题 | ||
| 232 | + object.set("url", VoiceRecoginizer.url); // 默认 | ||
| 233 | + object.set("workspace", workpath); // 必填, 且需要有读写权限 | ||
| 234 | + // object.set("sample_rate", "16000"); | ||
| 235 | + // object.set("format", "pcm"); | ||
| 236 | + | ||
| 237 | + //当初始化SDK时的save_log参数取值为true时,该参数生效。表示是否保存音频debug,该数据保存在debug目录中,需要确保debug_path有效可写。 | ||
| 238 | + // object.put("save_wav", "true"); | ||
| 239 | + //debug目录,当初始化SDK时的save_log参数取值为true时,该目录用于保存中间音频文件。 | ||
| 240 | + object.set("debug_path", debugpath); | ||
| 241 | + | ||
| 242 | + // FullMix = 0 // 选用此模式开启本地功能并需要进行鉴权注册 | ||
| 243 | + // FullCloud = 1 | ||
| 244 | + // FullLocal = 2 // 选用此模式开启本地功能并需要进行鉴权注册 | ||
| 245 | + // AsrMix = 3 // 选用此模式开启本地功能并需要进行鉴权注册 | ||
| 246 | + // AsrCloud = 4 | ||
| 247 | + // AsrLocal = 5 // 选用此模式开启本地功能并需要进行鉴权注册 | ||
| 248 | + //一句话识别 | ||
| 249 | + // console.log("init asr for 一句话识别") | ||
| 250 | + object.set("service_mode", Constants.ModeAsrCloud); // 必填 | ||
| 251 | + | ||
| 252 | + str = MapToJson(object) | ||
| 253 | + | ||
| 254 | + // console.info("configinfo genInitParams:" + str); | ||
| 255 | + return str; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + async AsrInit(path:string, filePath:string): Promise<number> { | ||
| 259 | + //console.log("AsrInit this is " + JSON.stringify(this)) | ||
| 260 | + // console.info("AsrInit path: " + path); | ||
| 261 | + //获取工作路径, 这里获得当前nuisdk.aar中assets路径 | ||
| 262 | + | ||
| 263 | + let asset_path:string = path+"/resources_cloud" | ||
| 264 | + // fs.stat(asset_path).catch((error: BusinessError) => { | ||
| 265 | + // if (error.code = 13900002) { | ||
| 266 | + // fs.mkdirSync(asset_path) | ||
| 267 | + // } | ||
| 268 | + // }) | ||
| 269 | + // fs.mkdirSync(asset_path) | ||
| 270 | + // try { | ||
| 271 | + // await this.checkPath(asset_path) | ||
| 272 | + this.cbhandle.nuiCallback = (result: string) => { | ||
| 273 | + if (this.voiceRecoginizerResult) { | ||
| 274 | + this.voiceRecoginizerResult(result) | ||
| 275 | + } | ||
| 276 | + } | ||
| 277 | + | ||
| 278 | + let parameters: string = "" | ||
| 279 | + // this.genInitParams(asset_path,filePath) | ||
| 280 | + // .then(parameters) { | ||
| 281 | + // | ||
| 282 | + // } | ||
| 283 | + await this.getToken() | ||
| 284 | + | ||
| 285 | + let ret:number = this.g_asrinstance.initialize(this.cbhandle, this.genInitParams(asset_path,filePath), Constants.LogLevel.LOG_LEVEL_NONE, false); | ||
| 286 | + // console.info("result = " + ret); | ||
| 287 | + if (ret == Constants.NuiResultCode.SUCCESS) { | ||
| 288 | + | ||
| 289 | + } else { | ||
| 290 | + // Logger.debug(TAG,"语音识别初始化失败") | ||
| 291 | + //final String msg_text = Utils.getMsgWithErrorCode(ret, "init"); | ||
| 292 | + //抛出错误异常信息。 | ||
| 293 | + /* | ||
| 294 | + runOnUiThread(new Runnable() { | ||
| 295 | + @Override | ||
| 296 | + public void run() { | ||
| 297 | + Toast.makeText(SpeechRecognizerActivity.this, msg_text, Toast.LENGTH_LONG).show(); | ||
| 298 | + } | ||
| 299 | + }); | ||
| 300 | + */ | ||
| 301 | + } | ||
| 302 | + // return ret | ||
| 303 | + // } | ||
| 304 | + // catch { | ||
| 305 | + // return -1; | ||
| 306 | + // } | ||
| 307 | + //初始化SDK,注意用户需要在Auth.getAliYunTicket中填入相关ID信息才可以使用。 | ||
| 308 | + return ret | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + // checkPath(asset_path:string):Promise<void> { | ||
| 312 | + // return new Promise<void> ((success,fail) => { | ||
| 313 | + // fs.stat(asset_path).catch((error: BusinessError) => { | ||
| 314 | + // if (error.code = 13900002) { | ||
| 315 | + // fs.mkdirSync(asset_path) | ||
| 316 | + // success() | ||
| 317 | + // return | ||
| 318 | + // } | ||
| 319 | + // success() | ||
| 320 | + // }) | ||
| 321 | + // }) | ||
| 322 | + // } | ||
| 323 | + startDialog():number { | ||
| 324 | + // console.log(`womx startDialog uid[${process.uid}] pid[${process.pid}] tid[${process.tid}]`); | ||
| 325 | + this.cbhandle.clearAsrInfo() | ||
| 326 | + //由于对外的SDK不带有本地VAD模块(仅带有唤醒功能的SDK具有VAD模块), | ||
| 327 | + //若要使用VAD模式,则需要设置nls_config参数启动在线VAD模式(见genParams()) | ||
| 328 | + let vad_mode:Constants.VadMode = Constants.VadMode.TYPE_P2T; | ||
| 329 | + if (this.vadMode) { | ||
| 330 | + //TYPE_VAD: SDK自动判断句尾结束识别。(此功能仅存在于<029>带唤醒功能的SDK) | ||
| 331 | + //vad_mode = Constants.VadMode.TYPE_VAD; | ||
| 332 | + // console.info("使用Voice Active Detection模式"); | ||
| 333 | + } else { | ||
| 334 | + //TYPE_P2T: 有用户主动stop()以告知识别完成 | ||
| 335 | + //vad_mode = Constants.VadMode.TYPE_P2T; | ||
| 336 | + // console.info("使用Push To Talk模式"); | ||
| 337 | + } | ||
| 338 | + | ||
| 339 | + //设置相关识别参数,具体参考API文档 | ||
| 340 | + // initialize()之后startDialog之前调用 | ||
| 341 | + this.g_asrinstance.setParams(this.genParams()); | ||
| 342 | + AudioCapturer.init(this.g_asrinstance) | ||
| 343 | + let ret:number = this.g_asrinstance.startDialog(vad_mode, ""); | ||
| 344 | + // console.info("start done . ret = ", ret); | ||
| 345 | + if (ret != 0) { | ||
| 346 | + // console.info("call startDialog return error. ", ret); | ||
| 347 | + } | ||
| 348 | + return ret | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + stop() { | ||
| 352 | + this.cbhandle.clearAsrInfo() | ||
| 353 | + AudioCapturer.stop() | ||
| 354 | + } | ||
| 355 | + | ||
| 356 | + static async checkPemmission (context: common.UIAbilityContext) { | ||
| 357 | + | ||
| 358 | + let grant = await PermissionUtils.checkPermissions(VoiceRecoginizer.WRITE_MEDIA) | ||
| 359 | + | ||
| 360 | + if (grant) { | ||
| 361 | + ///初始化SDK | ||
| 362 | + // Logger.debug("已申请过权限") | ||
| 363 | + return | ||
| 364 | + } | ||
| 365 | + // let context = getContext() | ||
| 366 | + let requestGrant = await PermissionUtils.reqPermissionsFromUser([VoiceRecoginizer.MICROPHONEMISSION | ||
| 367 | + ,VoiceRecoginizer.READMEDIA | ||
| 368 | + ,VoiceRecoginizer.WRITE_MEDIA | ||
| 369 | + ,VoiceRecoginizer.INTENT],context) | ||
| 370 | + if (requestGrant) { | ||
| 371 | + ///初始化SDK | ||
| 372 | + } | ||
| 373 | + // return false | ||
| 374 | + } | ||
| 375 | + | ||
| 376 | + | ||
| 377 | + private async getToken():Promise<NetLayerVoiceRecoginizerToken | undefined> { | ||
| 378 | + return new Promise<NetLayerVoiceRecoginizerToken|undefined>((success,fail) => { | ||
| 379 | + if (this.authToken && this.authToken.accessToken.length > 0) { | ||
| 380 | + if (Date.now() < this.authToken.expireTime - 60 * 1000) { | ||
| 381 | + success(this.authToken) | ||
| 382 | + return | ||
| 383 | + } | ||
| 384 | + } | ||
| 385 | + | ||
| 386 | + HttpRequest.get<ResponseDTO<NetLayerVoiceRecoginizerToken>>( | ||
| 387 | + HttpUrlUtils.getVoiceRecognizerSDKAuthToken() | ||
| 388 | + ).then((res: ResponseDTO<NetLayerVoiceRecoginizerToken>) => { | ||
| 389 | + if (res.code != 0) { | ||
| 390 | + fail(res.message) | ||
| 391 | + return | ||
| 392 | + } | ||
| 393 | + this.authToken = res.data | ||
| 394 | + success(res.data) | ||
| 395 | + }) | ||
| 396 | + }) | ||
| 397 | + | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + | ||
| 401 | +} |
No preview for this file type
| 1 | +{ | ||
| 2 | + "cei":{ | ||
| 3 | + "cei_param_version":"2.2.0", | ||
| 4 | + "cei_param_device_type":"car", | ||
| 5 | + "cei_param_reco_mode":0, | ||
| 6 | + "cei_param_log_level":2, | ||
| 7 | + "cei_param_debug_path":"asr_debug", | ||
| 8 | + "cei_param_is_debug_enable":false, | ||
| 9 | + "cei_param_resource_path":"", | ||
| 10 | + "cei_param_resource_is_multi_language":false, | ||
| 11 | + "cei_param_audio_format_str":"16k16bitmono", | ||
| 12 | + "cei_param_mcs_mode":0, | ||
| 13 | + "cei_param_work_mode":0, | ||
| 14 | + "cei_param_max_cache_frames":1000, | ||
| 15 | + "cei_param_is_aec_bf_active":false, | ||
| 16 | + "cei_param_is_agc_active":false, | ||
| 17 | + "cei_param_is_vad_active":true, | ||
| 18 | + "cei_param_is_kws_active":true, | ||
| 19 | + "cei_param_is_sr_active":true | ||
| 20 | + }, | ||
| 21 | + "asp":{ | ||
| 22 | + "asp_param_is_process_parallel":false, | ||
| 23 | + "asp_param_is_input_debug_enable":false, | ||
| 24 | + "asp_param_is_output_debug_enable":false, | ||
| 25 | + "asp_param_debug_path":"asr_debug", | ||
| 26 | + "asp_param_is_callback_enable":false, | ||
| 27 | + "asp_param_callback_period_frames":5 | ||
| 28 | + }, | ||
| 29 | + "vad":{ | ||
| 30 | + "vad_param_is_input_debug_enable":false, | ||
| 31 | + "vad_param_is_output_debug_enable":false, | ||
| 32 | + "vad_param_debug_path":"asr_debug", | ||
| 33 | + "vad_param_asleep_speech_noise_thres":-0.8, | ||
| 34 | + "vad_param_awake_speech_noise_thres":-0.5, | ||
| 35 | + "vad_param_asleep_max_speech_segment_time":300000, | ||
| 36 | + "vad_param_awake_max_speech_segment_time":60000, | ||
| 37 | + "vad_param_asleep_block_size":3, | ||
| 38 | + "vad_param_awake_block_size":3, | ||
| 39 | + "vad_param_front_timeout_interval":8000, | ||
| 40 | + "vad_param_tail_timeout_interval":800, | ||
| 41 | + "vad_param_is_detect_start":true, | ||
| 42 | + "vad_param_is_detect_end":true | ||
| 43 | + }, | ||
| 44 | + "kws":{ | ||
| 45 | + "kws_param_is_input_debug_enable":false, | ||
| 46 | + "kws_param_is_output_debug_enable":false, | ||
| 47 | + "kws_param_debug_path":"asr_debug", | ||
| 48 | + "kws_param_is_process_parallel":false, | ||
| 49 | + "kws_param_front_extend_frames":10, | ||
| 50 | + "kws_param_tail_extend_frames":5, | ||
| 51 | + "kws_param_encoder_type_str":"opu", | ||
| 52 | + "kws_param_encoder_bitrate":16000, | ||
| 53 | + "kws_param_encoder_complexity":2, | ||
| 54 | + "kws_param_callback_period_ms":100, | ||
| 55 | + "kws_param_max_frames_per_callback":25, | ||
| 56 | + "kws_param_max_bytes_per_callback":16000 | ||
| 57 | + }, | ||
| 58 | + "sr":{ | ||
| 59 | + "sr_param_is_input_debug_enable":false, | ||
| 60 | + "sr_param_is_output_debug_enable":false, | ||
| 61 | + "sr_param_debug_path":"asr_debug", | ||
| 62 | + "sr_param_is_itn_enable":true, | ||
| 63 | + "sr_param_is_do_conf_filter":false, | ||
| 64 | + "sr_param_is_process_parallel":true, | ||
| 65 | + "sr_param_is_need_result":false, | ||
| 66 | + "sr_param_is_need_voice":true, | ||
| 67 | + "sr_param_ngram_conf_thres":65.0, | ||
| 68 | + "sr_param_jsgf_conf_thres":65.0, | ||
| 69 | + "sr_param_encoder_type_str":"opu", | ||
| 70 | + "sr_param_encoder_bitrate":16000, | ||
| 71 | + "sr_param_encoder_complexity":2, | ||
| 72 | + "sr_param_callback_period_ms":100, | ||
| 73 | + "sr_param_max_frames_per_callback":25, | ||
| 74 | + "sr_param_max_bytes_per_callback":16000 | ||
| 75 | + }, | ||
| 76 | + "ou":{ | ||
| 77 | + "oss_upload_param_is_enable":false, | ||
| 78 | + "oss_upload_param_asp_in":false, | ||
| 79 | + "oss_upload_param_asp_out":false, | ||
| 80 | + "oss_upload_param_vad_in":false, | ||
| 81 | + "oss_upload_param_vad_out":false, | ||
| 82 | + "oss_upload_param_kws_in":false, | ||
| 83 | + "oss_upload_param_kws_susp_in":false, | ||
| 84 | + "oss_upload_param_kws_out":false, | ||
| 85 | + "oss_upload_param_kws_susp_out":false, | ||
| 86 | + "oss_upload_param_sr_in":false | ||
| 87 | + } | ||
| 88 | +} |
| 1 | +{ | ||
| 2 | + "device_type":"phone", | ||
| 3 | + "assets_version":"1.1.20190902", | ||
| 4 | + "nui_config":{ | ||
| 5 | + "service_mode":"kModeFullCloud", | ||
| 6 | + "log_level":"kLogLevelVerbose", | ||
| 7 | + "enable_recorder_by_user":true, | ||
| 8 | + "enable_callback_recording":false, | ||
| 9 | + "enable_dialog":false | ||
| 10 | + }, | ||
| 11 | + "nls_config":{ | ||
| 12 | + "debug_level":4, | ||
| 13 | + "sr_format":"opus", | ||
| 14 | + "sample_rate":16000, | ||
| 15 | + "dns_timeout":5000, | ||
| 16 | + "vocab_default_weight":2 | ||
| 17 | + }, | ||
| 18 | + "audio_config":{ | ||
| 19 | + "debug":"none", | ||
| 20 | + "16k_audio":{ | ||
| 21 | + "name":"16kmono16bit", | ||
| 22 | + "id":0, | ||
| 23 | + "mic":{ | ||
| 24 | + "name":"16kmono16bit", | ||
| 25 | + "debug_heap_pollution":false, | ||
| 26 | + "read_cnt":0, | ||
| 27 | + "sample_rate":16000, | ||
| 28 | + "bits_per_sample":16, | ||
| 29 | + "channels":1, | ||
| 30 | + "recording_interval":10, | ||
| 31 | + "cei_frame_time_len":20, | ||
| 32 | + "channel_mask":"kAMChannalMaskNone", | ||
| 33 | + "format_type":"kAMDataFormatPcmInterleaved", | ||
| 34 | + "endianness":"kAMByteOrderLittleEndian" | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + "8k_audio":{ | ||
| 38 | + "name":"8kmono16bit", | ||
| 39 | + "id":0, | ||
| 40 | + "mic":{ | ||
| 41 | + "name":"8kmono16bit", | ||
| 42 | + "debug_heap_pollution":false, | ||
| 43 | + "read_cnt":0, | ||
| 44 | + "sample_rate":8000, | ||
| 45 | + "bits_per_sample":16, | ||
| 46 | + "channels":1, | ||
| 47 | + "recording_interval":10, | ||
| 48 | + "cei_frame_time_len":20, | ||
| 49 | + "channel_mask":"kAMChannalMaskNone", | ||
| 50 | + "format_type":"kAMDataFormatPcmInterleaved", | ||
| 51 | + "endianness":"kAMByteOrderLittleEndian" | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | +} |
sight_harmony/features/wdHwAbility/src/main/resources/resfile/resources_cloud/tts/parameter.cfg
0 → 100755
| 1 | +{ | ||
| 2 | + "device_type":"car", | ||
| 3 | + "mode_type":2, | ||
| 4 | + "smart_engine":3, | ||
| 5 | + "encode_type":"pcm", | ||
| 6 | + "debug_info":{ | ||
| 7 | + "debug_level":0, | ||
| 8 | + "debug_path":"/sdcard/tmp" | ||
| 9 | + }, | ||
| 10 | + "common_info":{ | ||
| 11 | + "pitch_level":0, | ||
| 12 | + "speed_level":1.0, | ||
| 13 | + "volume":1.0, | ||
| 14 | + "play_audio":0, | ||
| 15 | + "callback_raw_data":1, | ||
| 16 | + "sample_rate":16000, | ||
| 17 | + "font_name":"xiaoyun", | ||
| 18 | + "wait_time":2000 | ||
| 19 | + }, | ||
| 20 | + "cache":{ | ||
| 21 | + "on":true, | ||
| 22 | + "max_cache_size":2000000, | ||
| 23 | + "save_path":"/sdcard/mit/" | ||
| 24 | + }, | ||
| 25 | + "font":{ | ||
| 26 | + "on":false, | ||
| 27 | + "mode":"cmd", | ||
| 28 | + "save_path":"/sdcard/mit" | ||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + |
| 1 | +{ | ||
| 2 | + "cei":{ | ||
| 3 | + "cei_param_version":"2.2.0", | ||
| 4 | + "cei_param_device_type":"car", | ||
| 5 | + "cei_param_reco_mode":0, | ||
| 6 | + "cei_param_log_level":2, | ||
| 7 | + "cei_param_debug_path":"asr_debug", | ||
| 8 | + "cei_param_is_debug_enable":false, | ||
| 9 | + "cei_param_resource_path":"", | ||
| 10 | + "cei_param_resource_is_multi_language":false, | ||
| 11 | + "cei_param_audio_format_str":"16k16bitmono", | ||
| 12 | + "cei_param_mcs_mode":0, | ||
| 13 | + "cei_param_work_mode":0, | ||
| 14 | + "cei_param_max_cache_frames":1000, | ||
| 15 | + "cei_param_is_aec_bf_active":false, | ||
| 16 | + "cei_param_is_agc_active":false, | ||
| 17 | + "cei_param_is_vad_active":true, | ||
| 18 | + "cei_param_is_kws_active":true, | ||
| 19 | + "cei_param_is_sr_active":true | ||
| 20 | + }, | ||
| 21 | + "asp":{ | ||
| 22 | + "asp_param_is_process_parallel":false, | ||
| 23 | + "asp_param_is_input_debug_enable":false, | ||
| 24 | + "asp_param_is_output_debug_enable":false, | ||
| 25 | + "asp_param_debug_path":"asr_debug", | ||
| 26 | + "asp_param_is_callback_enable":false, | ||
| 27 | + "asp_param_callback_period_frames":5 | ||
| 28 | + }, | ||
| 29 | + "vad":{ | ||
| 30 | + "vad_param_is_input_debug_enable":false, | ||
| 31 | + "vad_param_is_output_debug_enable":false, | ||
| 32 | + "vad_param_debug_path":"asr_debug", | ||
| 33 | + "vad_param_asleep_speech_noise_thres":-0.8, | ||
| 34 | + "vad_param_awake_speech_noise_thres":-0.5, | ||
| 35 | + "vad_param_asleep_max_speech_segment_time":300000, | ||
| 36 | + "vad_param_awake_max_speech_segment_time":60000, | ||
| 37 | + "vad_param_asleep_block_size":3, | ||
| 38 | + "vad_param_awake_block_size":3, | ||
| 39 | + "vad_param_front_timeout_interval":8000, | ||
| 40 | + "vad_param_tail_timeout_interval":800, | ||
| 41 | + "vad_param_is_detect_start":true, | ||
| 42 | + "vad_param_is_detect_end":true | ||
| 43 | + }, | ||
| 44 | + "kws":{ | ||
| 45 | + "kws_param_is_input_debug_enable":false, | ||
| 46 | + "kws_param_is_output_debug_enable":false, | ||
| 47 | + "kws_param_debug_path":"asr_debug", | ||
| 48 | + "kws_param_is_process_parallel":false, | ||
| 49 | + "kws_param_front_extend_frames":10, | ||
| 50 | + "kws_param_tail_extend_frames":5, | ||
| 51 | + "kws_param_encoder_type_str":"opu", | ||
| 52 | + "kws_param_encoder_bitrate":16000, | ||
| 53 | + "kws_param_encoder_complexity":2, | ||
| 54 | + "kws_param_callback_period_ms":100, | ||
| 55 | + "kws_param_max_frames_per_callback":25, | ||
| 56 | + "kws_param_max_bytes_per_callback":16000 | ||
| 57 | + }, | ||
| 58 | + "sr":{ | ||
| 59 | + "sr_param_is_input_debug_enable":false, | ||
| 60 | + "sr_param_is_output_debug_enable":false, | ||
| 61 | + "sr_param_debug_path":"asr_debug", | ||
| 62 | + "sr_param_is_itn_enable":true, | ||
| 63 | + "sr_param_is_do_conf_filter":false, | ||
| 64 | + "sr_param_is_process_parallel":true, | ||
| 65 | + "sr_param_is_need_result":false, | ||
| 66 | + "sr_param_is_need_voice":true, | ||
| 67 | + "sr_param_ngram_conf_thres":65.0, | ||
| 68 | + "sr_param_jsgf_conf_thres":65.0, | ||
| 69 | + "sr_param_encoder_type_str":"opu", | ||
| 70 | + "sr_param_encoder_bitrate":16000, | ||
| 71 | + "sr_param_encoder_complexity":2, | ||
| 72 | + "sr_param_callback_period_ms":100, | ||
| 73 | + "sr_param_max_frames_per_callback":25, | ||
| 74 | + "sr_param_max_bytes_per_callback":16000 | ||
| 75 | + }, | ||
| 76 | + "ou":{ | ||
| 77 | + "oss_upload_param_is_enable":false, | ||
| 78 | + "oss_upload_param_asp_in":false, | ||
| 79 | + "oss_upload_param_asp_out":false, | ||
| 80 | + "oss_upload_param_vad_in":false, | ||
| 81 | + "oss_upload_param_vad_out":false, | ||
| 82 | + "oss_upload_param_kws_in":false, | ||
| 83 | + "oss_upload_param_kws_susp_in":false, | ||
| 84 | + "oss_upload_param_kws_out":false, | ||
| 85 | + "oss_upload_param_kws_susp_out":false, | ||
| 86 | + "oss_upload_param_sr_in":false | ||
| 87 | + } | ||
| 88 | +} |
| 1 | +{ | ||
| 2 | + "device_type":"phone", | ||
| 3 | + "assets_version":"1.1.20190902", | ||
| 4 | + "nui_config":{ | ||
| 5 | + "service_mode":"kModeFullCloud", | ||
| 6 | + "log_level":"kLogLevelVerbose", | ||
| 7 | + "enable_recorder_by_user":true, | ||
| 8 | + "enable_callback_recording":false, | ||
| 9 | + "enable_dialog":false | ||
| 10 | + }, | ||
| 11 | + "nls_config":{ | ||
| 12 | + "debug_level":4, | ||
| 13 | + "sr_format":"opus", | ||
| 14 | + "sample_rate":16000, | ||
| 15 | + "dns_timeout":5000, | ||
| 16 | + "vocab_default_weight":2 | ||
| 17 | + }, | ||
| 18 | + "audio_config":{ | ||
| 19 | + "debug":"none", | ||
| 20 | + "16k_audio":{ | ||
| 21 | + "name":"16kmono16bit", | ||
| 22 | + "id":0, | ||
| 23 | + "mic":{ | ||
| 24 | + "name":"16kmono16bit", | ||
| 25 | + "debug_heap_pollution":false, | ||
| 26 | + "read_cnt":0, | ||
| 27 | + "sample_rate":16000, | ||
| 28 | + "bits_per_sample":16, | ||
| 29 | + "channels":1, | ||
| 30 | + "recording_interval":10, | ||
| 31 | + "cei_frame_time_len":20, | ||
| 32 | + "channel_mask":"kAMChannalMaskNone", | ||
| 33 | + "format_type":"kAMDataFormatPcmInterleaved", | ||
| 34 | + "endianness":"kAMByteOrderLittleEndian" | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + "8k_audio":{ | ||
| 38 | + "name":"8kmono16bit", | ||
| 39 | + "id":0, | ||
| 40 | + "mic":{ | ||
| 41 | + "name":"8kmono16bit", | ||
| 42 | + "debug_heap_pollution":false, | ||
| 43 | + "read_cnt":0, | ||
| 44 | + "sample_rate":8000, | ||
| 45 | + "bits_per_sample":16, | ||
| 46 | + "channels":1, | ||
| 47 | + "recording_interval":10, | ||
| 48 | + "cei_frame_time_len":20, | ||
| 49 | + "channel_mask":"kAMChannalMaskNone", | ||
| 50 | + "format_type":"kAMDataFormatPcmInterleaved", | ||
| 51 | + "endianness":"kAMByteOrderLittleEndian" | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | +} |
sight_harmony/products/phone/src/main/resources/resfile/resources_cloud/tts/parameter.cfg
0 → 100755
| 1 | +{ | ||
| 2 | + "device_type":"car", | ||
| 3 | + "mode_type":2, | ||
| 4 | + "smart_engine":3, | ||
| 5 | + "encode_type":"pcm", | ||
| 6 | + "debug_info":{ | ||
| 7 | + "debug_level":0, | ||
| 8 | + "debug_path":"/sdcard/tmp" | ||
| 9 | + }, | ||
| 10 | + "common_info":{ | ||
| 11 | + "pitch_level":0, | ||
| 12 | + "speed_level":1.0, | ||
| 13 | + "volume":1.0, | ||
| 14 | + "play_audio":0, | ||
| 15 | + "callback_raw_data":1, | ||
| 16 | + "sample_rate":16000, | ||
| 17 | + "font_name":"xiaoyun", | ||
| 18 | + "wait_time":2000 | ||
| 19 | + }, | ||
| 20 | + "cache":{ | ||
| 21 | + "on":true, | ||
| 22 | + "max_cache_size":2000000, | ||
| 23 | + "save_path":"/sdcard/mit/" | ||
| 24 | + }, | ||
| 25 | + "font":{ | ||
| 26 | + "on":false, | ||
| 27 | + "mode":"cmd", | ||
| 28 | + "save_path":"/sdcard/mit" | ||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + |
-
Please register or login to post a comment