使用说明
本文介绍如何在你的项目中集成和使用依图实时语音转写(中文)插件(以下简称“依图实时转写插件”)。
技术原理
依图实时转写插件是对依图核心 API 的封装。通过声网 SDK v4.x 提供的 setExtensionProperty
方法,传入指定的 key
和 value
参数,你可以快速集成依图的语音转写能力。
setExtensionProperty
方法的 key
参数与依图的 API 名称完全对应,value
参数以 JSON 格式包装该 API 的部分或全部参数。因此,调用该方法时只要传入指定的 key
和 value
,就可以调用对应的依图 API,实现语音转写的有关功能。
前提条件
Android 开发环境需满足以下要求:
- JDK 8 或以上版本。
- Android Studio 4.1 以上版本。
- 搭载 arm64-v8a 或 armeabi-v7a 的真机(非模拟器)。
示例项目
依图实时转写插件提供了一个 Gitee 示例项目,你可以前往查看完整的项目结构和示例代码。
平台 | 语言 | 示例项目 |
---|---|---|
Android | Java | agora/android |
iOS | Objective-C | agora/ios |
运行步骤
参考以下步骤快速跑通示例项目:
-
克隆仓库:
Shellgit clone https://gitee.com/shanghai-yitu-network/saas-demo.git
-
在声网控制台购买和激活依图实时语音转写(中文)插件,购买成功后,保存好弹窗中展示的
devId
和accessKey
。 -
进入声网控制台 > 云市场页面,下载依图实时语音转写(中文)的 Android 插件动态库压缩包。
-
解压文件夹,将所有
.aar
文件保存到项目文件夹的Android/app/libs
路径。 -
在 Android Studio 中打开示例项目。
-
将项目与 Gradle 文件同步。
-
打开
MainActivity.java
文件,填入你的声网 App ID。获取 App ID 请参考开通服务。Java// 第 32 行
private static final String appId = ""; -
连接一台 Android 真机(非模拟器),运行项目。
预期效果
运行成功后,示例项目会安装到你的设备上。
-
启动 App,在设置 DEVID、设置公钥输入框中分别填入购买插件时获取的
devId
和accessKey
,注意删除输入框内自带的=
。 -
单击左下角的 ENABLE 按钮启动倾听。
-
对着麦克风说话,语音转写文本会显示在文本视图中。
-
单击右下角的关闭码流按钮停止转写。
集成和调用流程
本节介绍如何集成声网 SDK 和插件,并调用核心 API 实现转写功能。
1. 集成 SDK 和插件
开始前,你需要在项目中分别集成声网音频 SDK 和依图实时转写插件。
1.1 集成声网音频 SDK
依图实时转写插件需要与声网音频 SDK v4.x 搭配使用。参考以下文档集成音频 SDK v4.x 并实现基础的语音通话:
1.2 购买和激活插件
在声网控制台购买和激活依图实时转写插件。购买成功后,保存好弹窗中展示的 devId
和 accessKey
,后续初始化插件时需要用到。
1.3 集成插件
参考以下步骤在你的项目中集成插件:
-
进入声网控制台 > 云市场页面下载依图实时语音转写(中文)的 Android 插件包。
-
解压后,将所有
.aar
文件保存到项目文件夹的/app/libs
路径。 -
打开
app/build.gradle
文件,在dependencies
中添加如下行:Javaimplementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
-
导入需要用到的类:
Javaimport io.agora.extension.yitu.ExtensionManager;
1.4 升级插件
声网云市场推荐你更新插件版本前使用数据库工具 (如 SQLite) 来实现插件版本管理,从而确保插件版本与对应的资源包版本一致。因为当插件版本和资源包版本未对齐时,会出现 App 闪退、崩溃等现象。
以下是用 SQLite 来进行插件版本管理的示例:
- 使用 SQLite 数据库自行维护插件包和资源包的版本信息。
- 每次项目初始化时,自动检测当前项目使用的资源包版本:
- 如果无记录文件或记录的资源包版本为旧,则更新资源。成功更新后,回写最新资源包版本信息到 SQLite。
- 如果记录的资源包版本与当前匹配,则正常实现业务。
如果你的项目已经集成过声网云市场提供的第三方插件,并需要更新插件,可以参考以下步骤来保证更新后的可用性。
以下升级流程以相芯美颜特效插件为例:
-
参考集成插件章节下载所需平台最新版本的插件包和资源包。
-
删除项目内旧版本的插件包及其资源包后,再将新版插件和资源包放入对应位置。或者直接在对应目录下用新版插件和资源包替换旧版。
-
删除设备上用老版本插件和资源包编译的 App,重新编译你的项目并运行。
编译 App 时,系统会优先使用连接设备上存在的资源包。请务必在删除旧版本应用程序后再进行编译和运行,否则可能会出现插件版本与资源包不匹配的情况,从而导致各种意外问题。
2. 启用插件
创建并初始化 RtcEngine
后,调用 addExtension
加载插件并且调用 enableExtension
开启插件,然后调用其它 API(enableVideo
、joinChannel
等)。
RtcEngineConfig config = new RtcEngineConfig();
config.addExtension(ExtensionManager.EXTENSION_NAME);
mRtcEngine = RtcEngine.create(config);
mRtcEngine.enableExtension(ExtensionManager.EXTENSION_VENDOR_NAME, ExtensionManager.EXTENSION_AUDIO_FILTER_NAME, true);
3. 初始化插件
调用 setExtensionProperty
,依次设置依图服务器 IP、端口、devId
、accessKey
。
public static final String EXTENSION_VENDOR_NAME = "Yitu";
public static final String EXTENSION_AUDIO_FILTER_NAME = "YituSpeechRecognition";
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "ip", "127.0.0.1");
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "port", "8080");
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "devID", "2333");
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "accessKey", "21354515312");
4. 建立 WebSocket 连接
调用 setExtensionProperty
,发起 WebSocket 连接。
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "command", "WebSocketConnect");
如果 WebSocket 连接成功,依图插件会返回 onEvent(WebSocketConnectResult, success)
回调。
成功建立 WebSocket 连接后,如果 10 秒内无任何操作,服务器将自动断开连接,此时你会收到 onEvent(WebSocketConnectResult, remoteClose)
回调。
5. 创建任务
收到成功连接 WebSocket 的回调后,你需要调用 setExtensionProperty
创建任务。目前依图只支持采样率 sampleRate
为 16000。
收到声网 SDK 的 onStarted
回调后,调用 getExtensionProperty
,传入 key
为 getSpeakersInfo
,获取音色列表:
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "createTask", "{\"audioConfig\":{\"aue\":\"PCM\",\"sampleRate\":16000},\"speechConfig\":{\"lang\":\"MANDARIN\",\"customWord\":[\"依图\",\"卡拉 O K\"],\"recognizeType\":\"STREAMING\",\"wordsReplace\":{\"keywords\":[\"回忆\"],\"replace\":[\"什么\"]}}}");
其中 value
参数的 JSON 格式如下,各字段的解释详见 JSON 字段说明。
{
"audioConfig": {
"aue": "PCM",
"sampleRate": 16000
},
"speechConfig": {
"lang": "MANDARIN",
"customWord": ["依图", "卡拉 O K"],
"recognizeType": "STREAMING",
"wordsReplace": {
"keywords": ["回忆"],
"replace": ["什么"]
}
}
}
6.接收解析结果
创建完任务后,依图插件会自动开启码流解析,返回 onEvent(recognizedResult, "识别结果")
回调。解析过程中会多次返回结果,isFinal
字段为 true
代表是最终的返回结果。
返回结果的 JSON 示例:
{
"globalStreamId": "85987bdd-c187-4019-a8e7-1a6ecb3ad840",
"result": {
"isFinal": true,
"bestTranscription": {
"transcribedText": "啊什么一",
"piece": [
{
"transcribedText": "啊",
"endTimestamp": 60,
"transcribedType": 20
},
{
"transcribedText": "什",
"beginTimestamp": 840,
"endTimestamp": 930,
"transcribedType": 20
},
{
"transcribedText": "么",
"beginTimestamp": 930,
"endTimestamp": 1020,
"transcribedType": 20
},
{
"transcribedText": "一",
"beginTimestamp": 1050,
"endTimestamp": 1110,
"transcribedType": 20
}
]
},
"status": {
"processedTimestamp": 1500
}
}
}
各字段的解释详见 JSON 字段说明。
7. 关闭任务
需要停止识别时,调用 setExtensionProperty
关闭任务。关闭任务代表插件不再接收新的码流,已经接收到的码流仍然会返回解析结果。
mRtcEngine.setExtensionProperty(EXTENSION_VENDOR_NAME, EXTENSION_AUDIO_FILTER_NAME, "command", "turnOffAudioStream");
8. 再次开启或修改配置
关闭任务后,如果需要再次开启实时转写或需要修改配置参数,从第 3 步建立 WebSocket 连接开始即可。
参考信息
API 参考
常见问题
1. 在 MacBook 上运行 Android 示例项目为什么会编译失败?
由于示例项目中 Android NDK 的路径默认为 Windows 设备上的路径,因此在 MacBook 上会编译失败并提示 Location specified by ndk.dir did not contain a valid NDK
。参考以下步骤解决:
- 在 Android Studio 的顶部菜单栏中依次点击 File > Project Structure... > SDK Location,将 Android NDK location 的路径替换为你的本地路径,并且复制该路径。
- 打开
local.properties
文件,将ndk.dir
的路径替换为你刚才复制的路径,并且保存修改。 - 连接 Android 设备,再次运行。
2. 为什么在编译 App 时会出现 models: no match
的报错?
该错误通常是由于资源包匹配问题引起的。很可能是因为在编译新插件时,没有删除旧版本的 App。建议你删除旧版 App 后重新编译运行。