Files
senmesh-zc/src/main/java/com/newyetai/sdk/xf/service/RtasrClientApp.java
2025-08-15 10:03:33 +08:00

155 lines
5.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.newyetai.sdk.xf.service;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.xfyun.api.RtasrClient;
import cn.xfyun.model.response.rtasr.RtasrResponse;
import cn.xfyun.service.rta.AbstractRtasrWebSocketListener;
import com.newyetai.common.AlitaResult;
import com.newyetai.common.util.JsonUtils;
import com.newyetai.sdk.xf.config.XfProperties;
import java.io.InputStream;
import java.util.concurrent.CountDownLatch;
import okhttp3.Response;
import okhttp3.WebSocket;
import org.apache.commons.codec.binary.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ( Real-time ASR ) 实时语音转写 1、APPID、APIKey信息获取:<a
* href="https://console.xfyun.cn/services/rta">...</a> 2、文档地址:<a
* href="https://www.xfyun.cn/doc/asr/rtasr/API.html">...</a>
*
* @author kaili23
*/
public class RtasrClientApp extends AbstractRtasrWebSocketListener{
private static final Logger logger = LoggerFactory.getLogger(RtasrClientApp.class);
/**
* 记录完整结果
*/
private StringBuffer finalResult = new StringBuffer();
private AlitaResult<String> result;
/**
* 线程同步
*/
private CountDownLatch latch;
RtasrClientApp(CountDownLatch latch){
this.latch = latch;
}
public AlitaResult<String> getResult() {
return result;
}
@Override
public void onSuccess(WebSocket webSocket, String text) {
RtasrResponse response = JsonUtils.toObject(text, RtasrResponse.class);
// finalResult为服务端已转写的完整语句,后面拼接服务端本次返回的当前语句的转写中间结果。
String tempResult = handleAndReturnContent(response.getData());
logger.info("实时转写结果:{}", finalResult + tempResult);
result = AlitaResult.success(finalResult.toString());
}
@Override
public void onFail(WebSocket webSocket, Throwable t, Response response) {
result = AlitaResult.bizError(t.getMessage());
latch.countDown();
webSocket.close(1000, "");
}
@Override
public void onBusinessFail(WebSocket webSocket, String text) {
logger.error("业务异常,返回信息为:{}", text);
result = AlitaResult.bizError(text);
latch.countDown();
webSocket.close(1000, "");
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
latch.countDown();
webSocket.close(1000, "");
}
@Override
public void onClosed() {
latch.countDown();
}
public static AlitaResult<String> execute(InputStream is, String from, XfProperties xfProperties) {
try {
CountDownLatch latch = new CountDownLatch(1);
RtasrClientApp app = new RtasrClientApp(latch);
RtasrClient client = new RtasrClient.Builder()
.signature(xfProperties.getAppId(), xfProperties.getRtasr().getApiKey())
.lang(from)
// 设置此参数需需开通翻译功能,请在控制台申请并开通
// .targetLang(to)
.build();
client.send(is, app);
latch.await();
return app.getResult();
} catch (Exception e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
logger.error("语音转写失败", e);
return AlitaResult.error("语音转写失败:{}", e.getMessage());
}
}
/**
* 解析转写流式响应,更新实时结果,返回此次的中间结果
*/
public String handleAndReturnContent(String message) {
StringBuilder tempResult = new StringBuilder();
try {
// 解析本次服务端返回的文本内容
JSONObject messageObj = JSONUtil.parseObj(message);
JSONObject cn = messageObj.getJSONObject("cn");
JSONObject st = cn.getJSONObject("st");
JSONArray rtArr = st.getJSONArray("rt");
for (int i = 0; i < rtArr.size(); i++) {
JSONObject rtArrObj = rtArr.getJSONObject(i);
JSONArray wsArr = rtArrObj.getJSONArray("ws");
for (int j = 0; j < wsArr.size(); j++) {
JSONObject wsArrObj = wsArr.getJSONObject(j);
JSONArray cwArr = wsArrObj.getJSONArray("cw");
for (int k = 0; k < cwArr.size(); k++) {
JSONObject cwArrObj = cwArr.getJSONObject(k);
String wStr = cwArrObj.getStr("w");
tempResult.append(wStr);
}
}
}
// 根据中间结果类型更新最终结果
String type = st.getStr("type");
if (StringUtils.equals("1", type)) {
// 此时服务端返回的是当前语句的实时转写内容,不保存到最终结果中,返回到调用处进行拼接展示。
return tempResult.toString();
} else if (StringUtils.equals("0", type)) {
// 此时服务端返回的是当前语句的完整转写内容,保存到最终结果中,并返回空字符串。
finalResult.append(tempResult);
return "";
} else {
logger.warn("未知的转写响应类型:{}", type);
return tempResult.toString();
}
} catch (Exception e) {
return message;
}
}
}