HarmonyOS Next SDK

本文介绍了如何使用阿里云智能语音服务提供的HarmonyOS Next NUI SDK,包括SDK下载安装、关键接口及代码示例。

前提条件

下载安装

  1. 下载nuisdk-release-harmonyosnext-20240919-har-v1.5.015.napi.001.zip

    重要

    下载后请在样例初始化代码中替换您的阿里云账号信息、Appkey和Token才可运行。

    类别

    兼容范围

    系统

    支持HarmonyOS Next 5.0 版本,API LEVEL 12, DevEco Studio版本号5.0.3.403

    架构

    arm64-v8a

    此SDK还包含如下功能,若未支持您想要的功能,请前往对应文档获取SDK。

    功能

    是否支持

    一句话识别

    实时语音识别

    语音合成

    实时长文本语音合成

    流式文本语音合成

    离线语音合成

    录音文件识别极速版

    唤醒及命令词

    听悟实时推流

  2. 以arkts HAR包的形式进行集成。解压ZIP包,其中nuisdk-release/neonui.har 是SDK生成的HAR包文件,在用户工程项目中导入调用即可。如果需要HarmonyOS Next CPP接入方式,可在ZIP包的harmonyos_libs和harmonyos_include中获得动态库和头文件。

  3. 使用DevEco Studio打开harmony_nlsdemo目录下工程查看参考代码实现,其中一句话识别示例代码为TTS.ets文件,替换UserKey.ets中 UserKey类的Appkey和Token后,即可直接运行。

SDK关键接口

  • tts_initialize:初始化SDK。

    /**
     * 初始化SDK,SDK为单例,请先释放后再次进行初始化。请勿在UI线程调用,可能会引起阻塞。
     * @param callback:事件监听回调,参见下文具体回调。
     * @param ticket:json string形式的初始化参数,参见下方说明或接口说明:https://help.aliyun.com/document_detail/173642.html。
     * @param level:log打印级别,值越小打印越多。
     * @param save_log:是否保存log为文件,存储目录为ticket中的debug_path字段值。注意,log文件无上限,请注意持续存储导致磁盘存满。
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public tts_initialize(callback:NuiTtsSdkListener ,
                                ticket:string ,
                                level:number ,
                                save_log:boolean ):number

    其中,NuiTtsSdkListener类型包含如下回调。

    • onTtsEventCallback:SDK事件回调。

      /**
       * 事件回调
       * @param event:回调事件,参见如下事件列表。
       * @param task_id:请求的任务ID。
       * @param ret_code:参见错误码,出现TTS_EVENT_ERROR事件时有效,可查阅https://help.aliyun.com/document_detail/459864.html。
       */
      onTtsEventCallback: (event:NuiSdkTtsEvent, taskid:string, ret_code:number) => void;

      事件列表:

      名称

      说明

      TTS_EVENT_START

      语音合成开始,准备播放。

      TTS_EVENT_END

      语音合成结束,合成数据已全部抛出,但并不表示播放结束。

      TTS_EVENT_CANCEL

      取消语音合成。

      TTS_EVENT_PAUSE

      语音合成暂停。

      TTS_EVENT_RESUME

      语音合成恢复。

      TTS_EVENT_ERROR

      语音合成发生错误。可通过getparamTts("error_msg")获得详细错误消息。

    • onTtsDataCallback:合成数据回调。

      /**
       * 合成数据回调,开启enable_subtitle后,交替返回info和data
       * @param info:使用时间戳功能时,返回JSON格式的时间戳结果。
       * @param info_len:info字段的数据长度,暂不使用。
       * @param data:合成的音频数据,写入播放器。
       */
      onTtsDataCallback: (info:string, info_len:number , buffer:ArrayBuffer|null) => void;

      其中,ticket内容参数说明,生成示例参见下方代码示例:

      参数

      类型

      是否必选

      说明

      workspace

      String

      工作目录路径,SDK从该路径读取配置文件。需要有读写权限。

      app_key

      String

      管控台创建项目的appkey。

      token

      String

      请确保该Token可以使用并在有效期内。 Token可以在初始化时设置,也可通过参数设置进行更新。

      device_id

      String

      用户层面的账户号,请保证唯一性。

      mode_type

      String

      设置成在线语音合成模式,语音合成必须设置成2,如果不设置会导致无法运行。

      tts_version

      String

      设置语音合成模式。

      • 1:长文本语音合成(超过300字符)

      • 0:短文本语音合成(300字符以内)

      custom_params

      String

      若需要设置交互协议支持但是接口说明中未说明的参数,可通过此万能设置接口进行配置。其中custom_params为key,value为JSON字符串。具体设置方法请见代码示例。

  • setparamTts:设置TTS参数。

    /**
     * 以键值对形式设置参数, 参见接口说明:https://help.aliyun.com/document_detail/173642.html
     * @param param:参数名,参见接口说明。
     * @param value:参数值,参见接口说明。
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public setparamTts(param:string, value:string):number
  • getparamTts:获取参数。

    /**
     * 获取参数值
     * @param param:参数名,参考接口说明:https://help.aliyun.com/document_detail/173642.html。
     * @return:参数值。
     */
    public getparamTts(param:string):string
  • startTts:开始播放。

    /**
     * 开始合成任务
     * @param priority:任务优先级,请使用"1"。
     * @param taskid:任务ID,可传入32个字节的uuid,或传入空内容由SDK自动生成。
     * @param text:播放的文本内容。
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public startTts(priority:string, taskid:string, text:string):number
  • cancelTts:取消播放。

    /**
     * 取消合成任务
     * @param taskid:传入想要停止的任务ID,如果为空则取消所有任务。
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public cancelTts(taskid:string):number
  • pauseTts:暂停播放。

    /**
     * 暂停合成任务
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public pauseTts():number
  • resumeTts:恢复播放。

    /**
     * 恢复暂停的任务
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public resumeTts():number
  • tts_release:释放SDK资源。

    /**
     * 释放SDK
     * @return:参见错误码:https://help.aliyun.com/document_detail/459864.html。
     */
    public tts_release():number

