iOS SDK

更新时间:
复制 MD 格式

使用录音文件识别极速版 iOS SDK 上传本地音频文件,通过事件回调获取转写结果。本页介绍 SDK 集成、调用示例和关键接口。

前提条件与使用限制

  • 已开通录音文件识别极速版商用服务。极速版不支持试用,服务限制与计费请参见录音文件识别极速版接口说明。

  • 已获取项目 Appkey 和有效的 NLS Token,分别参见管理项目和获取 Token。

  • 准备待识别的本地音频文件。支持 WAV、MP3、AAC、MP4、OPUS,文件大小不超过 100 MB,时长不超过 2 小时。项目中的识别模型应与音频语种匹配。

重要

AccessKey ID 和 AccessKey Secret 应保存在服务端,不得写入 App 代码或存储在移动端。由服务端获取 NLS Token 后下发给 App,并在 Token 过期前更新。初始化参数包含凭证,不应将完整参数写入日志。

下载安装

  1. 从移动端 SDK 选择与下载获取支持录音文件识别极速版的 iOS SDK 包,并按该页核对兼容性与合规使用要求。

  2. 解压 SDK 包,将 nuisdk.xcframework 添加到 App 工程。在目标的中,将其嵌入方式设置为Embed & Sign。XCFramework 分别提供真机和模拟器变体,由 Xcode 按目标平台选择。

  3. 在源文件中导入头文件。

#import <nuisdk/NeoNui.h>

SDK 包内的示例工程提供 FileTranscriberViewController.m,以及音频播放、录音和文件操作工具类,可按 App 需要使用。运行示例工程前,配置项目 Appkey 和服务端下发的 NLS Token。

V2.5.14 之后的 iOS SDK 使用 Objective-C 接口。V2.6.2 起,纯云端功能无需复制资源文件或设置 workspace。

调用步骤

  1. 创建 NeoNui 实例,设置实现 NeoNuiSdkDelegate 的事件代理。

  2. 在非 UI 线程调用 nui_initialize,传入 Appkey、NLS Token、设备标识和服务地址。

  3. 构造包含本地文件路径、音频格式等配置的 JSON 参数,调用 nui_file_trans_start 发起识别。

  4. 在 EVENT_FILE_TRANS_RESULT 事件中获取最终结果,在 EVENT_ASR_ERROR 事件中处理错误。

  5. 任务结束或不再使用时调用 nui_release 释放资源。需要中止任务时,使用开始识别返回的任务 ID 调用 nui_file_trans_cancel。

重要

不要在 SDK 事件回调中直接调用 SDK 接口,以免死锁。将取消、释放等操作提交到回调之外的工作队列;界面更新应在主线程执行。

代码示例

以下 Objective-C 示例使用 SDK V2.7.4-01B,将 App 包中的 example.wav 提交到服务端识别。将待识别的 WAV 文件加入 App 目标的资源,并将 Appkey、Token 替换为项目 Appkey 和服务端下发的有效 NLS Token。使用其他音频文件时,同时调整 file_path 和 nls_config.format。

示例通过独立工作队列执行 SDK 调用,在任务完成后释放资源,离开页面时取消未完成的任务。

#import <UIKit/UIKit.h>
#import <nuisdk/NeoNui.h>

@interface FileTranscriberViewController : UIViewController <NeoNuiSdkDelegate> {
    char _taskId[33];
}
@property(nonatomic, strong) NeoNui *nui;
@property(nonatomic, strong) dispatch_queue_t sdkQueue;
@end

@implementation FileTranscriberViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.sdkQueue = dispatch_queue_create("com.example.file-transcriber", DISPATCH_QUEUE_SERIAL);
    self.nui = [[NeoNui alloc] init];
    self.nui.delegate = self;
    [self startRecognition];
}

