跳至主要内容

实时语音识别库 Wrp 的使用方法

Wrp库可以使用与 AmiVoice SDK 相似的接口,通过 AmiVoice API 的 WebSocket 接口开发实时应用程序。可以发送流式音频并逐步接收结果。该库可用于 Java、C#、C++、Python、PHP 等语言。

客户端程序概述

使用Wrp的程序流程如下:

图. 命令和事件

方法

客户端程序按顺序执行以下处理。()中列出了对应的Wrp方法。

  1. 连接 (connect)
  2. 发送语音识别请求 (feedDataResume)
  3. 发送音频数据 (feedData)
  4. 结束音频数据发送 (feedDataPause)
  5. 断开连接 (disconnect)

事件

来自服务器的语音检测和语音识别通知事件都通过监听器类的方法获得。有以下5种事件。()中列出了Wrp需要实现的方法名称。

  • 检测到语音开始时通知的事件 utteranceStarted(startTime)
  • 检测到语音结束时通知的事件 utteranceEnded(endTime)
  • 语音识别处理开始时通知的事件 resultCreated()
  • 识别中间结果的通知事件 resultUpdated(result)
  • 识别结果的通知事件 resultFinalized(result)

必须实现识别结果通知事件 resultFinalized(result)。根据需要实现其他处理服务器通知的方法。

实现指南

我们将逐步说明如何使用Wrp,并给出每种语言的示例。

以下代码示例均摘自 GitHub 存储库 advanced-media-inc/amivoice-api-client-library 中公开的 WrpSimpleTester。完整代码请参考以下源文件:

有关执行方法和文件结构等说明,请参阅客户端库的示例程序WrpSimpleTester

1. 初始化

创建Wrp类的实例。

		// 初始化 WebSocket 语音识别服务器
com.amivoice.wrp.Wrp wrp = com.amivoice.wrp.Wrp.construct();

2. 实现监听器类

继承com.amivoice.wrp.WrpListener类并实现事件处理程序。

语音识别结果通过resultFinalized的参数result获得。详细信息请参阅语音识别结果格式的WebSocket 接口。另外,识别结果文本使用 UTF-8 编码并进行 Unicode 转义。另请参阅关于结果文本

以下代码在utteranceStartedutteranceEndedresultCreatedresultUpdatedresultFinalized各方法中实现了将日志输出到标准输出。通过wrp.setListener(listener)将实现了这些方法的监听器实例设置到wrp实例。使用text_方法解码结果文本的 Unicode 转义。text_方法的完整代码在 GitHub 上公开。

public class WrpTester implements com.amivoice.wrp.WrpListener {
public static void main(String[] args) {
// 创建 WebSocket 语音识别服务器事件监听器
com.amivoice.wrp.WrpListener listener = new WrpTester(verbose);
wrp.setListener(listener);
}

@Override
public void utteranceStarted(int startTime) {
System.out.println("S " + startTime);
}

@Override
public void utteranceEnded(int endTime) {
System.out.println("E " + endTime);
}

@Override
public void resultCreated() {
System.out.println("C");
}

@Override
public void resultUpdated(String result) {
System.out.println("U " + result);
String text = text_(result);
if (text != null) {
System.out.println(" -> " + text);
}
}

@Override
public void resultFinalized(String result) {
System.out.println("F " + result);
String text = text_(result);
if (text != null) {
System.out.println(" -> " + text);
}
}

3. 连接 (connect)

连接到语音识别服务器。

在调用此方法之前,必须设置以下参数:

  • serverURL ... WebSocket 接口的 endpoint

请指定以下 URL:

wss://acp-api.amivoice.com/v1/     (保存日志)
wss://acp-api.amivoice.com/v1/nolog/ (不保存日志)

可以通过设置以下参数来调整行为:

  • proxyServerName ... 当客户端程序通过代理服务器连接时指定
  • connectTimeout ... 与服务器的连接超时。单位为毫秒。
  • receiveTimeout ... 从服务器接收数据的超时。单位为毫秒。

有关服务器端超时,请参阅限制事项

以下代码连接到语音识别服务器。如果verbosefalse,则不显示错误消息。

		wrp.setServerURL(serverURL);
wrp.setProxyServerName(proxyServerName);
wrp.setConnectTimeout(connectTimeout);
wrp.setReceiveTimeout(receiveTimeout);

// 连接到 WebSocket 语音识别服务器
if (!wrp.connect()) {
if (!verbose) {
System.out.println(wrp.getLastMessage());
}
System.out.println("WebSocket 音声認識サーバ " + serverURL + " への接続に失敗しました。");
return;
}

4. 语音识别请求 (feedDataResume)

发送语音识别请求。该方法会阻塞,直到连接到请求参数中指定的适当的语音识别服务器,或准备好单词注册。如果失败,则返回错误。详情请参阅 s 命令响应数据包的错误消息

在调用此方法之前,必须设置以下参数:

可以通过设置以下参数来调整行为:

