文档

iOS SDK

更新时间:
一键部署

本文介绍了如何使用阿里云离线语音合成服务提供的iOS NUI SDK,包括下载安装SDK和语音包、SDK关键接口及代码示例。

前提条件

下载安装

  1. 下载SDK

    说明

    下载后在样例初始化代码中替换您的阿里云账号信息、Appkey才可运行。为方便集成,2.5.14版本后iOS接口使用纯Object-C接口,不再使用C++混合接口。

    类别

    兼容范围

    系统

    最低支持iOS9

    架构

    arm64,x86_64

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

    功能

    是否支持

    一句话识别

    实时语音识别

    语音合成

    实时长文本语音合成

    离线语音合成

    录音文件识别极速版

    唤醒及命令词

  2. 下载语音包,详情请参见接口说明中的语音包列表

    重要

    SDK和语音包是完全独立的,下载SDK后并不能直接使用,需要下载语音包,并设置语音包存放路径。

  3. 解压ZIP包。

    将ZIP包中的nuisdk.framework添加到您的工程中,并在工程Build Phases的Link Binary With Libraries中添加nuisdk.framework。

  4. 使用Xcode打开此工程。

    工程中提供了参考代码以及一些直接可使用的工具类,例如音频播放录制和文件操作,您可以直接复制源码到您的实际工程进行使用。其中语音合成示例代码在LocalTTSViewController类中。替换appkey和token后可直接运行。

SDK关键接口

  • nui_tts_initialize:初始化SDK。

    /**
     * 初始化SDK,离线合成暂不支持多实例,请先释放后再次进行初始化。请勿在UI线程调用,意外下可能引起阻塞。
     * 初始化是耗时操作,不需要合成一个任务就进行该操作;在启动和退出时进行一次即可。
     * @param parameters: 初始化参数,参考接口说明。
     * @param level: log打印级别,值越小打印越多。
     * @param save_log: 是否保存log为文件,存储目录为parameter中的debug_path字段值。
     * @return 参考错误码。
     */
    -(int) nui_tts_initialize:(const char *)parameters
                     logLevel:(NuiSdkLogLevel)level
                      saveLog:(BOOL)save_log;
  • nui_tts_play:开始播放。

    /**
     * 开始播放,该接口异步执行
     * @param priority: 任务优先级,请使用"1"。
     * @param taskid: 任务ID,可传入32个字节的uuid或者传入空内容由SDK自动生成。
     * @param text: 要播放的文本内容。
     * @return 参考错误码。
     */
    -(int) nui_tts_play:(const char *)priority
                 taskId:(const char *)taskid
                   text:(const char *)text;
  • nui_tts_cancel:取消播放。

    /**
     * 取消合成任务
     * @param taskid: 传入想要停止的任务ID,如果为空则取消所有任务。
     * @return 参考错误码。
     */
    -(int) nui_tts_cancel:(const char *)taskid;
  • nui_tts_pause:暂停播放。

    /**
     * 暂停
     * @return 参考错误码。
     */
    -(int) nui_tts_pause;
  • nui_tts_resume:恢复播放。

    /**
     * 恢复暂停的任务
     * @return 参考错误码。
     */
    -(int) nui_tts_resume;
  • nui_tts_set_param:设置语音合成参数。

    /**
     * 以键值对形式设置参数
     * @param param: 参数名,参考接口说明。
     * @param value: 参数值,参考接口说明。
     * @return 参考错误码。
     */
    -(int) nui_tts_set_param:(const char *)param
                       value:(const char *)value;
  • nui_tts_get_param:获取参数。

    /**
     * 获取参数值
     * @param param: 参数名,参考接口说明。
     * @return 参数值。
     */
    -(const char *) nui_tts_get_param:(const char *)param;
  • nui_tts_release:释放SDK资源。

    /**
     * 释放SDK
     * @return 参考错误码。
     */
    -(int) nui_tts_release;
  • NeoNuiTtsDelegate事件代理

    • onNuiTtsUserdataCallback:在回调中提供音频数据。

      /**
       * 当开始识别时,此回调被连续调用,App需要在回调中进行语音数据填充。
       * @param info: 在使用时间戳功能时返回时间戳结果,JSON格式。
       * @param info_len: info字段的数据长度。
       * @param buffer: 合成的语音数据。
       * @param len: 合成的语音长度。
       * @param taskid: 本次合成的任务ID。
       */
      - (void)onNuiTtsUserdataCallback:(char*)info infoLen:(int)info_len buffer:(char*)buffer len:(int)len taskId:(char*)task_id;
    • onNuiTtsEventCallback: 事件回调。

      /**
       * SDK主要事件回调
       * @param event: 回调事件,参考接口说明。
       * @param taskid: 本次合成的任务ID。
       * @param code: 参考错误码,TTS_EVENT_ERROR时有效。
       */
      - (void)onNuiTtsEventCallback:(NuiSdkTtsEvent)event taskId:(char*)taskid code:(int)code;

      NuiSdkTtsEvent事件列表:

      名称

      说明

      TTS_EVENT_START

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

      TTS_EVENT_END

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

      TTS_EVENT_CANCEL

      取消语音合成。

      TTS_EVENT_PAUSE

      语音合成暂停。

      TTS_EVENT_RESUME

      语音合成恢复。

      TTS_EVENT_ERROR

      语音合成发生错误。

    • onNuiTtsUserdataCallback:合成数据音量回调。

      /**
       * 当开始识别时,此回调被连续调用,App需要在回调中进行语音数据填充。
       * @param info: 在使用时间戳功能时返回时间戳结果,JSON格式。
       * @param info_len: info字段的数据长度。
       * @param buffer: 合成的语音数据。
       * @param len: 合成的语音长度。
       * @param taskid: 本次合成的任务ID。
       */
      - (void)onNuiTtsUserdataCallback:(char*)info infoLen:(int)info_len buffer:(char*)buffer len:(int)len taskId:(char*)task_id;