- (void)startRecognition {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"wav"];
    NSString *appkey = @"<APPKEY>";
    NSString *token = @"<NLS_TOKEN>";
    if (filePath.length == 0) {
        NSLog(@"Audio file not found");
        return;
    }

    dispatch_async(self.sdkQueue, ^{
        NSDictionary *initParams = @{
            @"app_key": appkey,
            @"token": token,
            @"device_id": [[NSUUID UUID] UUIDString],
            @"url": @"https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/FlashRecognizer"
        };
        NSData *initData = [NSJSONSerialization dataWithJSONObject:initParams options:0 error:nil];
        NSString *initJSON = [[NSString alloc] initWithData:initData encoding:NSUTF8StringEncoding];
        int ret = [self.nui nui_initialize:[initJSON UTF8String]
                                 logLevel:NUI_LOG_LEVEL_NONE saveLog:NO];
        if (ret != 0) {
            NSLog(@"Initialize failed: %d", ret);
            [self releaseSDK];
            return;
        }

        NSDictionary *taskParams = @{
            @"file_path": filePath,
            @"nls_config": @{@"format": @"wav", @"sample_rate": @16000}
        };
        NSData *taskData = [NSJSONSerialization dataWithJSONObject:taskParams options:0 error:nil];
        NSString *taskJSON = [[NSString alloc] initWithData:taskData encoding:NSUTF8StringEncoding];
        ret = [self.nui nui_file_trans_start:[taskJSON UTF8String] taskId:self->_taskId];
        if (ret != 0) {
            NSLog(@"Start failed: %d", ret);
            [self releaseSDK];
        }
    });
}

- (void)onFileTransEventCallback:(NuiCallbackEvent)event
                     asrResult:(const char *)asrResult
                        taskId:(const char *)taskId
                      ifFinish:(BOOL)finish
                       retCode:(int)code {
    if (event != EVENT_FILE_TRANS_RESULT && event != EVENT_ASR_ERROR) {
        return;
    }
    NSString *result = asrResult ? [NSString stringWithUTF8String:asrResult] : @"";
    dispatch_async(self.sdkQueue, ^{
        if (self.nui == nil) {
            return;
        }
        if (event == EVENT_FILE_TRANS_RESULT) {
            NSLog(@"Recognition result: %@", result);
        } else {
            NSLog(@"Recognition failed: %d; %@", code, result);
        }
        [self releaseSDK];
    });
}

- (void)cancelRecognition {
    dispatch_async(self.sdkQueue, ^{
        if (self.nui != nil && self->_taskId[0] != '\0') {
            int ret = [self.nui nui_file_trans_cancel:self->_taskId];
            if (ret != 0) {
                NSLog(@"Cancel failed: %d", ret);
            }
        }
        [self releaseSDK];
    });
}

- (void)releaseSDK {
    [self.nui nui_release];
    self.nui.delegate = nil;
    self.nui = nil;
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self cancelRecognition];
}
@end

初始化、任务参数和识别结果字段的完整说明,请参见移动端 SDK 说明。

SDK 关键接口

使用 [NeoNui get_instance] 获取共享实例,也可以使用 [[NeoNui alloc] init] 创建独立实例。同一实例再次初始化前,先释放已有 SDK 资源。

初始化与参数设置

nui_initialize 初始化 SDK,nui_set_params 使用 JSON 字符串设置参数。

- (NuiResultCode)nui_initialize:(const char *)parameters
                     logLevel:(NuiSdkLogLevel)level
                      saveLog:(BOOL)saveLog;

- (NuiResultCode)nui_set_params:(const char *)params;

参数

类型

说明

parameters

const char *

初始化配置的 JSON 字符串。

level

NuiSdkLogLevel

日志级别。枚举值越小,日志越详细。

saveLog

BOOL

是否保存日志文件。为 YES 时,日志保存到初始化参数 debug_path 指定的目录。

params

const char *

nui_set_params 的参数配置 JSON 字符串。

初始化配置和可设置的参数请参见移动端 SDK 说明。更新 Token 时,通过 nui_set_params 传入包含 token 字段的 JSON。

开始与取消识别

