|
@@ -0,0 +1,130 @@
|
|
|
+package com.jd.controller;
|
|
|
+
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+
|
|
|
+import javax.sound.sampled.AudioFileFormat;
|
|
|
+import javax.sound.sampled.AudioFormat;
|
|
|
+import javax.sound.sampled.AudioInputStream;
|
|
|
+import javax.sound.sampled.AudioSystem;
|
|
|
+import javax.websocket.OnClose;
|
|
|
+import javax.websocket.OnError;
|
|
|
+import javax.websocket.OnMessage;
|
|
|
+import javax.websocket.OnOpen;
|
|
|
+import javax.websocket.Session;
|
|
|
+import javax.websocket.server.ServerEndpoint;
|
|
|
+
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import com.jd.util.IatTool;
|
|
|
+
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+@ServerEndpoint(value = "/xfyun/socket/voice")
|
|
|
+public class VoiceController {
|
|
|
+
|
|
|
+ private String appid = "5c20ae83";
|
|
|
+ private String uploadFile = "D:/workspace/xfyunAip/uploadfile";
|
|
|
+
|
|
|
+ private static AtomicInteger onlineCount = new AtomicInteger(0);
|
|
|
+
|
|
|
+ @OnOpen
|
|
|
+ public void onOpen(Session session) {
|
|
|
+ onlineCount.incrementAndGet();
|
|
|
+ log.info("有新连接加入:{},当前在线人数为:{}", session.getId(), onlineCount.get());
|
|
|
+ }
|
|
|
+
|
|
|
+ @OnClose
|
|
|
+ public void onClose(Session session) {
|
|
|
+ onlineCount.decrementAndGet();
|
|
|
+ log.info("有一连接关闭:{},当前在线人数为:{}", session.getId(), onlineCount.get());
|
|
|
+ }
|
|
|
+
|
|
|
+ @OnError
|
|
|
+ public void onError(Session session, Throwable error) {
|
|
|
+ log.error("发生错误");
|
|
|
+ error.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
+
|
|
|
+ AudioFormat audioFormat = getAudioFormat();
|
|
|
+
|
|
|
+ private boolean status = false;
|
|
|
+
|
|
|
+ @OnMessage
|
|
|
+ public void onMessage(String data, Session session) {
|
|
|
+ if ("start".equals(data)) {
|
|
|
+ baos.reset();
|
|
|
+ status = true;
|
|
|
+ } else if ("end".equals(data)) {
|
|
|
+ status = false;
|
|
|
+ JSONObject obj = new JSONObject();
|
|
|
+ obj.set("type", "asr");
|
|
|
+ obj.set("data", saveWav());
|
|
|
+ try {
|
|
|
+ session.getBasicRemote().sendText(obj.toJSONString(0));
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @OnMessage
|
|
|
+ public void onMessage(InputStream inputStream, Session session) {
|
|
|
+ if (!status) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 一个帧 160ms的音频数据
|
|
|
+ byte[] buffer = new byte[4096];
|
|
|
+ try {
|
|
|
+ inputStream.read(buffer);
|
|
|
+ baos.write(buffer);
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ IatTool iatTool = new IatTool(appid);
|
|
|
+ private String saveWav() {
|
|
|
+ try {
|
|
|
+ byte audioData[] = baos.toByteArray();
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(audioData);
|
|
|
+ AudioInputStream ais = new AudioInputStream(bais, audioFormat,
|
|
|
+ audioData.length / audioFormat.getFrameSize());
|
|
|
+ // 定义最终保存的文件名
|
|
|
+ System.out.println("开始生成语音文件");
|
|
|
+
|
|
|
+ String path = uploadFile + "/" + System.currentTimeMillis() + ".wav";
|
|
|
+ File file = new File(path);
|
|
|
+ AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);
|
|
|
+ ais.close();
|
|
|
+ bais.close();
|
|
|
+ baos.reset();
|
|
|
+
|
|
|
+ String txt = iatTool.RecognizePcmfileByte(file);
|
|
|
+ file.delete();
|
|
|
+ return txt;
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ public static AudioFormat getAudioFormat() {
|
|
|
+ AudioFormat audioFormat = new AudioFormat(16000F, 16, 1, true, false);
|
|
|
+ // true,false 指示是以 big-endian 顺序还是以 little-endian 顺序存储音频数据。
|
|
|
+ return audioFormat;// 构造具有线性 PCM 编码和给定参数的 AudioFormat。
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|