调用步骤

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

  2. 根据业务需要设置参数。

  3. 调用nui_tts_play进行播放。

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

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

代码示例

  1. 语音合成初始化。

    // 一次初始化成功,可以反复调用合成和参数设置接口,不需要频繁初始化和释放,减少耗时
    NSString * initParam = [self genInitParams];
    [_nui nui_tts_initialize:[initParam UTF8String] logLevel:LOG_LEVEL_VERBOSE saveLog:true];
    if (retcode != 0) {
        // 初始化失败,通过"error_msg"查看详细的错误信息,离线语音合成FAQ文档中已列出常见错误。
        const char *errmsg = [_nui nui_tts_get_param: "error_msg"];
        TLog(@"init failed. retcode:%d. errmsg:%s", retcode, errmsg);
        // 初始化失败不需要再调用参数设置和合成接口
        return;
    }

    其中,genInitParams生成为String JSON字符串,包含资源目录和用户信息。其中用户信息包含如下字段。

    //用户申请阿里云账号和appkey后填入才可使用。
    
    //郑重提示:
    //  您的账号信息ak_id和ak_secret一定不可存储在app代码中和移动端侧, 以防账号信息泄露。
    //  若使用离线功能(离线语音合成), 则必须ak_id、ak_secret、app_key
    //  若使用在线功能(语音合成、实时转写、一句话识别、录音文件转写), 则只需app_key和token
    
    //账号和项目创建
    //  ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
    NSString *app_key = @"<您申请创建的app_key>"; // 必填
    [dictM setObject:app_key forKey:@"app_key"]; // 必填
    
    //请使用您的阿里云账号与appkey进行访问, 以下介绍两种方案(不限于两种)
    //方案一(强烈推荐):
    //  首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
    //  然后请看 https://help.aliyun.com/document_detail/466615.html 使用其中方案二使用STS获取临时账号
    //  此方案简介: 远端服务器运行STS生成具有有效时限的临时凭证, 下发给移动端进行使用, 保证账号信息ak_id和ak_secret不被泄露
    NSString *ak_id = @"STS.<服务器生成的具有时效性的临时凭证>"; // 必填
    NSString *ak_secret = @"<服务器生成的具有时效性的临时凭证>"; // 必填
    NSString *sts_token = @"<服务器生成的具有时效性的临时凭证>"; // 必填,STS临时账户在离线功能时必须填写sts_token
    [dictM setObject:ak_id forKey:@"ak_id"]; // 必填
    [dictM setObject:ak_secret forKey:@"ak_secret"]; // 必填
    [dictM setObject:sts_token forKey:@"sts_token"]; // 必填
    
    //方案二(泄露风险, 不推荐):
    //  首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
    //  此方案简介: 远端服务器存储账号信息, 加密下发给移动端进行使用, 但是仍然存在泄露风险。
    // NSString *ak_id = @"<一定不可代码中存储和本地明文存储>"; // 必填
    // NSString *ak_secret = @"<一定不可代码中存储和本地明文存储>"; // 必填
    // [dictM setObject:ak_id forKey:@"ak_id"]; // 必填
    // [dictM setObject:ak_secret forKey:@"ak_secret"]; // 必填
    
    // 离线语音合成sdk_code取值:精品版为software_nls_tts_offline, 标准版为software_nls_tts_offline_standard
    // 离线语音合成账户和sdk_code可用于唤醒
    NSString *sdk_code = @"software_nls_tts_offline_standard"; // 必填
    [dictM setObject:sdk_code forKey:@"sdk_code"]; // 必填
    
    // 特别说明: 鉴权所用的id是由以下device_id,与手机内部的一些唯一码进行组合加密生成的。
    //   更换手机或者更换device_id都会导致重新鉴权计费。
    //   此外, 以下device_id请设置有意义且具有唯一性的id, 比如用户账号(手机号、IMEI等),
    //   传入相同或随机变换的device_id会导致鉴权失败或重复收费。
    //   NSString *id_string = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]; 并不能保证生成不变的device_id,请不要使用
    [dictM setObject:@"empty_device_id" forKey:@"device_id"]; // 必填
    
    //工作目录路径,SDK从该路径读取配置文件,鉴权生成的license也会存储在此处。
    [dictM setObject:bundlePath forKey:@"workspace"];
    //设置成本地语音合成模式, 这个设置很重要, 遗漏会导致无法运行
    [dictM setObject:@"0" forKey:@"mode_type"]; // 必填
  2. 根据需求设置参数。

    //加载语音包:已购买的语音包,可以放在任意位置,以aijia为例,该语音包位于Documents/voices/下,设置命令为“Documents/voices/aijia”
    NSString *cmd = [NSString stringWithFormat:@"%@/aijia", myvoicedir];
    [self.nui nui_tts_set_param:"extend_font_name" value:[cmd UTF8String]];
  3. 启动语音合成。

    //建议同一时间单示例启动一个task进行语音合成,单实例多task易出异常。
    [self.nui nui_tts_play:"1" taskId:"" text:[content UTF8String]];
  4. 取消语音合成

    //如果上个任务没有合成完毕,手动取消,开始合成新的任务。
    //建议同一时间单示例启动一个task进行语音合成,单实例多task易在cancel时出异常。
    [self.nui nui_tts_cancel:NULL];
  5. 回调处理。

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

      - (void)onNuiTtsEventCallback:(nuisdk::NuiSdkTtsEvent)event taskId:(char*)taskid code:(int)code {
          TLog(@"onNuiTtsEventCallback event[%d]", event);
          if (event == TTS_EVENT_START) {
              // 表示合成开始。
              // 通知播放器准备播放。
              [self->_voicePlayer play];
          } else if (event == TTS_EVENT_END || event == TTS_EVENT_CANCEL || event == TTS_EVENT_ERROR) {
              // 这三个事件都表示本条任务合成结束,对一条合成任务这三个事件只会触发其中一个:正常结束、正常取消或者发生错误。
              if (event == TTS_EVENT_END) {
                  // 注意这里是指语音合成完成,而非播放完成,播放完成需要由voicePlayer对象来进行通知。
                  [self->_voicePlayer drain];
              } else {
                  // 取消播报、或者发生异常时终止播放。
                  [self->_voicePlayer stop];
              }
              if (event == TTS_EVENT_ERROR) {
                  // 发生异常时可通过此接口获得详细错误信息。
                  const char *errmsg = [_nui nui_tts_get_param: "error_msg"];
                  TLog(@"tts get errmsg:%s", errmsg);
              }
          }
      }
    • onNuiTtsUserdataCallback:语音合成数据回调,将回调中的合成数据写入播放器进行播放。

      - (void)onNuiTtsUserdataCallback:(char*)info wordIdx:(int)info_len buffer:(char*)buffer len:(int)len taskId:(char*)task_id {
          TLog(@"onnuiTtsUserdataCallback played info %s info_len %d", info, info_len);
          [_voicePlayer write:(char*)buffer Length:(unsigned int)len];
      }

