|
@@ -0,0 +1,174 @@
|
|
|
+package com.magicapi.util;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.util.Base64;
|
|
|
+import java.util.concurrent.CountDownLatch;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import org.opencv.core.Core;
|
|
|
+import org.opencv.core.Mat;
|
|
|
+import org.opencv.core.Point;
|
|
|
+import org.opencv.core.Scalar;
|
|
|
+import org.opencv.imgcodecs.Imgcodecs;
|
|
|
+import org.opencv.imgproc.Imgproc;
|
|
|
+
|
|
|
+import com.magicapi.voice.WebsocketLister;
|
|
|
+
|
|
|
+import cn.hutool.core.lang.UUID;
|
|
|
+import cn.hutool.core.util.RandomUtil;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import okhttp3.OkHttpClient;
|
|
|
+import okhttp3.Request;
|
|
|
+
|
|
|
+public class YzsUtil {
|
|
|
+
|
|
|
+ private static final String FILE_PATH = "D:/cgj/xfyunAudio/";
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+// System.err.println(Base64.getDecoder().decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"));
|
|
|
+ String path = tts("我国从北到南将呈现出“雨晴雨夹心状”的天气格局。");
|
|
|
+// new SimplyPlayer(path).play();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String tts(String txt) {
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+ // 获取appkey
|
|
|
+ String result = HttpUtil.get("https://ai.unisound.com/manager/captcha/get_service_link?aiCode=tts-short");
|
|
|
+ System.err.println(result);
|
|
|
+ JSONObject appObj = JSONUtil.parseObj(result).getJSONObject("result");
|
|
|
+ String appkey = appObj.getStr("appkey");
|
|
|
+ // 请求验证
|
|
|
+ result = HttpUtil.get("https://ai.unisound.com/manager/captcha/register");
|
|
|
+ System.err.println(result);
|
|
|
+ JSONObject obj = JSONUtil.parseObj(result).getJSONObject("result");
|
|
|
+ // 获取x
|
|
|
+ int x = checkImg(obj.getStr("bgImg"), obj.getStr("sliceImg")) + RandomUtil.randomInt(-1, 1);
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
+ params.set("aiCode", "");
|
|
|
+ params.set("sliceX", x);
|
|
|
+ params.set("token", obj.get("token"));
|
|
|
+ result = HttpRequest.post("https://ai.unisound.com/manager/captcha/check").header("content-type", "application/json;charset=UTF-8")
|
|
|
+ .body(params.toJSONString(0)).execute().body();
|
|
|
+ System.err.println(result);
|
|
|
+ if (JSONUtil.parseObj(result).getInt("errorCode") == 0) {
|
|
|
+ params = new JSONObject();
|
|
|
+ params.set("aiCode", "tts-short");
|
|
|
+ params.set("appKey", appkey);
|
|
|
+ params.set("sha", "sha256");
|
|
|
+ long time = System.currentTimeMillis();
|
|
|
+ params.set("time", time);
|
|
|
+ JSONObject captcha = new JSONObject();
|
|
|
+ captcha.set("sliceX", x);
|
|
|
+ captcha.set("token", obj.get("token"));
|
|
|
+ params.set("captcha", captcha);
|
|
|
+ result = HttpRequest.post("https://ai.unisound.com/manager/captcha/auth").header("content-type", "application/json;charset=UTF-8")
|
|
|
+ .body(params.toJSONString(0)).execute().body();
|
|
|
+ System.err.println(result);
|
|
|
+ // 创建websocket
|
|
|
+ String path = FILE_PATH + "yzs/" + UUID.randomUUID() + ".wav";
|
|
|
+ CountDownLatch handshakeSuccess = new CountDownLatch(1);
|
|
|
+ OkHttpClient client = new OkHttpClient.Builder().connectTimeout(2000, TimeUnit.MILLISECONDS).build();
|
|
|
+ Request request = new Request.Builder().url(appObj.getStr("cn.url") + "?appkey="+ appkey +"&time="
|
|
|
+ + time +"&sign=" + JSONUtil.parseObj(result).getJSONObject("result").getStr("sign")).build();
|
|
|
+ client.newWebSocket(request, new WebsocketLister(txt, path, handshakeSuccess));
|
|
|
+ client.dispatcher().executorService().shutdown();
|
|
|
+ try {
|
|
|
+ handshakeSuccess.await();
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ System.err.println("耗时:" + (System.currentTimeMillis() - start));
|
|
|
+ return path;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理图片获取x值
|
|
|
+ * @param bg
|
|
|
+ * @param slice
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static int checkImg(String bg, String slice) {
|
|
|
+ String bgPath = saveImage(bg);
|
|
|
+ String slicePath = saveImage(slice);
|
|
|
+ int x = getSlideDistance(slicePath, bgPath);
|
|
|
+ new File(bgPath).delete();
|
|
|
+ new File(slicePath).delete();
|
|
|
+ return x;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存图片
|
|
|
+ * @param base64Img
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static String saveImage(String base64Img) {
|
|
|
+ byte[] b = Base64.getDecoder().decode(base64Img);
|
|
|
+ String imgPath = FILE_PATH + UUID.randomUUID() + ".jpg";
|
|
|
+ try {
|
|
|
+ OutputStream out = new FileOutputStream(imgPath);
|
|
|
+ out.write(b);
|
|
|
+ out.flush();
|
|
|
+ out.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return imgPath;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取x值
|
|
|
+ * @param slideBlockPicPath
|
|
|
+ * @param slideBgPicPath
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private static int getSlideDistance(String slideBlockPicPath, String slideBgPicPath) {
|
|
|
+ System.load(FILE_PATH + "opencv_java340-x64.dll");
|
|
|
+ //对滑块进行处理
|
|
|
+ Mat slideBlockMat = Imgcodecs.imread(slideBlockPicPath);
|
|
|
+ //1、灰度化图片
|
|
|
+ Imgproc.cvtColor(slideBlockMat, slideBlockMat, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ //2、去除周围黑边
|
|
|
+ for (int row = 0; row < slideBlockMat.height(); row++) {
|
|
|
+ for (int col = 0; col < slideBlockMat.width(); col++) {
|
|
|
+ if (slideBlockMat.get(row, col)[0] == 0) {
|
|
|
+ slideBlockMat.put(row, col, 96);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //3、inRange二值化转黑白图
|
|
|
+ Core.inRange(slideBlockMat, Scalar.all(96), Scalar.all(96), slideBlockMat);
|
|
|
+
|
|
|
+
|
|
|
+ //对滑动背景图进行处理
|
|
|
+ Mat slideBgMat = Imgcodecs.imread(slideBgPicPath);
|
|
|
+ //1、灰度化图片
|
|
|
+ Imgproc.cvtColor(slideBgMat, slideBgMat, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ //2、二值化
|
|
|
+ Imgproc.threshold(slideBgMat, slideBgMat, 127, 255, Imgproc.THRESH_BINARY);
|
|
|
+ Mat g_result = new Mat();
|
|
|
+ /*
|
|
|
+ * matchTemplate:在模板和输入图像之间寻找匹配,获得匹配结果图像
|
|
|
+ * result:保存匹配的结果矩阵
|
|
|
+ * TM_CCOEFF_NORMED标准相关匹配算法
|
|
|
+ */
|
|
|
+ Imgproc.matchTemplate(slideBgMat, slideBlockMat, g_result, Imgproc.TM_CCOEFF_NORMED);
|
|
|
+ /* minMaxLoc:在给定的结果矩阵中寻找最大和最小值,并给出它们的位置
|
|
|
+ * maxLoc最大值
|
|
|
+ */
|
|
|
+ Point matchLocation = Core.minMaxLoc(g_result).maxLoc;
|
|
|
+ //返回匹配点的横向距离
|
|
|
+ return (int) matchLocation.x;
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|