调用步骤

  1. 创建SDK类对象实例

  2. 初始化SDK和播放组件。

  3. 根据业务需求设置参数。

  4. 调用startTts进行播放。

  5. 在合成数据回调中,将数据写入播放器进行播放,建议使用流式播放。

  6. 收到语音合成结束的回调。

代码示例

说明

您如果有多例需求,也可以直接new对象进行使用。也可采用GetInstance获得单例。

语音合成初始化

//这里获得资源路径, 即工作路径,使用固定的路径 context.resourceDir+"/resources_cloud"
ttsLongText:boolean = false;  //默认 非长文本TTS配置
ticket: string = "this is ticket string"

resourceDir:string = ""
let context = getContext(this) as common.UIAbilityContext;
this.resourceDir = context.resourceDir;

//SDK初始化
g_ttsinstance:NativeNui = new NativeNui(Constants.ModeType.MODE_TTS, "")

let path:string = this.resourceDir+"/resources_cloud"
this.ticket = genTicketTTS(path)
console.info("ticket is %s", this.ticket);

let level:number= 1
let save_log:boolean = false
let retcode:number = this.g_ttsinstance.tts_initialize(g_ttscallback_instance,this.ticket,level, save_log)

其中,genTicket生成为String JSON字符串,包含资源目录和用户信息。其中用户信息包含如下字段,获取方式请参考接口说明文档。

/**
 * ticket生成示例,详见Demo工程中代码示例
 */
