hiai引擎框架-文本转语音
介绍
本示例展示了使用hiai引擎框架提供的文本转语音能力。
本示例展示了对一段中文文本,进行语音合成及播报的能力。
需要使用hiai引擎框架文本转语音接口@kit.CoreSpeechKit.d.ts.
效果预览
使用说明:
- 在手机的主屏幕,点击”ttsDemo“,启动应用。
- 点击“CreateEngine”按钮,进行能力初始化。
- 点击“speak”按钮,试听文本播报。
- 点击“stop”等按钮对播报进行事件控制。
- 点击“listVoicesCallback/listVoicesPromise”查询支持的语种和音色。
具体实现
本示例展示了在@kit.CoreSpeechKit.d.ts定义的API:
- createEngine(createEngineParams: CreateEngineParams, callback: AsyncCallback): void;
- createEngine(createEngineParams: CreateEngineParams): Promise;
- speak(text: string, speakParams: SpeakParams, listener: SpeakListener): void;
- listVoices(params: VoiceQuery, callback: AsyncCallback): void;
- listVoices(params: VoiceQuery): Promise;
- stop(): void;
- isBusy(): boolean;
- shutdown(): void;
业务使用时,需要先进行import导入textToSpeech。 调用speak等接口,传入想要识别的文本,试听播报,观察日志等。参考:
import { textToSpeech } from '@kit.CoreSpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { TreeMap } from '@kit.ArkTS';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { UuidBasic } from './UuidBasic';const TAG: string = 'TtsDemo';
let ttsEngine: textToSpeech.TextToSpeechEngine;@Entry
@Component
struct Index {@State createCount: number = 0;@State result: boolean = false;@State voiceInfo: string = "";@State text: string = "";@State textContent: string = "";@State utteranceId: string = "123456";@State originalText: string = "\n\t\t古人学问无遗力,少壮工夫老始成;\n\t\t" +"纸上得来终觉浅,绝知此事要躬行。\n\t\t";@State illegalText: string = "";private pcmData: TreeMap<number, Uint8Array> = new TreeMap();build() {Column() {Scroll() {Column() {TextArea({ placeholder: 'Please enter tts original text', text: `${this.originalText}` }).margin(20).focusable(false).border({ width: 5, color: 0x317AE7, radius: 10, style: BorderStyle.Dotted }).onChange((value: string) => {this.originalText = value;hilog.info(0x0000, TAG, "original text: " + this.originalText);})Button() {Text("CreateEngine").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`createByCallback:createCount:${this.createCount}`);this.createByCallback();})Button() {Text("CreateEngineByPromise").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`createByPromise:createCount:${this.createCount}`);this.createByPromise();})Button() {Text("createOfErrorLanguage").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`createOfErrorLanguage:createCount:${this.createCount}`);this.createOfErrorLanguage();})Button() {Text("createOfErrorPerson").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`createOfErrorPerson:createCount:${this.createCount}`);this.createOfErrorPerson();})Button() {Text("speak").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`speak:createCount:${this.createCount}`)this.speak();})Button() {Text("SpeakIllegalText").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.createCount++;console.log(`illegalSpeak:createCount:${this.createCount}`)this.illegalSpeak();})Button() {Text("listVoicesCallback").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.listVoicesCallback();})Button() {Text("listVoicesPromise").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {this.listVoicesPromise();})Button() {Text("stop").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {//停止播报hilog.info(0x0000, TAG, "isSpeaking click:-->");//this.setListener();ttsEngine.stop();})Button() {Text("isBusy").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AE7").width("80%").height(50).margin(10).onClick(() => {hilog.info(0x0000, TAG, "isSpeaking click:-->");//查询播报状态this.setListener();let isBusy: boolean = ttsEngine.isBusy();console.log('isBusy :' + isBusy);})Button() {Text("shutdown").fontColor(Color.White).fontSize(20)}.type(ButtonType.Capsule).backgroundColor("#0x317AA7").width("80%").height(50).margin(10).onClick(() => {//释放引擎ttsEngine.shutdown();})}.layoutWeight(1)}.width('100%').height('100%')}}//创建引擎,通过callback形式返回//当引擎不存在、引擎资源不存在、初始化超时,返回错误码1002300005,引擎创建失败private createByCallback() {//设置创建引擎参数let extraParam: Record<string, Object> = { "style": 'interaction-broadcast', "locate": 'CN', "name": 'EngineName' }let initParamsInfo: textToSpeech.CreateEngineParams = {language: 'zh-CN',person: 0,online: 1,extraParams: extraParam};try {//调用createEngine方法textToSpeech.createEngine(initParamsInfo, (err: BusinessError, textToSpeechEngine: textToSpeech.TextToSpeechEngine) => {if (!err) {console.log('createEngine is success');//接收创建引擎的实例ttsEngine = textToSpeechEngine;} else {//创建引擎失败时返回错误码1002300005,可能原因:引擎不存在、资源不存在、创建引擎超时console.error("errCode is " + JSON.stringify(err.code));console.error("errMessage is " + JSON.stringify(err.message));}});} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`createEngine failed, error code: ${code}, message: ${message}.`)}}//创建引擎,通过promise形式返回private createByPromise() {//设置创建引擎参数let extraParam: Record<string, Object> = { "style": 'interaction-broadcast', "locate": 'CN', "name": 'EngineName' }let initParamsInfo: textToSpeech.CreateEngineParams = {language: 'zh-CN',person: 0,online: 1,extraParams: extraParam};//调用createEngine方法textToSpeech.createEngine(initParamsInfo).then((res: textToSpeech.TextToSpeechEngine) => {ttsEngine = res;console.log('result:' + JSON.stringify(res));}).catch((res: Object) => {console.log('result' + JSON.stringify(res));});}//调用speak播报方法//未初始化引擎时调用speak方法,返回错误码1002300007,合成及播报失败private async speak() {//设置播报相关参数let extraParam: Record<string, Object> = {"queueMode": 0,"speed": 1,"volume": 2,"pitch": 1,"languageContext": 'zh-CN',"audioType": "pcm","soundChannel": 1,"playType": 1}let speakParams: textToSpeech.SpeakParams = {requestId: UuidBasic.createUUID(),extraParams: extraParam}//设置回调this.setListener();//调用speak播报方法ttsEngine.speak(this.originalText, speakParams);}//查询语种音色信息,以callback形式返回private listVoicesCallback() {//设置查询相关参数let voicesQuery: textToSpeech.VoiceQuery = {requestId: UuidBasic.createUUID(),online: 1}//调用listVoices方法,以callback返回ttsEngine.listVoices(voicesQuery, (err: BusinessError, voiceInfo: textToSpeech.VoiceInfo[]) => {if (!err) {//接收目前支持的语种音色等信息this.voiceInfo = JSON.stringify(voiceInfo);console.log('voiceInfo is ' + JSON.stringify(voiceInfo));} else {console.error("error is " + JSON.stringify(err));}});};//查询语种音色信息,以promise返回private listVoicesPromise() {//设置查询相关的参数let voicesQuery: textToSpeech.VoiceQuery = {requestId: UuidBasic.createUUID(),online: 1}//调用listVoice方法ttsEngine.listVoices(voicesQuery).then((res: textToSpeech.VoiceInfo[]) => {console.log('voiceInfo:' + JSON.stringify(res));}).catch((res: Object) => {console.error('error is ' + JSON.stringify(res));});}private setListener() {let speakListener: textToSpeech.SpeakListener = {//开始播报回调onStart(utteranceId: string, response: textToSpeech.StartResponse) {console.log('speakListener onStart: ' + ' utteranceId: ' + utteranceId + ' response: ' + JSON.stringify(response));},//完成播报回调onComplete(utteranceId: string, response: textToSpeech.CompleteResponse) {console.log('speakListener onComplete: ' + ' utteranceId: ' + utteranceId + ' response: ' + JSON.stringify(response));},//停止播报完成回调,调用stop方法并完成时会触发此回调onStop(utteranceId: string, response: textToSpeech.StopResponse) {console.log('speakListener onStop: ' + ' utteranceId: ' + utteranceId + ' response: ' + JSON.stringify(response));},//返回音频流onData(utteranceId: string, audio: ArrayBuffer, response: textToSpeech.SynthesisResponse) {console.log('speakListener onData: ' + ' utteranceId: ' + utteranceId + ' sequence: ' + JSON.stringify(response) + ' audio: ' + audio);},//错误回调,播报过程发生错误时触发此回调//未创建引擎时调用speak方法时返回错误码1002300007,合成及播报失败//连续调用两次speak,第二次speak会返回错误码1002300006,服务正忙碌onError(utteranceId: string, errorCode: number, errorMessage: string) {console.error('speakListener onError: ' + ' utteranceId: ' + utteranceId + ' errorCode: ' + errorCode + ' errorMessage: ' + errorMessage);}};// 设置回调ttsEngine.setListener(speakListener);}//使用不支持的语种创建引擎,返回错误码1002300002,语种不支持private createOfErrorLanguage() {//设置创建引擎参数let initParamsInfo: textToSpeech.CreateEngineParams = {//不支持的语种language: 'ZH-CN',person: 0,online: 1};try {//调用createEngine方法textToSpeech.createEngine(initParamsInfo, (err: BusinessError, textToSpeechEngine: textToSpeech.TextToSpeechEngine) => {if (!err) {console.log('createEngine is success');//接收创建引擎的实例ttsEngine = textToSpeechEngine;} else {//返回错误码1002300002,语种不支持console.error("errCode is " + JSON.stringify(err.code));console.error("errMessage is " + JSON.stringify(err.message));}});} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`createEngine failed, error code: ${code}, message: ${message}.`)}}//使用不支持的语种创建引擎,返回错误码1002300003,音色不支持private createOfErrorPerson() {//设置创建引擎参数let initParamsInfo: textToSpeech.CreateEngineParams = {language: 'zh-CN',//不支持的音色person: 1,online: 1};try {//调用createEngine方法textToSpeech.createEngine(initParamsInfo, (err: BusinessError, textToSpeechEngine: textToSpeech.TextToSpeechEngine) => {if (!err) {console.log('createEngine is success');//接收创建引擎的实例ttsEngine = textToSpeechEngine;} else {//返回错误码1002300003,音色不支持console.error("errCode is " + JSON.stringify(err.code));console.error("errMessage is " + JSON.stringify(err.message));}});} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`createEngine failed, error code: ${code}, message: ${message}.`)}}//使用非法文本,调用speak播报方法,返回1002300001,文本长度非法private illegalSpeak() {this.setListener();//设置播报相关参数let extraParam: Record<string, Object> = { "speed": 1, "volume": 1, "pitch": 1, "audioType": "pcm" }let speakParams: textToSpeech.SpeakParams = {requestId: UuidBasic.createUUID(),extraParams: extraParam}//调用speak播报方法ttsEngine.speak(this.illegalText, speakParams);}
}
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!