注销互联网语音模块

This commit is contained in:
chenshaohua
2026-04-01 10:43:59 +08:00
parent b09fc0a3ef
commit 013e87f16b
3 changed files with 363 additions and 363 deletions

View File

@@ -1,64 +1,64 @@
package com.ruoyi.cms.handler; //package com.ruoyi.cms.handler;
//
import com.ruoyi.cms.util.AliyunNlsUtils; //import com.ruoyi.cms.util.AliyunNlsUtils;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
//
import javax.websocket.*; //import javax.websocket.*;
import javax.websocket.server.ServerEndpoint; //import javax.websocket.server.ServerEndpoint;
import java.io.ByteArrayInputStream; //import java.io.ByteArrayInputStream;
import java.io.IOException; //import java.io.IOException;
import java.nio.ByteBuffer; //import java.nio.ByteBuffer;
//
@Component //@Component
@ServerEndpoint("/speech-recognition") //@ServerEndpoint("/speech-recognition")
public class SpeechRecognitionWebSocketHandler { //public class SpeechRecognitionWebSocketHandler {
//
private SpeechRecognizerAI recognizerDemo; // private SpeechRecognizerAI recognizerDemo;
//
public SpeechRecognitionWebSocketHandler() { // public SpeechRecognitionWebSocketHandler() {
// 初始化语音识别器 // // 初始化语音识别器
String appKey = "4lFYn2yPsQymwGu8"; // String appKey = "4lFYn2yPsQymwGu8";
String id = "LTAI5t9hhSqdDHqwH3RjgyYj"; // String id = "LTAI5t9hhSqdDHqwH3RjgyYj";
String secret = "ni5aW3vxrWouMwcGqJPfh9Uu56PBuv"; // String secret = "ni5aW3vxrWouMwcGqJPfh9Uu56PBuv";
String url = System.getenv().getOrDefault("NLS_GATEWAY_URL", AliyunNlsUtils.getNlsUrl()+"/ws/v1/"); // String url = System.getenv().getOrDefault("NLS_GATEWAY_URL", AliyunNlsUtils.getNlsUrl()+"/ws/v1/");
recognizerDemo = new SpeechRecognizerAI(appKey, id, secret, url); // recognizerDemo = new SpeechRecognizerAI(appKey, id, secret, url);
} // }
//
/** // /**
* 连接建立成功调用的方法 // * 连接建立成功调用的方法
*/ // */
@OnOpen // @OnOpen
public void onOpen(Session session) { // public void onOpen(Session session) {
System.out.println("WebSocket 连接建立成功sessionId = " + session.getId()); // System.out.println("WebSocket 连接建立成功sessionId = " + session.getId());
} // }
//
/** // /**
* 收到客户端消息后调用的方法 // * 收到客户端消息后调用的方法
*/ // */
@OnMessage(maxMessageSize=5242880) // @OnMessage(maxMessageSize=5242880)
public void onMessage(ByteBuffer message, Session session) throws IOException { // public void onMessage(ByteBuffer message, Session session) throws IOException {
byte[] audioData = new byte[message.remaining()]; // byte[] audioData = new byte[message.remaining()];
message.get(audioData); // message.get(audioData);
//
// 处理音频数据 // // 处理音频数据
recognizerDemo.processStream(session, new ByteArrayInputStream(audioData), 16000); // recognizerDemo.processStream(session, new ByteArrayInputStream(audioData), 16000);
} // }
//
//
/** // /**
* 连接关闭调用的方法 // * 连接关闭调用的方法
*/ // */
@OnClose // @OnClose
public void onClose(Session session) { // public void onClose(Session session) {
System.out.println("WebSocket 连接关闭sessionId = " + session.getId()); // System.out.println("WebSocket 连接关闭sessionId = " + session.getId());
} // }
//
/** // /**
* 发生错误时调用的方法 // * 发生错误时调用的方法
*/ // */
@OnError // @OnError
public void onError(Session session, Throwable error) { // public void onError(Session session, Throwable error) {
System.err.println("WebSocket 发生错误:" + error.getMessage()); // System.err.println("WebSocket 发生错误:" + error.getMessage());
error.printStackTrace(); // error.printStackTrace();
} // }
} //}

View File

