本文介绍如何使用 HarmonyOS Next NUI SDK 实现录音文件识别极速版,包括 SDK 集成、调用流程、代码示例、接口和回调。
前提条件
已了解录音文件识别极速版的参数和使用限制,详情请参见录音文件识别极速版移动端 SDK 接口说明。
已获取项目 Appkey,详情请参见管理项目。
已获取有效的 NLS Token(Access Token),详情请参见获取 Token。
由应用服务端获取 NLS Token,再下发到客户端。不要将 AccessKey ID、AccessKey Secret 写入客户端代码或保存在设备端,也不要在日志中输出 Token 或包含 Token 的初始化参数。
下载安装与集成
解压 SDK 包,将
entry/libs/neonui.har导入应用工程。SDK 包同时提供 C++ 动态库和头文件,分别位于native/libs和native/include。使用 DevEco Studio 打开示例工程,在
entry/src/main/ets/Utils/UserKey.ets中填写 Appkey 和 Token,再运行entry/src/main/ets/pages/FileTranscriberPage.ets。
调用流程
创建 SDK 实例,实现
INativeFileTransCallback。调用
initializeFileTrans初始化 SDK,再按需调用setParams设置参数。准备音频文件路径和编码格式,调用
startFileTranscriber。在
EVENT_FILE_TRANS_RESULT回调中获取最终识别结果。不再使用时调用
release释放 SDK 资源。
SDK 接口为同步调用,不要在 UI 线程调用,以免阻塞界面。不要在 SDK 的事件回调中直接调用 SDK 接口,以免死锁;需要继续调用时,将操作调度到回调之外执行。
代码示例
以下示例展示 SDK 调用片段,不是独立的应用页面。完整页面为 SDK 包中的 FileTranscriberPage.ets,业务封装为 entry/src/main/ets/neonui/FileTranscriber.ets。资源目录使用应用上下文的 resourceDir + "/resources_cloud",调试目录使用可写的 filesDir。
示例通过构造函数创建实例,也可使用 NativeNui.GetInstance() 获取单例。对同一实例重新初始化前,先释放其资源。
初始化
导入 SDK 类型。callback 为下文的文件识别回调实现,其他参数由应用提供。
import { NativeNui, Constants, INativeFileTransCallback, AsrResult } from 'neonui';
function createFileRecognizer(callback: INativeFileTransCallback, resourceDir: string,
filesDir: string, appkey: string, token: string, deviceId: string): NativeNui {
const nui = new NativeNui(Constants.ModeType.MODE_DIALOG, 'file');
const parameters: Record<string, string> = {
app_key: appkey,
token: token,
device_id: deviceId,
url: 'https://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/FlashRecognizer',
workspace: resourceDir + '/resources_cloud',
debug_path: filesDir,
service_mode: Constants.ModeFullCloud
};
const ret = nui.initializeFileTrans(callback, JSON.stringify(parameters),
Constants.LogLevel.LOG_LEVEL_VERBOSE, false);
if (ret !== Constants.NuiResultCode.SUCCESS) {
throw new Error('initializeFileTrans failed: ' + ret);
}
return nui;
}
app_key、token、唯一的 device_id 和可读写的 workspace 为必填项。debug_path 用于保存调试文件。需要保存调试音频时,可配置 save_wav,同时开启 save_log 并保证调试目录有效、可写。
设置参数
function configureFileRecognizer(nui: NativeNui): number {
const nlsConfig: Record<string, boolean> = { enable_intermediate_result: true };
const parameters: Record<string, Object> = { nls_config: nlsConfig };
return nui.setParams(JSON.stringify(parameters));
}
开始识别
示例使用工程中的 entry/src/main/resources/resfile/2.wav。将应用上下文中的 resourceDir 传入函数,format 必须与文件的实际编码一致。任务 ID 缓冲区至少需要 33 字节。
function startFileRecognition(nui: NativeNui, resourceDir: string): ArrayBuffer {
const nlsConfig: Record<string, string> = { format: 'wav' };
const parameters: Record<string, Object> = {
file_path: resourceDir + '/2.wav',
nls_config: nlsConfig
};
const taskId = new ArrayBuffer(33);
const ret = nui.startFileTranscriber(JSON.stringify(parameters), taskId);
if (ret !== Constants.NuiResultCode.SUCCESS) {
throw new Error('startFileTranscriber failed: ' + ret);
}
return taskId;
}
需要在运行时切换项目时,可在任务参数中设置 app_key。
处理回调
识别结果位于 flash_result.sentences,每个句子的文本位于 text。以下示例按任务 ID 缓存多个文件的结果。
interface RecognizedSentence {
text: string;
}
interface FlashResult {
sentences: RecognizedSentence[];
}
interface FileRecognitionResponse {
flash_result: FlashResult;
}
class FileCallbackHandle implements INativeFileTransCallback {
taskResults: Map<string, string> = new Map();
combinedResults: string = '';
onFileTransEventCallback(event: Constants.NuiEvent, resultCode: number,
finish: number, asrResult: AsrResult, taskId: string): void {
if (event === Constants.NuiEvent.EVENT_FILE_TRANS_UPLOADED) {
console.info('file uploaded: ' + taskId);
} else if (event === Constants.NuiEvent.EVENT_ASR_ERROR) {
console.error('recognition error: ' + resultCode + ', task: ' + taskId);
} else if (event === Constants.NuiEvent.EVENT_FILE_TRANS_RESULT &&
asrResult && asrResult.asrResult) {
const response = JSON.parse(asrResult.asrResult) as FileRecognitionResponse;
if (response.flash_result) {
let text = '';
response.flash_result.sentences.forEach((sentence: RecognizedSentence) => {
text += sentence.text;
});
this.taskResults.set(taskId, text);
this.combinedResults = '';
this.taskResults.forEach((value: string, key: string) => {
this.combinedResults += key + ': ' + value + '\n';
});
}
}
}
}
释放资源
function releaseFileRecognizer(nui: NativeNui): number {
return nui.release();
}
关键接口与参数
参数含义和使用条件请参见接口说明。接口返回码及错误处理请参见错误码查询。
初始化与参数设置
initializeFileTrans(callback: INativeFileTransCallback, parameters: string,
level: number, save_log: boolean = false): number
setParams(params: string): number
parameters 和 params 为 JSON 字符串。level 为日志级别,值越小输出越多。save_log 默认关闭。初始化成功后、开始任务前调用 setParams。
识别与资源管理
startFileTranscriber(params: string, task_id: ArrayBuffer): number
cancelFileTranscriber(task_id: string): number
release(): number
startFileTranscriber 的 params 包含音频路径等参数。task_id 用于接收 SDK 生成的任务 ID,缓冲区至少分配 33 字节。cancelFileTranscriber 接收要取消的任务 ID 字符串。release 释放 SDK 资源。
回调和事件
onFileTransEventCallback(event: Constants.NuiEvent, resultCode: number,
finish: number, asrResult: AsrResult, taskId: string): void
event 为任务事件,resultCode 在 EVENT_ASR_ERROR 时提供错误码。第三个参数为保留参数;asrResult 为识别结果,taskId 为任务 ID。
|
事件 |
说明 |
|
EVENT_FILE_TRANS_CONNECTED |
连接识别服务成功。 |
|
EVENT_FILE_TRANS_UPLOADED |
文件上传成功。 |
|
EVENT_FILE_TRANS_RESULT |
返回最终识别结果。 |
|
EVENT_ASR_ERROR |
识别错误,根据错误码排查。 |
常见问题
如何通过任务 ID 查询状态?
本 SDK 不提供按任务 ID 查询状态的 API。通过 onFileTransEventCallback 接收对应任务的连接、上传、识别结果和错误事件。
是否支持 OPUS 音频?
本 SDK 的一句话识别和录音文件识别极速版支持 OPUS 数据;实时语音识别仅支持 PCM 编码、16 bit 采样位数和单声道。详情请参见接口说明。
接口调用超时导致应用无响应,如何处理?
避免在 UI 线程执行同步 SDK 调用。线程调度方式可参考 SDK 包中的 OneSentenceAsrWorker.ets。