yaorongkeji 5 mesiacov pred
rodič
commit
74093b079b

+ 40 - 0
hcp-app/src/main/java/com/yingyangfly/app/controller/VoiceController.java

@@ -1,5 +1,6 @@
 package com.yingyangfly.app.controller;
 
+import com.yingyangfly.app.util.AsrMain;
 import com.yingyangfly.app.util.BaiduVoiceUtil;
 import com.yingyangfly.common.dto.ResultResponse;
 import com.yingyangfly.common.log.annotation.TraceLog;
@@ -7,15 +8,23 @@ import com.yingyangfly.common.utils.MD5Util;
 import com.yingyangfly.core.annotation.Log;
 import com.yingyangfly.core.dto.SpeechSynthesis;
 import com.yingyangfly.core.enums.OperatorType;
+import com.yingyangfly.core.vo.AsrVo;
 import com.yingyangfly.redis.client.RedisClient;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * 声音语音合成
  *
@@ -25,6 +34,7 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/app/video")
 @Api(tags = "声音语音合成")
+@Slf4j
 public class VoiceController {
 
     @Autowired
@@ -58,4 +68,34 @@ public class VoiceController {
             return baiduVoiceUtil.getVoiceUrl(voiceMsg,"3");
         }
     }
+
+
+    @PostMapping("/vs")
+    public Map sendAsr(@RequestBody AsrVo p) {
+        log.info("【***************收到语音识别请求****************】");
+        Map ret = new HashMap();
+        try {
+            AsrMain demo = new AsrMain();
+            // 填写下面信息
+            String result = demo.run(this.shortArrayToByteArray(p.getContent(), ByteOrder.LITTLE_ENDIAN));
+            ret.put("code", "0");
+            ret.put("result", result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("【语音识别系统错误】");
+            ret.put("code", "900");
+            ret.put("msg", "调用语音接口失败");
+        }
+        log.info("【***************结果已发送给客户端****************】");
+        return ret;
+    }
+
+    private byte[] shortArrayToByteArray(short[] shorts, ByteOrder order) {
+        byte[] bytes = new byte[shorts.length * 2];
+        ByteBuffer.wrap(bytes)
+                .order(order)
+                .asShortBuffer()
+                .put(shorts);
+        return bytes;
+    }
 }

+ 292 - 0
hcp-app/src/main/java/com/yingyangfly/app/util/AsrMain.java