function genTicketTTS(workpath:string):string {
  let str:string = "";
  //注意:
  //  语音交互服务需要先准备好账号,并开通相关服务。具体步骤请查看:
  //    https://help.aliyun.com/zh/isi/getting-started/start-here
  //
  //原始账号:
  //  账号(子账号)信息主要包括AccessKey ID(后续简称为ak_id)和AccessKey Secret(后续简称为ak_secret)。
  //  此账号信息一定不可存储在app代码中或移动端侧,以防账号信息泄露造成资费损失。
  //
  //STS临时凭证:
  //  由于账号信息下发给客户端存在泄露的可能,阿里云提供的一种临时访问权限管理服务STS(Security Token Service)。
  //  STS是由账号信息ak_id和ak_secret,通过请求生成临时的sts_ak_id/sts_ak_secret/sts_token
  //  (为了区别原始账号信息和STS临时凭证, 命名前缀sts_表示STS生成的临时凭证信息)
  //什么是STS:https://help.aliyun.com/zh/ram/product-overview/what-is-sts
  //STS SDK概览:https://help.aliyun.com/zh/ram/developer-reference/sts-sdk-overview
  //STS Python SDK调用示例:https://help.aliyun.com/zh/ram/developer-reference/use-the-sts-openapi-example
  //
  //账号需求说明:
  //  若使用离线功能(离线语音合成、唤醒), 则必须app_key、ak_id和ak_secret,或app_key、sts_ak_id、sts_ak_secret和sts_token
  //  若使用在线功能(语音合成、实时转写、一句话识别、录音文件转写等), 则只需app_key和token
  
  // "mode_type" 设置为在线合成
  //  Local = 0,
  //  Mix = 1,  // init local and cloud
  //  Cloud = 2,

  let object:object = Object({
    "app_key" : UserKeyTTS.app_key,
    "token" : UserKeyTTS.token,
    "url" : UserKeyTTS.url,
    "device_id" : "empty_device_id_womx",  // 必填, 推荐填入具有唯一性的id, 方便定位问题
    "mode_type" : "2",
    "workspace" : workpath    // 必填, 工作目录路径,SDK从该路径读取配置文件,且需要有读写权限
  })
  str = JSON.stringify(object);
  console.info("UserContext:" + str);
  return str;
}

根据需求设置参数

//详细参数可见: https://help.aliyun.com/document_detail/173642.html

//  在线语音合成发音人可以参考阿里云官网
//  https://help.aliyun.com/document_detail/84435.html
this.g_ttsinstance.setparamTts("font_name", "xiaoyun");

//  设置发音人对应的语音合成采样率, 设置后也请设置播放器的对应采样率, 否则无法播放出正常音频。
this.g_ttsinstance.setparamTts("sample_rate", "16000");

// 字级别音素边界功能开关,该参数只对支持字级别音素边界接口的发音人有效。“1”表示打开,“0”表示关闭。
this.g_ttsinstance.setparamTts("enable_subtitle", "1");

// 设置文档中不存在的参数, key为custom_params, value以json string的形式设置参数
// this.g_ttsinstance.setparamTts("custom_params",{\"enable_phoneme_timestamp\":true}");

// 调整语速
// this.g_ttsinstance.setparamTts("speed_level", "1");
// 调整音调
// this.g_ttsinstance.setparamTts("pitch_level", "0");
// 调整音量
// this.g_ttsinstance.setparamTts("volume", "1.0");

//  支持一次性合成300字符以内的文字,其中1个汉字、1个英文字母或1个标点均算作1个字符,
//  超过300个字符的内容将会截断。所以请确保传入的text小于300字符(不包含ssml格式)。
//  长短文本语音合成收费不同,须另外开通长文本语音服务,请注意。
//  不需要长文本语音合成功能则无需考虑以下操作。
let charNum: number = this.g_ttsinstance.getUtf8CharsNum(ttsText);
console.info("chars:" + charNum + " of text:" + ttsText);
if (this.ttsLongText || charNum > 300) { //ttsLongText用于控制是否开启长文本语音合成
  console.info(`tts text with config ${this.ttsLongText} ,and chars number ${charNum}.`);
  // 超过300字符设置成 长文本语音合成 模式
  this.g_ttsinstance.setparamTts("tts_version", "1");
} else {
  // 未超过300字符设置成 短文本语音合成 模式
  this.g_ttsinstance.setparamTts("tts_version", "0");
}