常见问题

使用集成离线语音iOS SDK,集成的语音是语音包“艾佳”,为什么出来的是男声?

“艾”字辈发音人包括(艾佳),合成音频采样率是24000 Hz,如果播放时采样率设置为16000 Hz,听感就会变得不同,您可以尝试将audioplayer.java里的采样率从16000 Hz手动改为24000 Hz。

iOS是否支持后台处理?

SDK本身不限制前后台,iOS SDK的样例工程默认仅支持前台处理,如果您需要支持后台处理,可以做如下修改:

  1. 在工程Info.list中添加Required background modes配置,并在该配置下添加Item,Value设置为App plays audio or streams audio/video using AirPlay配置1

  2. 在录音模块中进入后台时,不停止录音。亦即NLSVoiceRecorder.m中_appResignActive接口中不做停止录音调用。配置2

下载语音交互iOS SDK至本地静态库,运行Demo程序测试代码时,模拟器可以正常运行,真机无法运行,报错“Reason: no suitable image found. Did find:xxx”如何解决?

建议您删除手机上对应的APP后,执行xcode clean,并重新尝试运行。除此以外,还需检查签名的正确性,如果签名不正确,需撤销原来的inHouse证书,重新制作新的证书和provisioning profile,并将代码重新签名,再次打包。

