SpringBoot集成免費(fèi)的EdgeTTS實(shí)現(xiàn)文本轉(zhuǎn)語(yǔ)音
引言
在需要文本轉(zhuǎn)語(yǔ)音(TTS)的應(yīng)用場(chǎng)景中(如語(yǔ)音助手、語(yǔ)音通知、內(nèi)容播報(bào)等),Java生態(tài)缺少類似Python生態(tài)的Edge TTS 客戶端庫(kù)。不過(guò)沒關(guān)系,現(xiàn)在可以通過(guò) UnifiedTTS 提供的 API 來(lái)調(diào)用免費(fèi)的 EdgeTTS 能力。同時(shí),UnifiedTTS 還支持 Azure TTS、MiniMax TTS、Elevenlabs TTS 等多種模型,通過(guò)對(duì)請(qǐng)求接口的抽象封裝,用戶可以方便在不同模型與音色之間靈活切換。
下面我們以調(diào)用免費(fèi)的EdgeTTS為目標(biāo),構(gòu)建一個(gè)包含文本轉(zhuǎn)語(yǔ)音功能的Spring Boot應(yīng)用。
實(shí)戰(zhàn)
1. 構(gòu)建 Spring Boot 應(yīng)用
通過(guò) start.spring.io 或其他構(gòu)建基礎(chǔ)的Spring Boot工程,根據(jù)你構(gòu)建應(yīng)用的需要增加一些依賴,比如最后用接口提供服務(wù)的話,可以加入web模塊:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. 注冊(cè) UnifiedTTS,獲取 API Key
- 前往 UnifiedTTS 官網(wǎng)注冊(cè)賬號(hào)(直接GitHub登錄即可)
- 從左側(cè)菜單進(jìn)入“API密鑰”頁(yè)面,創(chuàng)建 API Key;