启动语音合成

// 每个instance一个task,若想同时处理多个task,请启动多instance
this.g_ttsinstance.startTts("1", "", ttsText);

回调处理

  • onTtsEventCallback:语音合成事件回调,根据语音合成状态控制播放器。

    function cb_tts_event_callback(event:NuiSdkTtsEvent, task_id:string, code:number):void{
      console.info("womx cb_tts_event_callback  %d %s %d", event, task_id, code);
    
      console.log(`womx cb_tts_event_callback uid[${process.uid}] pid[${process.pid}] tid[${process.tid}]`);
      if (event==NuiSdkTtsEvent.TTS_EVENT_START){
        waitinginit() //初始化AudioRenderer模块并开启播放
      } else if (event==NuiSdkTtsEvent.TTS_EVENT_END){
        /*
         * 提示: TTS_EVENT_END事件表示TTS已经合成完并通过回调传回了所有音频数据, 而不是表示播放器已经播放完了所有音频数据。
         */
        console.info("womx call voiceEnd()");
        AudioRenderer.voiceEnd() //只是告知AudioRenderer模块,生成的数据已经结束,把所有数据播放完毕即可结束播放。
      } else if (event == TtsEvent.TTS_EVENT_PAUSE) {
          console.info("womx call pause()");
      } else if (event == TtsEvent.TTS_EVENT_RESUME) {
          console.info("womx call resume()");
      } else if(event==NuiSdkTtsEvent.TTS_EVENT_CANCEL || event==NuiSdkTtsEvent.TTS_EVENT_ERROR ){
        console.info("womx call stop()");
        AudioRenderer.voiceStop(true) //调用await AudioRenderer.stop(true)
      }
    }
  • onTtsDataCallback:语音合成数据回调,将回调中的合成数据写入播放器进行播放。

    function cb_tts_user_data_callback(info:string, info_len:number , buffer:ArrayBuffer|null):void{
      if (buffer){
        console.info("womx cb_tts_user_data_callback %s %d %d. times=%d", info, info_len, buffer.byteLength, countNumber);
        if (buffer.byteLength > 0) {
          AudioRenderer.writePlayerData(buffer)
        }
      } else {
        console.info("womx cb_tts_user_data_callback %s %d undefined", info, info_len);
      }
    }

取消语音合成

this.g_ttsinstance.cancelTts("")

退出语音合成

this.g_ttsinstance.tts_release()

常见问题

使用语音合成 SDK,在调用cancel时候出现一次anr,该如何处理?

SDK接口为同步调用,建议您不要在主线程调用SDK接口。

使用语音合成 SDK TTS时,报错提示“tts event:TTS_EVENT_ERROR ret 140002”。

建议您检查下输入文本是否合规。

不能正常使用语音合成 SDK。

您需要检查以下条件是否满足:

  • 是否已经满足 SDK语音合成的前提条件,详情请参见前提条件

  • 是否已开通商用。

调用 SDK时,手机报错提示“audio recoder not init”。

您可以通过以下方式排查:

  • 检查AudioRecord是否初始化正常。

  • 检查语音播放器是否有问题。

  • 编写AudioRecord录音代码,测试是否正常。

在模拟器上运行下载的程序,程序出现闪退现象,是什么原因?

模拟器可能会出现未知问题,建议您使用真机测试。

TTS支持的最长文本长度是多少?

TTS支持的语音长度有短文本和长文本两种模式,以300字符为分界。对于短文本请求设置参数"tts_version"为 "0";对于超过300字符的长文本,则需要设置为 "1",否则生成TTS时会截断。

代码可参考根据需求设置参数