  • profileId
  • profileWords
  • keepFillerToken
  • segmenterProperties
  • resultUpdatedInterval

详情请参阅参数详细信息

注意

为避免死锁,请不要从用于接收事件通知的监听器类的方法(如 resultFinalized 等)中调用 feedDataResume 方法。

以下代码基于上述参数向服务器发送语音识别请求,并在出错时将消息显示在标准输出上。如果 verbosefalse,则不显示错误消息。

        wrp.setCodec(codec);
wrp.setGrammarFileNames(grammarFileNames);
wrp.setAuthorization(authorization);

// 开始向 WebSocket 语音识别服务器发送音频数据
if (!wrp.feedDataResume()) {
if (!verbose) {
System.out.println(wrp.getLastMessage());
}
System.out.println("WebSocket 音声認識サーバへの音声データの送信の開始に失敗しました。");
break;
}

5. 发送音频数据 (feedData)

接下来发送音频数据。此方法不会阻塞。如果服务器端发生任何错误,将在下一次方法调用时返回错误。有关错误内容,请参阅 p 命令响应数据包的错误消息。开始发送音频数据后,监听器类的方法将根据服务器端的处理被调用。

信息
  • 请发送与 feedDataResume 中指定的 codec 相匹配的音频数据。即使格式不同,也不会出错,但响应时间可能会非常长,或无法正确获得识别结果。
  • 如果从发送的音频数据中无法检测到语音,则不会调用监听器类的方法。可能有以下原因,请检查:
    • 完全不包含音频。或音量非常小。请检查录音系统是否未静音,音量设置是否适当等。
    • 音频格式与音频数据不匹配。请检查音频格式
备注
  • 一次 feedData 方法调用可以发送的最大音频数据大小为 16MB。如果数据大小超过此限制,请将其分割。
  • 音频数据可以在任意位置分割,无需考虑 wav 块或 mp3、flac、opus 等的帧边界。
  • 无法在中途更改要发送的数据格式。如需更改音频格式,请使用 e 命令结束,然后从 s 重新发起语音识别请求。对于带 header 的音频文件,同样需要对每个文件使用 e 命令结束,然后从 s 重新发起语音识别请求。

以下代码从 audioFileName 指定的音频数据文件中读取音频数据,并将其发送到 WebSocket 语音识别服务器。当 sleepTime-1 时,程序会一直休眠直到等待识别结果的数量不超过 1。当 verbosefalse 时,不会显示错误消息。

					try (FileInputStream audioStream = new FileInputStream(audioFileName)) {
// 从音频数据文件读取音频数据
byte[] audioData = new byte[4096];
int audioDataReadBytes = audioStream.read(audioData, 0, audioData.length);
while (audioDataReadBytes > 0) {
// 检查是否已计算休眠时间
if (sleepTime >= 0) {
// 如果已计算休眠时间...
// 短暂休眠
wrp.sleep(sleepTime);
} else {
// 如果未计算休眠时间...
// 短暂休眠
wrp.sleep(1);

// 休眠直到等待识别结果的数量不超过 1
int maxSleepTime = 50000;
while (wrp.getWaitingResults() > 1 && maxSleepTime > 0) {
wrp.sleep(100);
maxSleepTime -= 100;
}
}

// 向 WebSocket 语音识别服务器发送音频数据
if (!wrp.feedData(audioData, 0, audioDataReadBytes)) {
if (!verbose) {
System.out.println(wrp.getLastMessage());
}
System.out.println("WebSocket 音声認識サーバへの音声データの送信に失敗しました。");
break;
}

// 从音频数据文件读取音频数据
audioDataReadBytes = audioStream.read(audioData, 0, audioData.length);
}
} catch (IOException e) {
System.out.println("音声データファイル " + audioFileName + " の読み込みに失敗しました。");
}

6. 结束发送语音数据 (feedDataPause)

当语音数据发送完成时调用此方法。此方法会阻塞直到语音识别处理完成。请求可能因某些原因失败。详情请参阅e命令响应数据包中的错误消息

注意

请不要从用于接收事件通知的监听器类的方法(如resultFinalized)中调用feedDataPause方法,否则可能会导致死锁。

信息

如果不是流式传输而是一次性发送所有语音数据,语音识别处理会需要一些时间,因此需要等待一段时间才能得到结果。预计等待时间约为发送的语音时长的0.5到1.5倍。

以下代码向服务器表明所有语音数据已发送完毕,并阻塞等待结果返回。如果verbosefalse,则不显示错误消息。

					// 完成向WebSocket语音识别服务器发送语音数据
if (!wrp.feedDataPause()) {
if (!verbose) {
System.out.println(wrp.getLastMessage());
}
System.out.println("WebSocket 音声認識サーバへの音声データの送信の完了に失敗しました。");
break;
}

7. 断开连接 (disconnect)

最后断开与语音识别服务器的连接。

			// 断开与WebSocket语音识别服务器的连接
wrp.disconnect();

客户端程序的状态转换

客户端程序会进行以下状态转换。

其他文档