iOS端集成nuisdk运行报mic错误如何处理?

请检查当前录音设备是否被占用。

使用智能语音服务集成iOS SDK,接入nuisdk.framework后,导入头文件#import "nuisdk.framework/Headers/NeoNui.h"后项目报错如何解决?

一般情况下是SDK导入有问题导致,请您确认下图参数是否已勾选,如果已勾选,建议您将头文件导入方式换为#import <nuisdk/NeoNui.h>ios导入头部文件失败

按照文档使用SDK接入后报错“/Users/admin/FlashTranscription_iOS/Fc_ASR.xcodeproj Building for iOS, but the linked and embedded framework 'nuisdk.framework' was built for iOS + iOS Simulator."”如何解决?

可能因为版本过高导致,建议您修改项目配置Validate WorkspaceYes后,重新编译。按照文档使用SDK接入后报错

使用集成语音服务iOS SDK,集成flutter_plugin时报错“Undefined symbols for architecture arm64: "std::__1::mutex::~mutex()", referenced from: ___cxx_global_var_init in libflutter_tts.a(ringBuf.o)”如何解决?

您可以打开iOS工程下的Podfile文件,修改post_install do |installer|部分的代码,再次执行构建即可成功。

集成语音服务报错

TRTC实时音视频和语音识别结合,当同时调用麦克风时可能会发生冲突,导致有一方没有声音如何解决?

建议尝试TRTC的音视频流,然后使用localStream.getAudioTrack获取MediaStreamTrack对象,并转换为符合ASR标准的音频流,然后通过语音识别SDK发起请求。

使用App集成iOS SDK,提交到App store失败,提示“Unsupported Architectures. The executable for AliYunSmart.app/Frameworks/nuisdk.framework contains unsupported architectures '[x86_ _64, i386]'. With error code”如何解决?

可能是模拟器架构影响,您可以参考如下方法查看framework版本并移除framework模拟器架构。

  1. 进入到framework目录。

  2. 输入命令lipo -info xxxFramework,查看framework的架构版本,如果含有模拟器打包需要把模拟器架构移除。

使用集成语音服务iOS SDK,接入nuisdk.framework后报错,要修改Legacy Build system才可以运行,如何解决?

建议您修改项目配置Validate WorkspaceYes后,重新编译。按照文档使用SDK接入后报错

  • 本页导读 (1)
文档反馈