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内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!