import { audio } from '@kit.AudioKit'; import { fileIo } from '@kit.CoreFileKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { speechRecognizer } from '@kit.CoreSpeechKit'; const TAG = 'ZXY'; class Options { offset?: number; length?: number; } let asrEngine: speechRecognizer.SpeechRecognitionEngine; let bufferSize: number = 0; let audioCapturer: audio.AudioCapturer | undefined = undefined; let audioStreamInfo: audio.AudioStreamInfo = { samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_16000, // 采样率 channels: audio.AudioChannel.CHANNEL_1, // 通道 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式 } let audioCapturerInfo: audio.AudioCapturerInfo = { source: audio.SourceType.SOURCE_TYPE_MIC, // 音源类型 capturerFlags: 0 // 音频采集器标志 } let audioCapturerOptions: audio.AudioCapturerOptions = { streamInfo: audioStreamInfo, capturerInfo: audioCapturerInfo } let path = getContext().cacheDir; let filePath = path + `/huang.wav`; let file: fileIo.File = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE); let readDataCallback = (buffer: ArrayBuffer) => { let options: Options = { offset: bufferSize, length: buffer.byteLength } fileIo.writeSync(file.fd, buffer, options); bufferSize += buffer.byteLength; } function init() { audio.createAudioCapturer(audioCapturerOptions, (err, capturer) => { // 创建AudioCapturer实例 if (err) { console.error(TAG, `Invoke createAudioCapturer failed, code is ${err.code}, message is ${err.message}`); return; } console.error(TAG, `create AudioCapturer success`); audioCapturer = capturer; if (audioCapturer !== undefined) { (audioCapturer as audio.AudioCapturer).on('readData', readDataCallback); } }); } // 开始一次音频采集 function start() { if (audioCapturer !== undefined) { let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; if (stateGroup.indexOf((audioCapturer as audio.AudioCapturer).state.valueOf()) === -1) { // 当且仅当状态为STATE_PREPARED、STATE_PAUSED和STATE_STOPPED之一时才能启动采集 console.error(TAG, `start failed`); return; } // 启动采集 (audioCapturer as audio.AudioCapturer).start((err: BusinessError) => { if (err) { console.error(TAG, 'Capturer start failed.'); } else { console.error(TAG, 'Capturer start success.'); } }); } } // 停止采集 function stop() { if (audioCapturer !== undefined) { // 只有采集器状态为STATE_RUNNING或STATE_PAUSED的时候才可以停止 if ((audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (audioCapturer as audio.AudioCapturer).state.valueOf() !== audio.AudioState.STATE_PAUSED) { console.error(TAG, 'Capturer is not running or paused'); return; } //停止采集 (audioCapturer as audio.AudioCapturer).stop((err: BusinessError) => { if (err) { console.error(TAG, 'Capturer stop failed.'); } else { fileIo.close(file); console.error(TAG, 'Capturer stop success.'); } }); } } // 销毁实例,释放资源 function release() { if (audioCapturer !== undefined) { // 采集器状态不是STATE_RELEASED或STATE_NEW状态,才能release if ((audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_RELEASED || (audioCapturer as audio.AudioCapturer).state.valueOf() === audio.AudioState.STATE_NEW) { console.error(TAG, 'Capturer already released'); return; } //释放资源 (audioCapturer as audio.AudioCapturer).release((err: BusinessError) => { if (err) { console.error(TAG, 'Capturer release failed.'); } else { console.error(TAG, 'Capturer release success.'); } }); } } @Entry @Component struct Index { @State resultData: string = '' params(str: string) { this.resultData = str } aboutToAppear(): void { init(); //初始化录音机 audioinit() } aboutToDisappear(): void { release(); //释放资源 audiorelease() } build() { Column() { Button('开始录音').width('100%') .onClick(() => { start(); }) Button('停止录音').width('100%') .onClick(() => { stop(); }) Button('开始识别').width('100%') .onClick(async () => { this.createByCallback(); await this.setListener(); await this.startListening(); await this.writeAudio() }) Text(this.resultData) Button('播放').width('100%') .onClick(() => { audiostart() }) Button('暂停').width('100%') .onClick(() => { audiopause() }) Button('停止').width('100%') .onClick(() => { audiostop() }) Button('结束').width('100%') .onClick(() => { asrEngine.finish('123456'); }) } .height('100%') .width('100%') } // 计时 public async countDownLatch(count: number) { while (count > 0) { await this.sleep(10); count--; } } // 创建引擎,通过callback形式返回 private createByCallback() { // 设置创建引擎参数 let extraParam: Record<string, Object> = { "locate": "CN", "recognizerMode": "short" }; let initParamsInfo: speechRecognizer.CreateEngineParams = { language: 'zh-CN', online: 1, extraParams: extraParam }; // 调用createEngine方法 speechRecognizer.createEngine(initParamsInfo, (err: BusinessError, speechRecognitionEngine: speechRecognizer.SpeechRecognitionEngine) => { if (!err) { console.error(TAG, 'Succeeded in creating engine.'); // 接收创建引擎的实例 asrEngine = speechRecognitionEngine; } else { // 无法创建引擎时返回错误码1002200001,原因:语种不支持、模式不支持、初始化超时、资源不存在等导致创建引擎失败 // 无法创建引擎时返回错误码1002200006,原因:引擎正在忙碌中,一般多个应用同时调用语音识别引擎时触发 // 无法创建引擎时返回错误码1002200008,原因:引擎正在销毁中 console.error(TAG, `Failed to create engine. Code: ${err.code}, message: ${err.message}.`); } }); } // 开始识别 private startListening() { // samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率 // channels: audio.AudioChannel.CHANNEL_2, // 通道 // sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式 // encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式 // 设置开始识别的相关参数 let recognizerParams: speechRecognizer.StartParams = { sessionId: '123456', audioInfo: { audioType: 'pcm', sampleRate: 16000, soundChannel: 1, sampleBit: 16 } } // 调用开始识别方法 asrEngine.startListening(recognizerParams); }; // 写音频流 private async writeAudio() { let path = getContext().cacheDir; let filePath = path + `/huang.wav`; let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE); try { let buf: ArrayBuffer = new ArrayBuffer(1280); let offset: number = 0; while (1280 == fileIo.readSync(file.fd, buf, { offset: offset })) { let uint8Array: Uint8Array = new Uint8Array(buf); asrEngine.writeAudio("123456", uint8Array); await this.countDownLatch(1); offset = offset + 1280; console.error(TAG, `offset:${offset / 1024}`) } } catch (err) { console.error(TAG, `Failed to read from file. Code: ${err.code}, message: ${err.message}.`); } finally { if (null != file) { fileIo.closeSync(file); } } } // 睡眠 private sleep(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } // 设置回调 private setListener() { // 创建回调对象 let setListener: speechRecognizer.RecognitionListener = { // 开始识别成功回调 onStart(sessionId: string, eventMessage: string) { console.error(TAG, `onStart, sessionId: ${sessionId} eventMessage: ${eventMessage}`); }, // 事件回调 onEvent(sessionId: string, eventCode: number, eventMessage: string) { console.error(TAG, `onEvent, sessionId: ${sessionId} eventCode: ${eventCode} eventMessage: ${eventMessage}`); }, // 识别结果回调,包括中间结果和最终结果 onResult(sessionId: string, result: speechRecognizer.SpeechRecognitionResult) { console.error(TAG + 'result', `onResult, sessionId: ${sessionId} sessionId: ${JSON.stringify(result)}`); }, // 识别完成回调 onComplete(sessionId: string, eventMessage: string) { console.error(TAG + 'result', `onComplete, sessionId: ${sessionId} eventMessage: ${eventMessage}`); }, // 错误回调,错误码通过本方法返回 // 如:返回错误码1002200006,识别引擎正忙,引擎正在识别中 // 更多错误码请参考错误码参考 onError(sessionId: string, errorCode: number, errorMessage: string) { console.error(TAG, `onError, sessionId: ${sessionId} errorCode: ${errorCode} errorMessage: ${errorMessage}`); }, } // 设置回调 asrEngine.setListener(setListener); }; } //语音识别 // 播放录音 //播放音频 let renderModel: audio.AudioRenderer | undefined = undefined; let audioRendererInfo: audio.AudioRendererInfo = { usage: audio.StreamUsage.STREAM_USAGE_MUSIC, // 音频流使用类型 rendererFlags: 0 // 音频渲染器标志 } let audioRendererOptions: audio.AudioRendererOptions = { streamInfo: audioStreamInfo, rendererInfo: audioRendererInfo } let writeDataCallback = (buffer: ArrayBuffer) => { let options: Options = { offset: bufferSize, length: buffer.byteLength } fileIo.readSync(file.fd, buffer, options); bufferSize += buffer.byteLength; } // 初始化,创建实例,设置监听事件 function audioinit() { audio.createAudioRenderer(audioRendererOptions, (err, renderer) => { // 创建AudioRenderer实例 if (!err) { console.info(`${TAG}: creating AudioRenderer success`); renderModel = renderer; if (renderModel !== undefined) { (renderModel as audio.AudioRenderer).on('writeData', writeDataCallback); } } else { console.info(`${TAG}: creating AudioRenderer failed, error: ${err.message}`); } }); } // 开始一次音频渲染 function audiostart() { if (renderModel !== undefined) { let stateGroup = [audio.AudioState.STATE_PREPARED, audio.AudioState.STATE_PAUSED, audio.AudioState.STATE_STOPPED]; if (stateGroup.indexOf((renderModel as audio.AudioRenderer).state.valueOf()) === -1) { // 当且仅当状态为prepared、paused和stopped之一时才能启动渲染 console.error(TAG + 'start failed'); return; } // 启动渲染 (renderModel as audio.AudioRenderer).start((err: BusinessError) => { if (err) { console.error('Renderer start failed.'); } else { console.info('Renderer start success.'); } }); } } // 暂停渲染 function audiopause() { if (renderModel !== undefined) { // 只有渲染器状态为running的时候才能暂停 if ((renderModel as audio.AudioRenderer).state.valueOf() !== audio.AudioState.STATE_RUNNING) { console.info('Renderer is not running'); return; } // 暂停渲染 (renderModel as audio.AudioRenderer).pause((err: BusinessError) => { if (err) { console.error('Renderer pause failed.'); } else { console.info('Renderer pause success.'); } }); } } // 停止渲染 async function audiostop() { if (renderModel !== undefined) { // 只有渲染器状态为running或paused的时候才可以停止 if ((renderModel as audio.AudioRenderer).state.valueOf() !== audio.AudioState.STATE_RUNNING && (renderModel as audio.AudioRenderer).state.valueOf() !== audio.AudioState.STATE_PAUSED) { console.info('Renderer is not running or paused.'); return; } // 停止渲染 (renderModel as audio.AudioRenderer).stop((err: BusinessError) => { if (err) { console.error('Renderer stop failed.'); } else { fileIo.close(file); console.info('Renderer stop success.'); } }); } } // 销毁实例,释放资源 async function audiorelease() { if (renderModel !== undefined) { // 渲染器状态不是released状态,才能release if (renderModel.state.valueOf() === audio.AudioState.STATE_RELEASED) { console.info('Renderer already released'); return; } // 释放资源 (renderModel as audio.AudioRenderer).release((err: BusinessError) => { if (err) { console.error('Renderer release failed.'); } else { console.info('Renderer release success.'); } }); } } // 播放录音
08-16
06-29
1598