@@ -1,148 +1,148 @@
package com.ruoyi.cms.handler; //package com.ruoyi.cms.handler;
//
import com.alibaba.nls.client.AccessToken; //import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.InputFormatEnum; //import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient; //import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum; //import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer; //import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener; //import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse; //import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import com.ruoyi.cms.util.AliyunNlsUtils; //import com.ruoyi.cms.util.AliyunNlsUtils;
import lombok.Data; //import lombok.Data;
import org.slf4j.Logger; //import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//
import javax.websocket.Session; //import javax.websocket.Session;
import java.io.IOException; //import java.io.IOException;
import java.io.InputStream; //import java.io.InputStream;
@Data //@Data
public class SpeechRecognizerAI { //public class SpeechRecognizerAI {
private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizerAI.class); // private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizerAI.class);
private String appKey; // private String appKey;
private NlsClient client; // private NlsClient client;
private AccessToken accessToken; // private AccessToken accessToken;
public SpeechRecognizerAI(String appKey, String id, String secret, String url) { // public SpeechRecognizerAI(String appKey, String id, String secret, String url) {
this.appKey = appKey; // this.appKey = appKey;
//
// 获取 AccessToken // // 获取 AccessToken
accessToken = new AccessToken(id, secret); // accessToken = new AccessToken(id, secret);
try { // try {
if(AliyunNlsUtils.USE_TEST_ENV){ // if(AliyunNlsUtils.USE_TEST_ENV){
accessToken.apply(); // 申请 Token // accessToken.apply(); // 申请 Token
}else{ // }else{
AliyunNlsTokenUtil.generateToken(id, secret, this.accessToken); // AliyunNlsTokenUtil.generateToken(id, secret, this.accessToken);
} // }
//accessToken.apply(); // 申请 Token // //accessToken.apply(); // 申请 Token
logger.info("Token: {}, Expire Time: {}", accessToken.getToken(), accessToken.getExpireTime()); // logger.info("Token: {}, Expire Time: {}", accessToken.getToken(), accessToken.getExpireTime());
//
// 初始化 NlsClient // // 初始化 NlsClient
if (url.isEmpty()) { // if (url.isEmpty()) {
this.client = new NlsClient(accessToken.getToken()); // 使用默认服务地址 // this.client = new NlsClient(accessToken.getToken()); // 使用默认服务地址
} else { // } else {
this.client = new NlsClient(url, accessToken.getToken()); // 使用自定义服务地址 // this.client = new NlsClient(url, accessToken.getToken()); // 使用自定义服务地址
} // }
} catch (Exception e) { // } catch (Exception e) {
logger.error("Failed to initialize NlsClient: {}", e.getMessage()); // logger.error("Failed to initialize NlsClient: {}", e.getMessage());
} // }
} // }
//
public void processStream(Session session, InputStream inputStream, int sampleRate) { // public void processStream(Session session, InputStream inputStream, int sampleRate) {
SpeechRecognizer recognizer = null; // SpeechRecognizer recognizer = null;
try { // try {
// 创建 SpeechRecognizer 实例 // // 创建 SpeechRecognizer 实例
recognizer = new SpeechRecognizer(client, new SpeechRecognizerListener() { // recognizer = new SpeechRecognizer(client, new SpeechRecognizerListener() {
@Override // @Override
public void onRecognitionResultChanged(SpeechRecognizerResponse response) { // public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
// 打印中间识别结果 // // 打印中间识别结果
String text = response.getRecognizedText(); // String text = response.getRecognizedText();
logger.info("中间识别结果: {}", text); // logger.info("中间识别结果: {}", text);
//
sendResult(session, text,false); // sendResult(session, text,false);
} // }
//
@Override // @Override
public void onRecognitionCompleted(SpeechRecognizerResponse response) { // public void onRecognitionCompleted(SpeechRecognizerResponse response) {
// 打印最终识别结果 // // 打印最终识别结果
String text = response.getRecognizedText(); // String text = response.getRecognizedText();
logger.info("最终识别结果: {}", text); // logger.info("最终识别结果: {}", text);
sendResult(session, text,true); // sendResult(session, text,true);
} // }
//
@Override // @Override
public void onStarted(SpeechRecognizerResponse response) { // public void onStarted(SpeechRecognizerResponse response) {
logger.info("识别开始, TaskId: {}", response.getTaskId()); // logger.info("识别开始, TaskId: {}", response.getTaskId());
} // }
//
@Override // @Override
public void onFail(SpeechRecognizerResponse response) { // public void onFail(SpeechRecognizerResponse response) {
logger.error("识别失败: {}", response.getStatusText()); // logger.error("识别失败: {}", response.getStatusText());
} // }
}); // });
//
// 设置语音识别参数 // // 设置语音识别参数
recognizer.setAppKey(appKey); // recognizer.setAppKey(appKey);
recognizer.setFormat(InputFormatEnum.PCM); // recognizer.setFormat(InputFormatEnum.PCM);
recognizer.setSampleRate(sampleRate == 16000 ? // recognizer.setSampleRate(sampleRate == 16000 ?
SampleRateEnum.SAMPLE_RATE_16K : SampleRateEnum.SAMPLE_RATE_8K); // SampleRateEnum.SAMPLE_RATE_16K : SampleRateEnum.SAMPLE_RATE_8K);
recognizer.setEnableIntermediateResult(true); // recognizer.setEnableIntermediateResult(true);
recognizer.addCustomedParam("enable_voice_detection", true); // recognizer.addCustomedParam("enable_voice_detection", true);
//
// 启动识别 // // 启动识别
recognizer.start(); // recognizer.start();
//
// 读取音频流并发送 // // 读取音频流并发送
byte[] buffer = new byte[3200]; // byte[] buffer = new byte[3200];
int len; // int len;
while ((len = inputStream.read(buffer)) > 0) { // while ((len = inputStream.read(buffer)) > 0) {
recognizer.send(buffer, len); // recognizer.send(buffer, len);
} // }
//
// 停止识别 // // 停止识别
recognizer.stop(); // recognizer.stop();
} catch (Exception e) { // } catch (Exception e) {
logger.error("处理音频流时出错: {}", e.getMessage()); // logger.error("处理音频流时出错: {}", e.getMessage());
} finally { // } finally {
if (recognizer != null) { // if (recognizer != null) {
recognizer.close(); // recognizer.close();
} // }
} // }
} // }
//
private void sendResult(Session session, String text,Boolean asrEnd) { // private void sendResult(Session session, String text,Boolean asrEnd) {
try { // try {
session.getBasicRemote().sendText("{\"text\": \"" + text + "\",\"asrEnd\":\"" + asrEnd + "\"}"); // session.getBasicRemote().sendText("{\"text\": \"" + text + "\",\"asrEnd\":\"" + asrEnd + "\"}");
} catch (IOException e) { // } catch (IOException e) {
logger.error("发送识别结果失败: {}", e.getMessage()); // logger.error("发送识别结果失败: {}", e.getMessage());
} // }
} // }
//
public void shutdown() { // public void shutdown() {
if (client != null) { // if (client != null) {
client.shutdown(); // client.shutdown();
} // }
} // }
/** // /**
* 获取当前有效的 AccessToken // * 获取当前有效的 AccessToken
* // *
* @param id 阿里云 AccessKey ID // * @param id 阿里云 AccessKey ID
* @param secret 阿里云 AccessKey Secret // * @param secret 阿里云 AccessKey Secret
* @return 返回申请到的 AccessToken 字符串,失败时返回 null // * @return 返回申请到的 AccessToken 字符串,失败时返回 null
*/ // */
public static String getAccessToken(String id, String secret) { // public static String getAccessToken(String id, String secret) {
try { // try {
AccessToken accessToken = new AccessToken(id, secret); // AccessToken accessToken = new AccessToken(id, secret);
accessToken.apply(); // 申请 token // accessToken.apply(); // 申请 token
//
if (accessToken.getToken() != null) { // if (accessToken.getToken() != null) {
logger.info("成功获取 Token: {}, 过期时间: {}", accessToken.getToken(), accessToken.getExpireTime()); // logger.info("成功获取 Token: {}, 过期时间: {}", accessToken.getToken(), accessToken.getExpireTime());
return accessToken.getToken(); // return accessToken.getToken();
} else { // } else {
logger.error("get token fail:"+accessToken.getToken()); // logger.error("get token fail:"+accessToken.getToken());
return null; // return null;
} // }
} catch (IOException e) { // } catch (IOException e) {
logger.error("申请 Token 时发生网络错误: {}", e.getMessage()); // logger.error("申请 Token 时发生网络错误: {}", e.getMessage());
return null; // return null;
} // }
} // }
} //}