@@ -0,0 +1,292 @@
+package com.yingyangfly.app.util;
+
+import com.yingyangfly.app.util.baidu.common.Base64Util;
+import com.yingyangfly.app.util.baidu.common.ConnUtil;
+import com.yingyangfly.app.util.baidu.common.DemoException;
+import com.yingyangfly.app.util.baidu.common.TokenHolder;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class AsrMain {
+
+    private final boolean METHOD_RAW = false; // 默认以json方式上传音频文件
+
+    //  填写网页上申请的appkey 如 $apiKey="g8eBUMSokVB1BHGmgxxxxxx"
+    private final String APP_KEY = "DCie3SjWpSUEv8Q5X5hSxRxg";
+
+    // 填写网页上申请的APP SECRET 如 $SECRET_KEY="94dc99566550d87f8fa8ece112xxxxx"
+    private final String SECRET_KEY = "egjl5HPocG4GlbazXQcJSJBp4wzmHHxL";
+
+    // 需要识别的文件
+    private final String FILENAME = "16k.wav";
+
+    // 文件格式, 支持pcm/wav/amr 格式,极速版额外支持m4a 格式
+    private final String FORMAT = FILENAME.substring(FILENAME.length() - 3);
+
+
+    private String CUID = "1234567JAVA";
+
+    // 采样率固定值
+    private final int RATE = 16000;
+
+    private String URL;
+
+    private int DEV_PID;
+
+    //private int LM_ID;//测试自训练平台需要打开此注释
+
+    private String SCOPE;
+
+    //  普通版 参数
+//    {
+//        URL = "http://vop.baidu.com/server_api"; // 可以改为https
+//        //  1537 表示识别普通话,使用输入法模型。 其它语种参见文档
+//        DEV_PID = 1537;
+//        SCOPE = "audio_voice_assistant_get";
+//    }
+
+    // 自训练平台 参数
+    /*{
+        //自训练平台模型上线后,您会看见 第二步:“”获取专属模型参数pid:8001,modelid:1234”,按照这个信息获取 dev_pid=8001,lm_id=1234
+        DEV_PID = 8001;
+        LM_ID = 1234;
+    }*/
+
+    /* 极速版 参数*/
+    {
+        URL =   "http://vop.baidu.com/pro_api"; // 可以改为https
+        DEV_PID = 80001;
+        SCOPE = "brain_enhanced_asr";
+    }
+
+
+    /* 忽略scope检查,非常旧的应用可能没有
+    {
+        SCOPE = null;
+    }
+    */
+
+    public static void main(String[] args) throws IOException, DemoException {
+        AsrMain demo = new AsrMain();
+        // 填写下面信息
+        String result = demo.run();
+        System.out.println("识别结束:结果是:");
+        System.out.println(result);
+
+        // 如果显示乱码,请打开result.txt查看
+        File file = new File("result.txt");
+        FileWriter fo = new FileWriter(file);
+        fo.write(result);
+        fo.close();
+        System.out.println("Result also wrote into " + file.getAbsolutePath());
+    }
+
+    public String run(byte[] content) throws IOException, DemoException {
+        TokenHolder holder = new TokenHolder(APP_KEY, SECRET_KEY, SCOPE);
+//        holder.resfresh();
+//        String token = holder.getToken();
+        String result = null;
+        if (METHOD_RAW) {
+//            result = runRawPostMethod(token);
+        } else {
+//            result = runJsonPostMethod(token);
+            result = runJsonPostWhithApiKey(content);
+        }
+        return result;
+    }
+
+    /**
+     * 使用ApiKey调用语音转文字接口
+     * @return
+     * @throws DemoException
+     * @throws IOException
+     */
+    public String runJsonPostWhithApiKey(byte[] content) throws DemoException, IOException {
+
+//        byte[] content = getFileContent(FILENAME);
+        String speech = base64Encode(content);
+//        String speech = content;
+
+        JSONObject params = new JSONObject();
+        params.put("dev_pid", DEV_PID);
+        //params.put("lm_id",LM_ID);//测试自训练平台需要打开注释
+        params.put("format", FORMAT);
+        params.put("rate", RATE);
+//        params.put("token", token);
+        params.put("cuid", CUID);
+        params.put("channel", "1");
+        params.put("len", content.length);
+//        params.put("len", co);
+        params.put("speech", speech);
+
+//        System.out.println(params.toString());
+        HttpURLConnection conn = (HttpURLConnection) new URL(URL).openConnection();
+        conn.setRequestProperty("Authorization", "Bearer bce-v3/ALTAK-Igmc9iQIIETCHcRT6DAR0/5e238c4f1df92474f2b122e155e1b71f9dbe36b6");
+        conn.setConnectTimeout(5000);
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
+        conn.setDoOutput(true);
+        //发送语音
+        conn.getOutputStream().write(params.toString().getBytes());
+        conn.getOutputStream().close();
+        String result = ConnUtil.getResponseString(conn);
+
+//        params.put("speech", "base64Encode(getFileContent(FILENAME))");
+//        System.out.println("url is : " + URL);
+//        System.out.println("params is :" + params.toString());
+
+        return result;
+    }
+
+    public String run() throws IOException, DemoException {
+        TokenHolder holder = new TokenHolder(APP_KEY, SECRET_KEY, SCOPE);
+//        holder.resfresh();
+//        String token = holder.getToken();
+        String result = null;
+        if (METHOD_RAW) {
+//            result = runRawPostMethod(token);
+        } else {
+//            result = runJsonPostMethod(token);
+            result = runJsonPostWhithApiKey();
+        }
+        return result;
+    }
+
+    /**
+     * 使用ApiKey调用语音转文字接口
+     * @return
+     * @throws DemoException
+     * @throws IOException
+     */
+    public String runJsonPostWhithApiKey() throws DemoException, IOException {
+
+        byte[] content = getFileContent(FILENAME);
+        String speech = base64Encode(content);
+
+        JSONObject params = new JSONObject();
+        params.put("dev_pid", DEV_PID);
+        //params.put("lm_id",LM_ID);//测试自训练平台需要打开注释
+        params.put("format", FORMAT);
+        params.put("rate", RATE);
+//        params.put("token", token);
+        params.put("cuid", CUID);
+        params.put("channel", "1");
+        params.put("len", content.length);
+        params.put("speech", speech);
+
+        // System.out.println(params.toString());
+        HttpURLConnection conn = (HttpURLConnection) new URL(URL).openConnection();
+        conn.setRequestProperty("Authorization", "Bearer bce-v3/ALTAK-Igmc9iQIIETCHcRT6DAR0/5e238c4f1df92474f2b122e155e1b71f9dbe36b6");
+        conn.setConnectTimeout(5000);
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
+        conn.setDoOutput(true);
+        //发送语音
+        conn.getOutputStream().write(params.toString().getBytes());
+        conn.getOutputStream().close();
+        String result = ConnUtil.getResponseString(conn);
+
+
+        params.put("speech", "base64Encode(getFileContent(FILENAME))");
+        System.out.println("url is : " + URL);
+        System.out.println("params is :" + params.toString());
+
+
+        return result;
+    }
+    private String runRawPostMethod(String token) throws IOException, DemoException {         
+        String url2 = URL + "?cuid=" + ConnUtil.urlEncode(CUID) + "&dev_pid=" + DEV_PID + "&token=" + token;
+        //测试自训练平台需要打开以下信息
+        //String url2 = URL + "?cuid=" + ConnUtil.urlEncode(CUID) + "&dev_pid=" + DEV_PID + "&lm_id="+ LM_ID + "&token=" + token;
+        String contentTypeStr = "audio/" + FORMAT + "; rate=" + RATE;
+        //System.out.println(url2);
+        byte[] content = getFileContent(FILENAME);
+        HttpURLConnection conn = (HttpURLConnection) new URL(url2).openConnection();
+        conn.setConnectTimeout(5000);
+        conn.setRequestProperty("Content-Type", contentTypeStr);
+        conn.setRequestMethod("POST");
+        conn.setDoOutput(true);
+        conn.getOutputStream().write(content);
+        conn.getOutputStream().close();
+        System.out.println("url is " + url2);
+        System.out.println("header is  " + "Content-Type :" + contentTypeStr);
+        String result = ConnUtil.getResponseString(conn);
+        return result;
+    }
+
+    public String runJsonPostMethod(String token) throws DemoException, IOException {
+
+        byte[] content = getFileContent(FILENAME);
+        String speech = base64Encode(content);
+
+        JSONObject params = new JSONObject();
+        params.put("dev_pid", DEV_PID);
+        //params.put("lm_id",LM_ID);//测试自训练平台需要打开注释
+        params.put("format", FORMAT);
+        params.put("rate", RATE);
+        params.put("token", token);
+        params.put("cuid", CUID);
+        params.put("channel", "1");
+        params.put("len", content.length);
+        params.put("speech", speech);
+
+        // System.out.println(params.toString());
+        HttpURLConnection conn = (HttpURLConnection) new URL(URL).openConnection();
+        conn.setConnectTimeout(5000);
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
+        conn.setDoOutput(true);
+        conn.getOutputStream().write(params.toString().getBytes());
+        conn.getOutputStream().close();
+        String result = ConnUtil.getResponseString(conn);
+
+
+        params.put("speech", "base64Encode(getFileContent(FILENAME))");
+        System.out.println("url is : " + URL);
+        System.out.println("params is :" + params.toString());
+
+
+        return result;
+    }
+
+    private byte[] getFileContent(String filename) throws DemoException, IOException {
+        File file = new File(filename);
+        if (!file.canRead()) {
+            System.err.println("文件不存在或者不可读: " + file.getAbsolutePath());
+            throw new DemoException("file cannot read: " + file.getAbsolutePath());
+        }
+        FileInputStream is = null;
+        try {
+            is = new FileInputStream(file);
+            return ConnUtil.getInputStreamContent(is);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+
+    }
+
+    private String base64Encode(byte[] content) {
+        /**
+         Base64.Encoder encoder = Base64.getEncoder(); // JDK 1.8  推荐方法
+         String str = encoder.encodeToString(content);
+         **/
+
+        char[] chars = Base64Util.encode(content); // 1.7 及以下,不推荐,请自行跟换相关库
+        String str = new String(chars);
+
+        return str;
+    }
+
+}

+ 321 - 0
hcp-app/src/main/java/com/yingyangfly/app/util/baidu/common/Base64Util.java

@@ -0,0 +1,321 @@
+package com.yingyangfly.app.util.baidu.common;
+
+import java.io.*;
+
+/**
+ * Base64 编码和解码。
+ *
+ * @author jiangshuai
+ * @date 2016年10月03日
+ */
+public class Base64Util {
+
+    public Base64Util() {
+    }
+
+    /**
+     * 功能:编码字符串
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param data
+     *            源字符串
+     * @return String
+     */
+    public static String encode(String data) {
+        return new String(encode(data.getBytes()));
+    }
+
+    /**
+     * 功能:解码字符串
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param data
+     *            源字符串
+     * @return String
+     */
+    public static String decode(String data) {
+        return new String(decode(data.toCharArray()));
+    }
+
+    /**
+     * 功能:编码byte[]
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param data
+     *            源
+     * @return char[]
+     */
+    public static char[] encode(byte[] data) {
+        char[] out = new char[((data.length + 2) / 3) * 4];
+        for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
+            boolean quad = false;
+            boolean trip = false;
+
+            int val = (0xFF & (int) data[i]);
+            val <<= 8;
+            if ((i + 1) < data.length) {
+                val |= (0xFF & (int) data[i + 1]);
+                trip = true;
+            }
+            val <<= 8;
+            if ((i + 2) < data.length) {
+                val |= (0xFF & (int) data[i + 2]);
+                quad = true;
+            }
+            out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
+            val >>= 6;
+            out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
+            val >>= 6;
+            out[index + 1] = alphabet[val & 0x3F];
+            val >>= 6;
+            out[index + 0] = alphabet[val & 0x3F];
+        }
+        return out;
+    }
+
+    /**
+     * 功能:解码
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param data
+     *            编码后的字符数组
+     * @return byte[]
+     */
+    public static byte[] decode(char[] data) {
+
+        int tempLen = data.length;
+        for (int ix = 0; ix < data.length; ix++) {
+            if ((data[ix] > 255) || codes[data[ix]] < 0) {
+                --tempLen; // ignore non-valid chars and padding
+            }
+        }
+        // calculate required length:
+        // -- 3 bytes for every 4 valid base64 chars
+        // -- plus 2 bytes if there are 3 extra base64 chars,
+        // or plus 1 byte if there are 2 extra.
+
+        int len = (tempLen / 4) * 3;
+        if ((tempLen % 4) == 3) {
+            len += 2;
+        }
+        if ((tempLen % 4) == 2) {
+            len += 1;
+
+        }
+        byte[] out = new byte[len];
+
+        int shift = 0; // # of excess bits stored in accum
+        int accum = 0; // excess bits
+        int index = 0;
+
+        // we now go through the entire array (NOT using the 'tempLen' value)
+        for (int ix = 0; ix < data.length; ix++) {
+            int value = (data[ix] > 255) ? -1 : codes[data[ix]];
+
+            if (value >= 0) { // skip over non-code
+                accum <<= 6; // bits shift up by 6 each time thru
+                shift += 6; // loop, with new bits being put in
+                accum |= value; // at the bottom.
+                if (shift >= 8) { // whenever there are 8 or more shifted in,
+                    shift -= 8; // write them out (from the top, leaving any
+                    out[index++] = // excess at the bottom for next iteration.
+                            (byte) ((accum >> shift) & 0xff);
+                }
+            }
+        }
+
+        // if there is STILL something wrong we just have to throw up now!
+        if (index != out.length) {
+            throw new Error("Miscalculated data length (wrote " + index
+                    + " instead of " + out.length + ")");
+        }
+
+        return out;
+    }
+
+    /**
+     * 功能:编码文件
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param file
+     *            源文件
+     */
+    public static void encode(File file) throws IOException {
+        if (!file.exists()) {
+            System.exit(0);
+        }
+
+        else {
+            byte[] decoded = readBytes(file);
+            char[] encoded = encode(decoded);
+            writeChars(file, encoded);
+        }
+        file = null;
+    }
+
+    /**
+     * 功能:解码文件。
+     *
+     * @author jiangshuai
+     * @date 2016年10月03日
+     * @param file
+     *            源文件
+     * @throws IOException
+     */
+    public static void decode(File file) throws IOException {
+        if (!file.exists()) {
+            System.exit(0);
+        } else {
+            char[] encoded = readChars(file);
+            byte[] decoded = decode(encoded);
+            writeBytes(file, decoded);
+        }
+        file = null;
+    }
+
+    //
+    // code characters for values 0..63
+    //
+    private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+            .toCharArray();
+
+    //
+    // lookup table for converting base64 characters to value in range 0..63
+    //
+    private static byte[] codes = new byte[256];
+    static {
+        for (int i = 0; i < 256; i++) {
+            codes[i] = -1;
+            // LoggerUtil.debug(i + "&" + codes[i] + " ");
+        }
+        for (int i = 'A'; i <= 'Z'; i++) {
+            codes[i] = (byte) (i - 'A');
+            // LoggerUtil.debug(i + "&" + codes[i] + " ");
+        }
+
+        for (int i = 'a'; i <= 'z'; i++) {
+            codes[i] = (byte) (26 + i - 'a');
+            // LoggerUtil.debug(i + "&" + codes[i] + " ");
+        }
+        for (int i = '0'; i <= '9'; i++) {
+            codes[i] = (byte) (52 + i - '0');
+            // LoggerUtil.debug(i + "&" + codes[i] + " ");
+        }
+        codes['+'] = 62;
+        codes['/'] = 63;
+    }
+
+    private static byte[] readBytes(File file) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] b = null;
+        InputStream fis = null;
+        InputStream is = null;
+        try {
+            fis = new FileInputStream(file);
+            is = new BufferedInputStream(fis);
+            int count = 0;
+            byte[] buf = new byte[16384];
+            while ((count = is.read(buf)) != -1) {
+                if (count > 0) {
+                    baos.write(buf, 0, count);
+                }
+            }
+            b = baos.toByteArray();
+
+        } finally {
+            try {
+                if (fis != null)
+                    fis.close();
+                if (is != null)
+                    is.close();
+                if (baos != null)
+                    baos.close();
+            } catch (Exception e) {
+                System.out.println(e);
+            }
+        }
+
+        return b;
+    }
+
+    private static char[] readChars(File file) throws IOException {
+        CharArrayWriter caw = new CharArrayWriter();
+        Reader fr = null;
+        Reader in = null;
+        try {
+            fr = new FileReader(file);
+            in = new BufferedReader(fr);
+            int count = 0;
+            char[] buf = new char[16384];
+            while ((count = in.read(buf)) != -1) {
+                if (count > 0) {
+                    caw.write(buf, 0, count);
+                }
+            }
+
+        } finally {
+            try {
+                if (caw != null)
+                    caw.close();
+                if (in != null)
+                    in.close();
+                if (fr != null)
+                    fr.close();
+            } catch (Exception e) {
+                System.out.println(e);
+            }
+        }
+
+        return caw.toCharArray();
+    }
+
+    private static void writeBytes(File file, byte[] data) throws IOException {
+        OutputStream fos = null;
+        OutputStream os = null;
+        try {
+            fos = new FileOutputStream(file);
+            os = new BufferedOutputStream(fos);
+            os.write(data);
+
+        } finally {
+            try {
+                if (os != null)
+                    os.close();
+                if (fos != null)
+                    fos.close();
+            } catch (Exception e) {
+                System.out.println(e);
+            }
+        }
+    }
+
+    private static void writeChars(File file, char[] data) throws IOException {
+        Writer fos = null;
+        Writer os = null;
+        try {
+            fos = new FileWriter(file);
+            os = new BufferedWriter(fos);
+            os.write(data);
+
+        } finally {
+            try {
+                if (os != null)
+                    os.close();
+                if (fos != null)
+                    fos.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // /////////////////////////////////////////////////
+    // end of test code.
+    // /////////////////////////////////////////////////
+
+}

+ 97 - 0
hcp-app/src/main/java/com/yingyangfly/app/util/baidu/common/ConnUtil.java

@@ -0,0 +1,97 @@
+package com.yingyangfly.app.util.baidu.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URLEncoder;
+
+/**
+ * 与连接相关的Util类
+ */
+public class ConnUtil {
+
+    /**
+     * UrlEncode, UTF-8 编码
+     *
+     * @param str 原始字符串
+     * @return
+     */
+    public static String urlEncode(String str) {
+        String result = null;
+        try {
+            result = URLEncoder.encode(str, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    /**
+     * 从HttpURLConnection 获取返回的字符串
+     *
+     * @param conn
+     * @return
+     * @throws IOException
+     * @throws DemoException
+     */
+    public static String getResponseString(HttpURLConnection conn) throws IOException, DemoException {
+        return new String(getResponseBytes(conn));
+    }
+
+    /**
+     * 从HttpURLConnection 获取返回的bytes
+     * 注意 HttpURLConnection自身问题, 400类错误,会直接抛出异常。不能获取conn.getInputStream();
+     *
+     * @param conn
+     * @return
+     * @throws IOException   http请求错误
+     * @throws DemoException http 的状态码不是 200
+     */
+    public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException, DemoException {
+        int responseCode = conn.getResponseCode();
+        InputStream inputStream = conn.getInputStream();
+        if (responseCode != 200) {
+            System.err.println("http 请求返回的状态码错误,期望200, 当前是 " + responseCode);
+            if (responseCode == 401) {
+                System.err.println("可能是appkey appSecret 填错");
+            }
+            System.err.println("response headers" + conn.getHeaderFields());
+            if (inputStream == null) {
+                inputStream = conn.getErrorStream();
+            }
+            byte[] result = getInputStreamContent(inputStream);
+            System.err.println(new String(result));
+
+            throw new DemoException("http response code is" + responseCode);
+        }
+
+        byte[] result = getInputStreamContent(inputStream);
+        return result;
+    }
+
+    /**
+     * 将InputStream内的内容全部读取,作为bytes返回
+     *
+     * @param is
+     * @return
+     * @throws IOException @see InputStream.read()
+     */
+    public static byte[] getInputStreamContent(InputStream is) throws IOException {
+        byte[] b = new byte[1024];
+        // 定义一个输出流存储接收到的数据
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        // 开始接收数据
+        int len = 0;
+        while (true) {
+            len = is.read(b);
+            if (len == -1) {
+                // 数据读完
+                break;
+            }
+            byteArrayOutputStream.write(b, 0, len);
+        }
+        return byteArrayOutputStream.toByteArray();
+    }
+}

+ 7 - 0
hcp-app/src/main/java/com/yingyangfly/app/util/baidu/common/DemoException.java

@@ -0,0 +1,7 @@
+package com.yingyangfly.app.util.baidu.common;
+
+public class DemoException extends Exception {
+    public DemoException(String message) {
+        super(message);
+    }
+}

+ 125 - 0
hcp-app/src/main/java/com/yingyangfly/app/util/baidu/common/TokenHolder.java

@@ -0,0 +1,125 @@
+package com.yingyangfly.app.util.baidu.common;
+
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * token的获取类
+ * 将apiKey和secretKey换取token,注意有效期保存在expiresAt
+ */
+public class TokenHolder {
+
+
+    public static final String TTS_SCOPE = "audio_tts_post";
+
+    /**
+     * url , Token的url,http可以改为https
+     */
+    private static final String url = "http://aip.baidubce.com/oauth/2.0/token";
+
+    /**
+     * asr的权限 scope 是  "audio_voice_assistant_get"
+     * tts 的权限 scope 是 "audio_tts_post"
+     */
+    private String scope;
+
+    /**
+     * 网页上申请语音识别应用获取的apiKey
+     */
+    private String apiKey;
+
+    /**
+     * 网页上申请语音识别应用获取的secretKey
+     */
+    private String secretKey;
+
+    /**
+     * 保存访问接口获取的token
+     */
+    private String token;
+
+    /**
+     * 当前的时间戳,毫秒
+     */
+    private long expiresAt;
+
+    /**
+     * @param apiKey    网页上申请语音识别应用获取的apiKey
+     * @param secretKey 网页上申请语音识别应用获取的secretKey
+     */
+    public TokenHolder(String apiKey, String secretKey, String scope) {
+        this.apiKey = apiKey;
+        this.secretKey = secretKey;
+        this.scope = scope;
+    }
+
+
+    /**
+     * 获取token,refresh 方法后调用有效
+     *
+     * @return
+     */
+    public String getToken() {
+        return token;
+    }
+
+    /**
+     * 获取过期时间,refresh 方法后调用有效
+     *
+     * @return
+     */
+    public long getExpiresAt() {
+        return expiresAt;
+    }
+
+
+
+
+    /**
+     * 获取token
+     *
+     * @return
+     * @throws IOException   http请求错误
+     * @throws DemoException http接口返回不是 200, access_token未获取
+     */
+    public void resfresh() throws IOException, DemoException {
+        String getTokenURL = url + "?grant_type=client_credentials"
+                + "&client_id=" + ConnUtil.urlEncode(apiKey) + "&client_secret=" + ConnUtil.urlEncode(secretKey);
+
+        // 打印的url出来放到浏览器内可以复现
+        System.out.println("token url:" + getTokenURL);
+
+        URL url = new URL(getTokenURL);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setConnectTimeout(5000);
+        String result = ConnUtil.getResponseString(conn);
+        System.out.println("Token result json:" + result);
+        parseJson(result);
+    }
+
+    /**
+     * @param result token接口获得的result
+     * @throws DemoException
+     */
+    private void parseJson(String result) throws DemoException {
+        JSONObject json = new JSONObject(result);
+        if (!json.has("access_token")) {
+            // 返回没有access_token字段
+            throw new DemoException("access_token not obtained, " + result);
+        }
+        if (!json.has("scope")) {
+            // 返回没有scope字段
+            throw new DemoException("scopenot obtained, " + result);
+        }
+        // scope = null, 忽略scope检查
+
+        if (scope != null && !json.getString("scope").contains(scope)) {
+            throw new DemoException("scope not exist, " + scope + "," + result);
+        }
+        token = json.getString("access_token");
+        expiresAt = System.currentTimeMillis() + json.getLong("expires_in") * 1000;
+    }
+}

+ 1 - 0
hcp-app/src/main/resources/application.yml

@@ -42,3 +42,4 @@ security:
       - /app/reset/password
       - /app/sysOrg/getHospitalList
       - /app/humanFace/login
+      - /app/video/vs

+ 26 - 0
hcp-core/src/main/java/com/yingyangfly/core/mapper/GameTaskMapper.java

@@ -1,10 +1,36 @@
 package com.yingyangfly.core.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.yingyangfly.core.domain.GameTask;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
 
 @Mapper
 public interface GameTaskMapper  extends BaseMapper<GameTask>{
 
+
+    @Select("<script>" +
+            "SELECT " +
+            "  gt.*, " +
+            "  GROUP_CONCAT(DISTINCT gtd.game_name) as gameNames " +
+            "FROM game_task gt " +
+            "LEFT JOIN game_task_detail gtd ON gt.id = gtd.task_id " +
+            "<where>" +
+            "  gt.user_id = #{userId} " +
+            "  <if test='treatmentId != null'>" +
+            "    AND gt.treatment_id = #{treatmentId} " +
+            "  </if>" +
+            "</where>" +
+            "GROUP BY gt.id " +
+            "ORDER BY gt.task_start_time DESC" +
+            "</script>")
+    List<GameTask> selectTaskWithGameNames(@Param("userId") Long userId,
+                                           @Param("treatmentId") Long treatmentId);
+
 }

+ 5 - 17
hcp-core/src/main/java/com/yingyangfly/core/service/impl/GameTaskServiceImpl.java

@@ -128,25 +128,13 @@ public class GameTaskServiceImpl extends ServiceImpl<GameTaskMapper, GameTask> i
 
     @Override
     public List<GameTask> findMyTask(Long treatmentId) {
+        // 获取当前登录用户
         AppCurrentLoginUser appCurrentLoginUser = tokenUtil.getAppCurrentLoginUser();
 
-        QueryWrapper<GameTask> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq("user_id", appCurrentLoginUser.getId());
-        if (treatmentId != null) {
-            queryWrapper.eq("treatment_id", treatmentId);
-        }
-        queryWrapper.orderByDesc("task_start_time");
-        List<GameTask> gameTasks = gameTaskMapper.selectList(queryWrapper);
-        for (GameTask gameTask:gameTasks) {
-            Long taskId= gameTask.getId();
-            //查询任务详情
-            QueryWrapper<GameTaskDetail> queryWrapperDetail = new QueryWrapper<>();
-            queryWrapperDetail.eq("task_id", taskId);
-            List<GameTaskDetail> gameTaskDetailList = gameTaskDetailMapper.selectList(queryWrapperDetail);
-            Set<String> names = gameTaskDetailList.stream().map(e -> e.getGameName()).collect(Collectors.toSet());
-            gameTask.setGameNames(StringUtils.join(names,","));
-        }
-        return gameTasks;
+        // 执行查询
+        List<GameTask> dtoResult = gameTaskMapper.selectTaskWithGameNames(appCurrentLoginUser.getId(), treatmentId);
+
+        return dtoResult;
     }
 
     @Override

+ 3 - 1
hcp-core/src/main/java/com/yingyangfly/core/service/impl/SysUserService.java

@@ -172,7 +172,9 @@ public class SysUserService extends  ServiceImpl<SysUserMapper,SysUser> {
         Set<String> roleNameSet = sysRoles.stream().map(sysRole -> sysRole.getRoleName()).collect(Collectors.toSet());
         currentLoginUser.setRoleCodes(roleSet);
         currentLoginUser.setRoleNames(roleNameSet);
-        currentLoginUser.setEmail(Sm4Util.decrypt(user.getEmail()));
+        if (ObjectUtils.isNotNull(user.getEmail())) {
+            currentLoginUser.setEmail(Sm4Util.decrypt(user.getEmail()));
+        }
         currentLoginUser.setMobile(Sm4Util.decrypt(user.getMobile()));
         currentLoginUser.setPhone(currentLoginUser.getMobile());
         currentLoginUser.setSex(user.getSex());

+ 17 - 0
hcp-core/src/main/java/com/yingyangfly/core/vo/AsrVo.java

@@ -0,0 +1,17 @@
+package com.yingyangfly.core.vo;
+
+import lombok.Data;
+
+@Data
+public class AsrVo {
+
+    private short[] content;
+
+    public short[] getContent() {
+        return content;
+    }
+
+    public void setContent(short[] content) {
+        this.content = content;
+    }
+}