1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
| package com.listen.utils;
import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import okhttp3.HttpUrl; import org.java_websocket.WebSocket; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake;
import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.*; import java.net.URI; import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*;
public class TtsUtil { public static final String hostUrl = "https://tts-api.xfyun.cn/v2/tts"; public static final String appid = "自行申请"; public static final String apiSecret = "自行申请"; public static final String apiKey = "自行申请"; public static final String TEXT = "服务端可能返回data为空的帧,并且错误码为0,这种帧客户端可以直接忽略,不解析"; public static final String TTE = "UTF8"; public static final String VCN = "xiaoyan"; public static final String OUTPUT_FILE_PATH = "src/main/resources/tts/" + System.currentTimeMillis() + ".mp3"; public static final Gson gson = new Gson(); public static boolean wsCloseFlag = false; private static final String AUE = "lame"; private static final int SPEED = 50; private static final int VOLUME = 50; private static final int PITCH = 50;
public static void main(String[] args) throws Exception { String wsUrl = getAuthUrl(hostUrl, apiKey, apiSecret).replace("https://", "wss://"); OutputStream outputStream = new FileOutputStream(OUTPUT_FILE_PATH); websocketWork(wsUrl, outputStream); }
public static void websocketWork(String wsUrl, OutputStream outputStream) { try { URI uri = new URI(wsUrl); WebSocketClient webSocketClient = new WebSocketClient(uri) { @Override public void onOpen(ServerHandshake serverHandshake) { System.out.println("ws建立连接成功..."); }
@Override public void onMessage(String text) { JsonParse myJsonParse = gson.fromJson(text, JsonParse.class); if (myJsonParse.code != 0) { System.out.println("发生错误,错误码为:" + myJsonParse.code); System.out.println("本次请求的sid为:" + myJsonParse.sid); } if (myJsonParse.data != null) { try { byte[] textBase64Decode = Base64.getDecoder().decode(myJsonParse.data.audio); outputStream.write(textBase64Decode); outputStream.flush(); } catch (Exception e) { e.printStackTrace(); } if (myJsonParse.data.status == 2) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("本次请求的sid==>" + myJsonParse.sid); System.out.println("合成成功,文件保存路径为==>" + OUTPUT_FILE_PATH); wsCloseFlag = true; } } }
@Override public void onClose(int i, String s, boolean b) { System.out.println("ws链接已关闭,本次请求完成..."); }
@Override public void onError(Exception e) { System.out.println("发生错误 " + e.getMessage()); } }; webSocketClient.connect(); while (!webSocketClient.getReadyState().equals(WebSocket.READYSTATE.OPEN)) { Thread.sleep(100); } MyThread webSocketThread = new MyThread(webSocketClient); webSocketThread.start(); } catch (Exception e) { System.out.println(e.getMessage()); } }
static class MyThread extends Thread { WebSocketClient webSocketClient;
public MyThread(WebSocketClient webSocketClient) { this.webSocketClient = webSocketClient; }
public void run() { try { JSONObject commonJson = new JSONObject(); commonJson.put("app_id", appid); JSONObject businessJson = new JSONObject(); businessJson.put("aue", AUE); businessJson.put("sfl", 1); businessJson.put("tte", TTE); businessJson.put("ent", "intp65"); businessJson.put("vcn", VCN); businessJson.put("pitch", PITCH); businessJson.put("speed", SPEED);
JSONObject dataJson = new JSONObject(); dataJson.put("status", 2); dataJson.put("text", Base64.getEncoder().encodeToString(TEXT.getBytes(StandardCharsets.UTF_8)));
JSONObject requestJson = new JSONObject(); requestJson.put("common", commonJson); requestJson.put("business", businessJson); requestJson.put("data", dataJson); webSocketClient.send(requestJson.toString()); while (!wsCloseFlag) { Thread.sleep(200); } webSocketClient.close(); } catch (Exception e) { e.printStackTrace(); } } }
public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception { URL url = new URL(hostUrl); SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); String date = format.format(new Date()); String preStr = "host: " + url.getHost() + "\n" + "date: " + date + "\n" + "GET " + url.getPath() + " HTTP/1.1"; Mac mac = Mac.getInstance("hmacsha256"); SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256"); mac.init(spec); byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8)); String sha = Base64.getEncoder().encodeToString(hexDigits); String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha); HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder(). addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))). addQueryParameter("date", date). addQueryParameter("host", url.getHost()). build();
return httpUrl.toString(); }
class JsonParse { int code; String sid; Data data; }
class Data { int status; String audio; } }
|