View File

@@ -1,151 +1,151 @@
package com.ruoyi.cms.handler; //package com.ruoyi.cms.handler;
//
import com.alibaba.nls.client.AccessToken; //import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.NlsClient; //import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum; //import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum; //import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer; //import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener; //import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse; //import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import com.ruoyi.cms.util.AliyunNlsUtils; //import com.ruoyi.cms.util.AliyunNlsUtils;
import org.slf4j.Logger; //import org.slf4j.Logger;
import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; //import org.springframework.stereotype.Component;
//
import javax.websocket.*; //import javax.websocket.*;
import javax.websocket.server.ServerEndpoint; //import javax.websocket.server.ServerEndpoint;
import java.io.IOException; //import java.io.IOException;
import java.nio.ByteBuffer; //import java.nio.ByteBuffer;
//
@Component //@Component
@ServerEndpoint("/speech-synthesis") //@ServerEndpoint("/speech-synthesis")
public class SpeechSynthesisWebSocketHandler { //public class SpeechSynthesisWebSocketHandler {
private static final Logger logger = LoggerFactory.getLogger(SpeechSynthesisWebSocketHandler.class); // private static final Logger logger = LoggerFactory.getLogger(SpeechSynthesisWebSocketHandler.class);
//
private NlsClient client; // private NlsClient client;
private String appKey = "mtA2pwmvCeefHT3Y"; // private String appKey = "mtA2pwmvCeefHT3Y";
private String accessKeyId = "LTAI5tRBahK93vPNF1JDVEPA"; // private String accessKeyId = "LTAI5tRBahK93vPNF1JDVEPA";
private String accessKeySecret = "x95OWb4cV6ccQVtbEJ2Gxm2Uwl2thJ"; // private String accessKeySecret = "x95OWb4cV6ccQVtbEJ2Gxm2Uwl2thJ";
private String url = AliyunNlsUtils.getNlsUrl()+"/ws/v1/"; // private String url = AliyunNlsUtils.getNlsUrl()+"/ws/v1/";
//
public SpeechSynthesisWebSocketHandler() { // public SpeechSynthesisWebSocketHandler() {
// Initialize NLS client with token // // Initialize NLS client with token
AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret); // AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
try { // try {
if(AliyunNlsUtils.USE_TEST_ENV){ // if(AliyunNlsUtils.USE_TEST_ENV){
accessToken.apply(); // accessToken.apply();
}else{ // }else{
AliyunNlsTokenUtil.generateToken(accessKeyId, accessKeySecret, accessToken); // AliyunNlsTokenUtil.generateToken(accessKeyId, accessKeySecret, accessToken);
} // }
//accessToken.apply(); // //accessToken.apply();
String token = accessToken.getToken(); // String token = accessToken.getToken();
if(url.isEmpty()) { // if(url.isEmpty()) {
this.client = new NlsClient(token); // this.client = new NlsClient(token);
} else { // } else {
this.client = new NlsClient(url, token); // this.client = new NlsClient(url, token);
} // }
} catch (Exception e) { // } catch (Exception e) {
logger.error("Failed to initialize NLS client", e); // logger.error("Failed to initialize NLS client", e);
} // }
} // }
//
@OnOpen // @OnOpen
public void onOpen(Session session) { // public void onOpen(Session session) {
logger.info("WebSocket connected for speech synthesis, sessionId: {}", session.getId()); // logger.info("WebSocket connected for speech synthesis, sessionId: {}", session.getId());
} // }
//
@OnMessage(maxMessageSize=5242880) // @OnMessage(maxMessageSize=5242880)
public void onMessage(String text, Session session) { // public void onMessage(String text, Session session) {
logger.info("Received text for synthesis: {}", text); // logger.info("Received text for synthesis: {}", text);
//
SpeechSynthesizer synthesizer = null; // SpeechSynthesizer synthesizer = null;
try { // try {
// Create synthesizer with a session-specific listener // // Create synthesizer with a session-specific listener
synthesizer = new SpeechSynthesizer(client, createSynthesizerListener(session)); // synthesizer = new SpeechSynthesizer(client, createSynthesizerListener(session));
//
// Configure synthesizer // // Configure synthesizer
synthesizer.setAppKey(appKey); // synthesizer.setAppKey(appKey);
synthesizer.setFormat(OutputFormatEnum.WAV); // synthesizer.setFormat(OutputFormatEnum.WAV);
synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K); // synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
synthesizer.setVoice("aiqi"); // synthesizer.setVoice("aiqi");
synthesizer.setPitchRate(0); // synthesizer.setPitchRate(0);
synthesizer.setSpeechRate(0); // synthesizer.setSpeechRate(0);
//
// Use long text synthesis // // Use long text synthesis
synthesizer.setLongText(text); // synthesizer.setLongText(text);
//
// Start synthesis // // Start synthesis
synthesizer.start(); // synthesizer.start();
//
} catch (Exception e) { // } catch (Exception e) {
logger.error("Error during speech synthesis", e); // logger.error("Error during speech synthesis", e);
try { // try {
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Synthesis error")); // session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, "Synthesis error"));
} catch (IOException ioException) { // } catch (IOException ioException) {
logger.error("Error closing session", ioException); // logger.error("Error closing session", ioException);
} // }
} finally { // } finally {
// Note: We can't close the synthesizer here because synthesis is async // // Note: We can't close the synthesizer here because synthesis is async
// It should be closed in the listener's onComplete/onFail methods // // It should be closed in the listener's onComplete/onFail methods
} // }
} // }
//
@OnClose // @OnClose
public void onClose(Session session) { // public void onClose(Session session) {
logger.info("WebSocket closed for speech synthesis, sessionId: {}", session.getId()); // logger.info("WebSocket closed for speech synthesis, sessionId: {}", session.getId());
} // }
//
@OnError // @OnError
public void onError(Session session, Throwable error) { // public void onError(Session session, Throwable error) {
logger.error("WebSocket error for session {}: {}", session.getId(), error.getMessage(), error); // logger.error("WebSocket error for session {}: {}", session.getId(), error.getMessage(), error);
} // }
//
private SpeechSynthesizerListener createSynthesizerListener(Session session) { // private SpeechSynthesizerListener createSynthesizerListener(Session session) {
return new SpeechSynthesizerListener() { // return new SpeechSynthesizerListener() {
private boolean firstRecvBinary = true; // private boolean firstRecvBinary = true;
private long startTime; // private long startTime;
//
@Override // @Override
public void onComplete(SpeechSynthesizerResponse response) { // public void onComplete(SpeechSynthesizerResponse response) {
logger.info("Synthesis completed for session {}, status: {}", session.getId(), response.getStatus()); // logger.info("Synthesis completed for session {}, status: {}", session.getId(), response.getStatus());
try { // try {
// Send a close message or marker to indicate completion // // Send a close message or marker to indicate completion
session.getBasicRemote().sendText("{\"status\":\"complete\"}"); // session.getBasicRemote().sendText("{\"status\":\"complete\"}");
} catch (IOException e) { // } catch (IOException e) {
logger.error("Error sending completion message", e); // logger.error("Error sending completion message", e);
} // }
} // }
//
@Override // @Override
public void onMessage(ByteBuffer message) { // public void onMessage(ByteBuffer message) {
try { // try {
if (firstRecvBinary) { // if (firstRecvBinary) {
firstRecvBinary = false; // firstRecvBinary = false;
startTime = System.currentTimeMillis(); // startTime = System.currentTimeMillis();
logger.info("First audio packet received for session {}", session.getId()); // logger.info("First audio packet received for session {}", session.getId());
} // }
//
// Send audio data to client // // Send audio data to client
byte[] bytesArray = new byte[message.remaining()]; // byte[] bytesArray = new byte[message.remaining()];
message.get(bytesArray, 0, bytesArray.length); // message.get(bytesArray, 0, bytesArray.length);
session.getBasicRemote().sendBinary(ByteBuffer.wrap(bytesArray)); // session.getBasicRemote().sendBinary(ByteBuffer.wrap(bytesArray));
//
} catch (IOException e) { // } catch (IOException e) {
logger.error("Error sending audio data to client", e); // logger.error("Error sending audio data to client", e);
} // }
} // }
//
@Override // @Override
public void onFail(SpeechSynthesizerResponse response) { // public void onFail(SpeechSynthesizerResponse response) {
logger.error("Synthesis failed for session {}: task_id: {}, status: {}, status_text: {}", // logger.error("Synthesis failed for session {}: task_id: {}, status: {}, status_text: {}",
session.getId(), response.getTaskId(), response.getStatus(), response.getStatusText()); // session.getId(), response.getTaskId(), response.getStatus(), response.getStatusText());
try { // try {
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, // session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION,
"Synthesis failed: " + response.getStatusText())); // "Synthesis failed: " + response.getStatusText()));
} catch (IOException e) { // } catch (IOException e) {
logger.error("Error closing failed session", e); // logger.error("Error closing failed session", e);
} // }
} // }
}; // };
} // }
} //}