package com.fuyuanshen.app.http; import com.alibaba.nls.client.AccessToken; import com.fuyuanshen.common.redis.utils.RedisUtils; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.time.Duration; import java.util.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import static cn.dev33.satoken.SaManager.log; public class HttpTtsClient { private String accessKeyId; private String accessKeySecret; private String appKey; /** * 阿里云TTS服务基础URL */ private static final String BASE_URL = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts"; public HttpTtsClient(String accessKeyId, String accessKeySecret, String appKey) { this.accessKeyId = accessKeyId; this.accessKeySecret = accessKeySecret; this.appKey = appKey; } private String refreshAccessToken() { try { // 调用阿里云API获取访问令牌 AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret); accessToken.apply(); String token = accessToken.getToken(); log.info("访问令牌刷新成功"); return token; } catch (Exception e) { log.error("刷新访问令牌失败: {}", e.getMessage(), e); return null; } } /** * 使用HTTP POST方式调用阿里云TTS服务生成MP3格式语音 */ public byte[] synthesizeTextToMp3(String text) throws IOException { String endpoint = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts"; // 构建请求体 // String requestBody = String.format( // "{\"appkey\":\"%s\",\"text\":\"%s\",\"voice\":\"zhifeng\",\"format\":\"MP3\",\"sample_rate\":24000,\"volume\":50,\"speech_rate\":0,\"pitch_rate\":0}", // appKey, // text.replace("\"", "\\\"") // ); String token = refreshAccessToken(); String requestBody = " {\n" + " \"appkey\":\""+appKey+"\",\n" + " \"text\":\""+text+"\",\n" + " \"token\":\""+token+"\",\n" + " \"format\":\"mp3\"\n" + " }"; URL url = new URL(endpoint); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求方法和头部 conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Authorization", buildAuthorization()); conn.setRequestProperty("Content-Length", String.valueOf(requestBody.getBytes().length)); conn.setDoOutput(true); // 发送请求体 try (OutputStream os = conn.getOutputStream()) { os.write(requestBody.getBytes("UTF-8")); } // 读取响应 int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取音频数据 try (InputStream is = conn.getInputStream()) { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } return buffer.toByteArray(); } } else { throw new IOException("HTTP请求失败,状态码: " + responseCode); } } /** * 构建授权头部 */ private String buildAuthorization() { // 实际实现需要根据阿里云API规范构建签名 // 这里是简化示例 return "Bearer " + generateAccessToken(); } /** * 生成访问令牌 */ private String generateAccessToken() { // 实际实现需要调用阿里云获取token的API return "your-access-token"; } /** * 保存MP3到文件 */ public String saveMp3ToFile(String text, String outputPath) throws IOException { byte[] mp3Data = synthesizeTextToMp3(text); try (FileOutputStream fos = new FileOutputStream(outputPath)) { fos.write(mp3Data); } return outputPath; } }