nui_file_trans_start 发起文件识别,SDK 将生成的任务 ID 写入 taskId 指向的缓冲区。nui_file_trans_cancel 取消指定任务。

- (NuiResultCode)nui_file_trans_start:(const char *)params
                            taskId:(char *)taskId;

- (NuiResultCode)nui_file_trans_cancel:(const char *)taskId;

参数

类型

说明

params

const char *

文件识别参数的 JSON 字符串,包含 file_path 和 nls_config 等配置。

taskId(开始)

char *

输出参数,用于接收 SDK 生成的任务 ID。示例使用 33 字节缓冲区。

taskId(取消)

const char *

需要取消的任务 ID。

释放资源

调用 nui_release 释放 SDK 资源。

- (NuiResultCode)nui_release;

以上接口返回 0 表示接口调用成功,非 0 表示发生错误。识别结果通过事件回调返回。

错误码及处理方式请参见错误码查询。

事件回调

在实现 NeoNuiSdkDelegate 的代理对象中处理文件识别事件。

- (void)onFileTransEventCallback:(NuiCallbackEvent)event
                     asrResult:(const char *)asrResult
                        taskId:(const char *)taskId
                      ifFinish:(BOOL)finish
                       retCode:(int)code;

参数

类型

说明

event

NuiCallbackEvent

回调事件类型。

asrResult

const char *

识别结果或错误信息。

taskId

const char *

当前任务的唯一 ID。

finish

BOOL

当前任务是否结束。

code

int

错误码,在 EVENT_ASR_ERROR 事件中有效。

主要事件如下。

事件

说明

EVENT_FILE_TRANS_CONNECTED

已连接文件识别服务。

EVENT_FILE_TRANS_UPLOADED

文件上传完成。

EVENT_FILE_TRANS_RESULT

返回最终识别结果。

EVENT_ASR_ERROR

发生错误,根据错误码处理。

常见问题

iOS 是否支持后台处理?

SDK 不限制前后台调用,App 在后台的执行时间由 iOS 管理。文件识别通过网络上传本地文件,无需开启麦克风或配置后台录音。

如需让网络任务在 App 切入后台后继续执行,应在开始长时间任务前调用 iOS 的 beginBackgroundTaskWithExpirationHandler: 申请有限的后台执行时间,并在完成或到期时结束后台任务。具体用法请参见 Apple 的延长 App 后台执行时间说明。

真机运行时报 no suitable image found,如何处理?

检查 App 链接和嵌入的库是否适用于真机,以及 Framework 的嵌入与签名配置。当前 SDK 使用 XCFramework,真机和模拟器分别使用对应平台的变体。确认配置后,可清理工程、删除设备上的旧 App 并重新安装。

存在签名错误时,修正签名证书、Provisioning Profile 与 App 的对应配置,再重新签名和打包。

导入 NeoNui.h 时报错,如何处理?

使用 #import <nuisdk/NeoNui.h> 导入头文件,并确认 SDK 已添加到 App 目标,Framework 搜索路径能够定位目标平台的 nuisdk.framework。动态库的嵌入与签名按下载安装步骤配置。

提示 Framework 同时面向 iOS 和 iOS Simulator,如何处理?

使用当前 SDK 的 nuisdk.xcframework 集成,由 Xcode 选择真机或模拟器变体。使用旧版 Framework 包时,应选择与目标平台匹配的库。平台变体的组织方式请参见 Apple 的创建多平台二进制 Framework说明。

App Store 提示包含不支持的模拟器架构,如何处理?

真机归档应使用 XCFramework 的真机变体。旧版混合 Framework 包含 x86_64、i386 等模拟器架构时,可使用 lipo -info 查看 Framework 内二进制文件的架构,并为真机归档使用不含模拟器架构的库。

集成时是否需要切换到 Legacy Build System?

使用当前 SDK 的 XCFramework,并按工程的目标平台配置集成。旧工程出现库平台不匹配时,应更新或替换对应平台的 SDK 库;构建系统的选择不能改变库的目标平台。