HarmonyOS 文字转语音问题?

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);
阅读 986
1 个回答

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

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进