1.为什么每次朗读都要重新创建,不能复用之前的实例?
2.为什么不能动态调解语速?
3.偶尔还会出现要点两次才能触发语音播放问题
demo如下,是我封装的一个类,使用步骤如下
1.播放:TextToSpeechUtils.createByCallback(‘要播放的内容’, 语速),
2.销毁暂停
TextToSpeechUtils.shutdown()
TextToSpeechUtils.stop()
import { textToSpeech } from '@kit.CoreSpeechKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { ConfigStore } from './GuJiStore';
let ttsEngine: textToSpeech.TextToSpeechEngine;
let originalText = '';
let speed: number = 1
class TextToSpeechUtils {
// 数据回调
speakListener?: textToSpeech.SpeakListener;
constructor(originalText: string, speed: number) {
this.initListener()
this.createByCallback(originalText, speed)
}
//服务初始化
initListener() {
this.speakListener = {
// 开始播报回调
onStart(requestId: string, response: textToSpeech.StartResponse) {
console.info(`onStart, requestId: ${requestId} response: ${JSON.stringify(response)}`);
},
// 完成播报回调
onComplete(requestId: string, response: textToSpeech.CompleteResponse) {
console.info(`onComplete, requestId: ${requestId} response: ${JSON.stringify(response)}`);
},
// 停止播报完成回调,调用stop方法并完成时会触发此回调
onStop(requestId: string, response: textToSpeech.StopResponse) {
console.info(`onStop, requestId: ${requestId} response: ${JSON.stringify(response)}`);
ttsEngine.shutdown();
console.info('onComplete' + ttsEngine.isBusy())
},
// 返回音频流
onData(requestId: string, audio: ArrayBuffer, response: textToSpeech.SynthesisResponse) {
console.info(`onData, requestId: ${requestId} sequence: ${JSON.stringify(response)} audio: ${JSON.stringify(audio)}`);
},
// 错误回调,播报过程发生错误时触发此回调
// 未创建引擎时调用speak方法时返回错误码1003400007,合成及播报失败
// 连续调用两次speak,第二次speak会返回错误码1003400006,服务正忙碌
onError(requestId: string, errorCode: number, errorMessage: string) {
console.error(`onError, requestId: ${requestId} errorCode: ${errorCode} errorMessage: ${errorMessage}`);
}
};
}
// 创建引擎,通过callback形式返回
// 当引擎不存在、引擎资源不存在、初始化超时,返回错误码1003400005,引擎创建失败
createByCallback(originalText: string, speed: number) {
// 设置创建引擎参数
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
};
// textToSpeech.createEngine(initParamsInfo,
// (err: BusinessError, textToSpeechEngine: textToSpeech.TextToSpeechEngine) => {
// if (!err) {
// console.info('Succeeded in creating engine.');
// // 接收创建引擎的实例
// ttsEngine = textToSpeechEngine;
// // 设置回调
// ttsEngine?.setListener(this.speakListener);
// } else {
// console.error(`Failed to create engine. Code: ${err.code}, message: ${err.message}.`);
// }
// });
// 调用createEngine方法
textToSpeech.createEngine(initParamsInfo)
.then((res: textToSpeech.TextToSpeechEngine) => {
// 获得引擎实例
ttsEngine = res;
// 设置回调
console.info(`Succeeded in creating engine, result: ${JSON.stringify(res)}.`);
if (res) {
ttsEngine?.setListener(this.speakListener);
this.speak(originalText, speed)
}
}).catch((err: BusinessError) => {
console.error(`Failed to create engine. Code: ${err.code}, message: ${err.message}.`);
})
.finally(() => {
})
};
// 调用speak播报方法
// 未初始化引擎时调用speak方法,返回错误码1003400007,合成及播报失败
speak(originalText: string, speed: number) {
// 设置播报相关参数
let extraParam: Record<string, Object> = {
"queueMode": 0,
"speed": speed, // 语速,取值范围[0.5, 2.0]
"volume": 2,
"pitch": 1,
"languageContext": 'zh-CN',
"audioType": "pcm",
"soundChannel": 3,
"playType": 1
}
let speakParams: textToSpeech.SpeakParams = {
requestId: Date.now().toString(), // requestId在同一实例内仅能用一次,请勿重复设置
extraParams: extraParam
};
// 调用speak播报方法
ttsEngine?.speak(originalText, speakParams);
};
// 查询语种音色信息,以callback形式返回
listVoicesCallback() {
// 设置查询相关参数
let voicesQuery: textToSpeech.VoiceQuery = {
requestId: Date.now().toString(), // requestId在同一实例内仅能用一次,请勿重复设置
online: 1
};
// 调用listVoices方法,以callback返回语种音色查询结果
ttsEngine.listVoices(voicesQuery, (err: BusinessError, voiceInfo: textToSpeech.VoiceInfo[]) => {
if (!err) {
// 接收目前支持的语种音色等信息
let voice: string = JSON.stringify(voiceInfo);
console.info(`Succeeded in listing voices, voiceInfo is ` + voice);
} else {
console.error(`Failed to list voices. Code: ${err.code}, message: ${err.message}`);
}
});
};
// 停止合成及停止播报
stop() {
// 调用stop方法停止播报
ttsEngine?.stop();
};
// 释放引擎,释放成功后,再次调用createEngine方法会重新创建引擎
shutdown() {
// 调用release方法释放引擎
ttsEngine?.shutdown();
};
//判断当前是否处于合成或播报中
isSpeaking() {
let isSpeaking: boolean = ttsEngine.isBusy();
console.info(`isSpeaking: ${isSpeaking}`);
return isSpeaking;
};
}
export default new TextToSpeechUtils(originalText, speed);
1.为什么每次朗读都要重新创建,不能复用之前的实例?:
在HarmonyOS(HarmonyOS)中,文字转语音(TTS)功能每次朗读都需要重新创建实例,主要是因为TTS引擎的设计和资源管理策略。TTS引擎可能在每次使用时都需要重新初始化或恢复资源,以确保语音质量和稳定性。
2.为什么不能动态调解语速?:
目前HarmonyOS(HarmonyOS)的TTS功能不支持动态调解语速。这可能是由于技术限制或设计上的考虑。如果需要动态调整语速,可以考虑在应用逻辑中分段控制语音播放,通过暂停和恢复来实现不同语速的效果。
3、demo中readingAbility方法的this.isSpeaking = true造成的,可以去除,经测试,可以正常朗读
4、目前官方有一款demo可做参考:https://gitee.com/harmonyos\_samples/core-speech-kit-sample-code-ark-ts-kit-ttsdemo