- 存好API Key,后續(xù)需要使用
3. 集成 UnifiedTTS API
下面根據(jù)API 文檔:https://unifiedtts.com/zh/api-docs/tts-sync 實(shí)現(xiàn)一個(gè)可運(yùn)行的參考實(shí)現(xiàn),包括配置文件、請(qǐng)求模型、服務(wù)類與控制器。
3.1 配置文件(application.properties)
unified-tts.host=https://unifiedtts.com unified-tts.api-key=your-api-key-here
這里unifiedtts.api-key參數(shù)記得替換成之前創(chuàng)建的ApiKey。
3.2 配置加載類
@Data
@ConfigurationProperties(prefix = "unified-tts")
public class UnifiedTtsProperties {
private String host;
private String apiKey;
}
3.3 請(qǐng)求封裝和響應(yīng)封裝
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UnifiedTtsRequest {
private String model;
private String voice;
private String text;
private Double speed;
private Double pitch;
private Double volume;
private String format;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UnifiedTtsResponse {
private boolean success;
private String message;
private long timestamp;
private UnifiedTtsResponseData data;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class UnifiedTtsResponseData {
@JsonProperty("request_id")
private String requestId;
@JsonProperty("audio_url")
private String audioUrl;
@JsonProperty("file_size")
private long fileSize;
}
}
UnifiedTTS 抽象了不同模型的請(qǐng)求,這樣用戶可以用同一套請(qǐng)求參數(shù)標(biāo)準(zhǔn)來(lái)實(shí)現(xiàn)對(duì)不同TTS模型的調(diào)用,這個(gè)非常方便。所以,為了簡(jiǎn)化TTS的客戶端調(diào)用,非常推薦使用 UnifiedTTS。
3.3 服務(wù)實(shí)現(xiàn)(調(diào)用 UnifiedTTS)
使用 Spring Boot自帶的RestClient HTTP客戶端來(lái)實(shí)現(xiàn)UnifiedTTS的功能實(shí)現(xiàn)類,提供兩個(gè)實(shí)現(xiàn):
- 接收音頻字節(jié)并返回。
@Service
public class UnifiedTtsService {
private final RestClient restClient;
private final UnifiedTtsProperties properties;
public UnifiedTtsService(RestClient restClient, UnifiedTtsProperties properties) {
this.restClient = restClient;
this.properties = properties;
}
/**
* 調(diào)用 UnifiedTTS 同步 TTS 接口,返回音頻字節(jié)數(shù)據(jù)。
*
* <p>請(qǐng)求頭:
* <ul>
* <li>Content-Type: application/json</li>
* <li>X-API-Key: 來(lái)自配置的 API Key</li>
* <li>Accept: 接受二進(jìn)制流或常見 mp3/mpeg 音頻類型</li>
* </ul>
*
* @param request 模型、音色、文本、速度/音調(diào)/音量、輸出格式等參數(shù)
* @return 音頻二進(jìn)制字節(jié)(例如 mp3)
* @throws IllegalStateException 當(dāng)服務(wù)端返回非 2xx 或無(wú)內(nèi)容時(shí)拋出
*/
public byte[] synthesize(UnifiedTtsRequest request) {
ResponseEntity<byte[]> response = restClient
.post()
.uri("/api/v1/common/tts-sync")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_OCTET_STREAM, MediaType.valueOf("audio/mpeg"), MediaType.valueOf("audio/mp3"))
.header("X-API-Key", properties.getApiKey())
.body(request)
.retrieve()
.toEntity(byte[].class);
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return response.getBody();
}
throw new IllegalStateException("UnifiedTTS synthesize failed: " + response.getStatusCode());
}
/**
* 調(diào)用合成并將音頻寫入指定文件。
*
* <p>若輸出路徑的父目錄不存在,會(huì)自動(dòng)創(chuàng)建;失敗時(shí)拋出運(yùn)行時(shí)異常。
*
* @param request TTS 請(qǐng)求參數(shù)
* @param outputPath 目標(biāo)文件路徑(例如 output.mp3)
* @return 實(shí)際寫入的文件路徑
*/
public Path synthesizeToFile(UnifiedTtsRequest request, Path outputPath) {
byte[] data = synthesize(request);
try {
if (outputPath.getParent() != null) {
Files.createDirectories(outputPath.getParent());
}
Files.write(outputPath, data);
return outputPath;
} catch (IOException e) {
throw new RuntimeException("Failed to write TTS output to file: " + outputPath, e);
}
}
}
3.4 單元測(cè)試
@SpringBootTest
class UnifiedTtsServiceTest {
@Autowired
private UnifiedTtsService unifiedTtsService;
@Test
void testRealSynthesizeAndDownloadToFile() throws Exception {
UnifiedTtsRequest req = new UnifiedTtsRequest(
"edge-tts",
"en-US-JennyNeural",
"Hello, this is a test of text to speech synthesis.",
1.0,
1.0,
1.0,
"mp3"
);
// 調(diào)用真實(shí)接口,斷言返回結(jié)構(gòu)
UnifiedTtsResponse resp = unifiedTtsService.synthesize(req);
assertNotNull(resp);
assertTrue(resp.isSuccess(), "Response should be success");
assertNotNull(resp.getData(), "Response data should not be null");
assertNotNull(resp.getData().getAudioUrl(), "audio_url should be present");
// 在當(dāng)前工程目錄下生成測(cè)試結(jié)果目錄并寫入文件
Path projectDir = Paths.get(System.getProperty("user.dir"));
Path resultDir = projectDir.resolve("test-result");
Files.createDirectories(resultDir);
Path out = resultDir.resolve(System.currentTimeMillis() + ".mp3");
Path written = unifiedTtsService.synthesizeToFile(req, out);
System.out.println("UnifiedTTS test output: " + written.toAbsolutePath());
assertTrue(Files.exists(written), "Output file should exist");
assertTrue(Files.size(written) > 0, "Output file size should be > 0");
}
}
4. 運(yùn)行與驗(yàn)證
執(zhí)行單元測(cè)試之后,可以在工程目錄test-result下找到生成的音頻文件:

5. 常用參數(shù)與音色選擇
目前支持的常用參數(shù)如下圖所示:

小結(jié)
本文展示了如何在 Spring Boot 中集成 UnifiedTTS 的 EdgeTTS 能力,實(shí)現(xiàn)文本轉(zhuǎn)語(yǔ)音并輸出為 mp3。UnifiedTTS 通過(guò)統(tǒng)一的 API 屏蔽了不同 TTS 模型的差異,使你無(wú)需維護(hù)多個(gè) SDK,即可在成本與效果之間自由切換。根據(jù)業(yè)務(wù)需求,你可以進(jìn)一步完善異常處理、緩存與并發(fā)控制,實(shí)現(xiàn)更可靠的生產(chǎn)級(jí) TTS 服務(wù)。
以上就是SpringBoot集成免費(fèi)的EdgeTTS實(shí)現(xiàn)文本轉(zhuǎn)語(yǔ)音的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot EdgeTTS文本轉(zhuǎn)語(yǔ)音的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java的MybatisPlus調(diào)用儲(chǔ)存過(guò)程的返回?cái)?shù)據(jù)問(wèn)題
這篇文章主要介紹了java的MybatisPlus調(diào)用儲(chǔ)存過(guò)程的返回?cái)?shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
SpringBoot復(fù)雜參數(shù)應(yīng)用詳細(xì)講解
我們?cè)诰帉懡涌跁r(shí)會(huì)傳入復(fù)雜參數(shù),如Map、Model等,這種類似的參數(shù)會(huì)有相應(yīng)的參數(shù)解析器進(jìn)行解析,并且最后會(huì)將解析出的值放到request域中,下面我們一起來(lái)探析一下其中的原理2022-09-09
HandlerMapping之RequestMappingHandlerMapping作用詳解
這篇文章主要介紹了HandlerMapping之RequestMappingHandlerMapping作用詳解,HandlerMapping是用來(lái)尋找Handler的,并不與Handler的類型或者實(shí)現(xiàn)綁定,而是根據(jù)需要定義的,那么為什么要單獨(dú)給@RequestMapping實(shí)現(xiàn)一個(gè)HandlerMapping,需要的朋友可以參考下2023-10-10
Java中定時(shí)任務(wù)的6種實(shí)現(xiàn)方式
這篇文章主要給大家分享的是Java中定時(shí)任務(wù)的6種實(shí)現(xiàn)方式,幾乎在所有的項(xiàng)目中,定時(shí)任務(wù)的使用都是不可或缺的,如果使用不當(dāng)甚至?xí)斐少Y損,下面文章我們就來(lái)看看Java中定時(shí)任務(wù)的具體使用方式吧2021-10-10
Mybatis注解開發(fā)單表、多表操作的實(shí)現(xiàn)代碼
這篇文章主要介紹了Mybatis高級(jí):Mybatis注解開發(fā)單表操作,Mybatis注解開發(fā)多表操作,構(gòu)建sql語(yǔ)句,綜合案例學(xué)生管理系統(tǒng)使用接口注解方式優(yōu)化,需要的朋友可以參考下2021-02-02
SpringBoot集成Redis使用Cache緩存的實(shí)現(xiàn)方法
SpringBoot通過(guò)配置RedisConfig類和使用Cache注解可以輕松集成Redis實(shí)現(xiàn)緩存,主要包括@EnableCaching開啟緩存,自定義key生成器,改變序列化規(guī)則,以及配置RedisCacheManager,本文為使用SpringBoot與Redis處理緩存提供了詳實(shí)的指導(dǎo)和示例,感興趣的朋友一起看看吧2024-10-10
Spring?Cloud?Loadbalancer服務(wù)均衡負(fù)載器詳解
這篇文章主要介紹了Spring?Cloud?Loadbalancer服務(wù)均衡負(fù)載器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03

