音频模型
约 3073 字大约 10 分钟
2026-09-15
合集说明
本篇合并自参考文档「Models / Audio Models」章节,覆盖文本转语音(TTS)与语音转录(Transcription)两大 API 及各厂商实现,按官方文档顺序排列:(各篇之间以 --- 分隔)
- Audio Models(音频模型)
- Text-to-Speech API(文本转语音 API)
- OpenAI TTS(OpenAI 文字转语音)
- ElevenLabs TTS(ElevenLabs 文字转语音)
- Transcription API(转录 API)
- OpenAI Transcription(OpenAI 语音转文字)
- Azure OpenAI Transcription(Azure OpenAI 语音转文字)
Audio Models(音频模型)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio.html 📌 原文版本:Java AI 2.0.1
Java AI 用统一的接口把"音频相关的 AI 能力"封装成了两个方向:
- 文字转语音(Text-to-Speech,TTS):把一段文本丢给模型,模型吐回一段音频(mp3、opus、pcm 等)。
- 语音转文字(Speech-to-Text,STT,又叫转录 / Transcriptions):把一段音频丢给模型,模型吐回识别出的文字。
白话解读
简单说就是"说"和"听"两件事。Spring 把这两件事的接口都做了厂商无关的封装,你换厂商只需要换 starter,业务代码不用动。
下面这一章会分两块讲:
- Text-to-Speech(文字转语音) —— 见
Text-To-Speech-API(文本转语音API).md - Transcriptions(语音转录) —— 见
Transcription-API(转录API).md
每个具体厂商的实现(OpenAI、ElevenLabs、Azure OpenAI 等)会作为独立小节展开。
Text-to-Speech API(文本转语音 API)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/speech.html 📌 原文版本:Java AI 2.0.1
Java AI 把"文字转语音"封装成两个核心接口:
TextToSpeechModel:同步版,一次性返回完整音频。StreamingTextToSpeechModel:流式版,一边生成一边吐数据。
白话解读
TTS 模型通常要等几十毫秒到几秒才能把整段音频吐完。如果你要做实时语音播报,用流式接口能省一大截延迟。
1. TextToSpeechPrompt(请求)
请求里塞的是一段文本,外加一些可选项(声音、语速、格式等):
TextToSpeechPrompt prompt = new TextToSpeechPrompt("你好,世界!");也可以带选项:
TextToSpeechPrompt promptWithOptions = new TextToSpeechPrompt(
"你好,世界!",
OpenAiAudioSpeechOptions.builder()
.withModel("gpt-4o-mini-tts")
.withVoice(OpenAiAudioSpeechOptions.Voice.ALLOY)
.withResponseFormat(OpenAiAudioSpeechOptions.AudioResponseFormat.MP3)
.withSpeed(1.0f)
.build()
);2. TextToSpeechResponse(响应)
call(...) 拿到的是 TextToSpeechResponse,里面核心字段就是音频字节流:
TextToSpeechResponse response = speechModel.call(prompt);
byte[] audioBytes = response.getResult().getOutput();getResult().getOutput() 返回的是 byte[],可以直接写文件、推给前端播放、或者塞进 ResponseEntity<byte[]> 当下载用。
3. 流式接口(StreamingTextToSpeechModel)
Flux<TextToSpeechResponse> stream = streamingSpeechModel.stream(prompt);关于背压(backpressure)
流式拿到的是 Flux<TextToSpeechResponse>。如果直接 collect 成大 byte[] 再写文件,就退化成"先全下完再播",流式接口的意义就没了。生产环境通常会做背压控制(比如 onBackpressureBuffer + 上限),避免内存爆掉。
4. 多提供商选择
TextToSpeechModel 接口在 classpath 上有多个实现时,Spring Boot 自动配置会按 starter 优先级选一个。你也可以显式注入某个 bean:
@Autowired
@Qualifier("openAiAudioSpeechModel")
private TextToSpeechModel speechModel;或者用 ChatClient 风格的 builder:
TextToSpeechModel model = TextToSpeechModelFactory.create(...);注意版本
SpeechModel 是 1.x 时代的旧接口名,2.0 已统一为 TextToSpeechModel。如果是从老版本迁过来,需要替换 import 和类名。
5. 下一步
- 具体厂商实现见
OpenAI-TTS.md、ElevenLabs-TTS.md。
OpenAI TTS(OpenAI 文字转语音)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/speech/openai-speech.html 📌 原文版本:Java AI 2.0.1
OpenAI 提供了多种 TTS 模型。Java AI 通过 starter spring-ai-starter-model-openai 自动装配一个 TextToSpeechModel bean(名字是 openAiAudioSpeechModel)。
白话解读
这个 starter 其实和 OpenAI Chat 共享一套连接配置(API key、base-url 等),所以你引一个 starter 就能聊又能听。
1. 准备工作
- 在 OpenAI 申请 API key。
- 设置环境变量(或 application.yml):
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
audio:
speech:
options:
model: gpt-4o-mini-tts # 默认模型
voice: alloy # 默认声音
response-format: mp3 # 默认输出格式
speed: 1.0 # 语速,0.25 ~ 4.0- 引入依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>2. 基础用法
@RestController
class TtsController {
private final TextToSpeechModel speechModel;
TtsController(TextToSpeechModel speechModel) {
this.speechModel = speechModel;
}
@GetMapping(value = "/tts", produces = "audio/mpeg")
public byte[] tts(@RequestParam String text) {
TextToSpeechResponse resp = speechModel.call(new TextToSpeechPrompt(text));
return resp.getResult().getOutput(); // 直接返回 mp3 字节流
}
}3. 选项一览(OpenAiAudioSpeechOptions)
| 选项 | 类型 | 说明 |
|---|---|---|
model | String | 模型名。gpt-4o-mini-tts(默认,可调语气)、tts-1、tts-1-hd |
voice | enum | 声音:ALLOY、ECHO、FABLE、ONYX、NOVA、SHIMMER |
responseFormat | enum | 输出格式:MP3、OPUS、AAC、FLAC、WAV、PCM |
speed | float | 语速,0.25 ~ 4.0 |
gpt-4o-mini-tts 独有
gpt-4o-mini-tts 是新一代模型,支持"自然语言指令"调语气(比如 "用兴奋一点的语气说")。老模型 tts-1 / tts-1-hd 没有这能力。
4. 运行时动态切换
不写死在 yml 里,调用时塞进去:
TextToSpeechPrompt prompt = new TextToSpeechPrompt(
"今天天气真好。",
OpenAiAudioSpeechOptions.builder()
.withModel("tts-1-hd")
.withVoice(OpenAiAudioSpeechOptions.Voice.NOVA)
.withResponseFormat(OpenAiAudioSpeechOptions.AudioResponseFormat.OPUS)
.withSpeed(1.2f)
.build()
);
TextToSpeechResponse resp = speechModel.call(prompt);
Files.write(Path.of("out.opus"), resp.getResult().getOutput());5. 流式用法
Flux<TextToSpeechResponse> flux = speechModel.stream(prompt);适合边生成边播放的场景(比如 WebSocket 推流)。
6. 从老版本迁移(SpeechModel → TextToSpeechModel)
2.0 重命名
1.x 里这个接口叫 SpeechModel,方法名是 call(SpeechPrompt) 返回 SpeechResponse。2.0 统一改为 TextToSpeechModel / TextToSpeechPrompt / TextToSpeechResponse,命名上和 ChatModel 体系对齐。迁移成本就是改 import + 改三个类名。
ElevenLabs TTS(ElevenLabs 文字转语音)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/speech/elevenlabs-speech.html 📌 原文版本:Java AI 2.0.1
ElevenLabs 以"声音克隆"和"情感丰富"出名,适合做有声书、播客、虚拟主播。Java AI 通过 starter spring-ai-starter-model-elevenlabs 接入。
白话解读
ElevenLabs 的卖点不是参数多,而是声音质量本身——尤其在"自然停顿"、"情绪起伏"上比 OpenAI TTS 更像人。
1. 准备工作
- 在 ElevenLabs 申请 API key。
- 配置:
spring:
ai:
elevenlabs:
api-key: ${ELEVENLABS_API_KEY}
audio:
speech:
options:
model-id: eleven_turbo_v2_5 # 默认模型
voice-id: <你的 voice id>
output-format: mp3_44100_128 # 默认输出格式- 引入依赖:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-elevenlabs</artifactId>
</dependency>2. 基础用法
@RestController
class ElevenTtsController {
private final TextToSpeechModel speechModel;
ElevenTtsController(TextToSpeechModel speechModel) {
this.speechModel = speechModel;
}
@GetMapping(value = "/tts", produces = "audio/mpeg")
public byte[] tts(@RequestParam String text) {
return speechModel.call(new TextToSpeechPrompt(text))
.getResult()
.getOutput();
}
}3. 选项一览(ElevenLabsAudioSpeechOptions)
| 选项 | 类型 | 说明 |
|---|---|---|
modelId | String | 模型 ID,默认 eleven_turbo_v2_5 |
voiceId | String | 声音 ID(ElevenLabs 控制台创建/克隆后拿到) |
outputFormat | enum | 输出格式(见下表) |
voiceSettings | Object | 稳定性 / 相似度 / 风格 / 扬声器增益 |
输出格式枚举(节选)
| 格式 | 采样率 | 比特率 | 用途 |
|---|---|---|---|
mp3_22050_32 | 22050 | 32 | 低带宽 |
mp3_44100_64 | 44100 | 64 | 普通 |
mp3_44100_128 | 44100 | 128 | 高质量(默认) |
mp3_44100_192 | 44100 | 192 | 接近无损 |
pcm_16000 | 16000 | - | 实时流式 |
pcm_22050 | 22050 | - | 实时流式 |
pcm_44100 | 44100 | - | 高保真 |
opus_48000_64 | 48000 | 64 | Web 实时 |
opus_48000_128 | 48000 | 128 | Web 高质量 |
4. Voices API(查询可用声音)
ElevenLabs 还提供了一个独立的 ElevenLabsVoicesApi,可以列出账号下所有可用声音:
VoicesResponse voices = voicesApi.listVoices();
voices.voices().forEach(v ->
System.out.println(v.name() + " -> " + v.voiceId())
);voice vs voice_id
ElevenLabs 的"声音"是用 ID 标识的(不是名字)。克隆一个声音后,控制台会给你一个 voice_id,调用时填它就行。也可以通过 Voices API 程序化查询。
5. 流式用法
Flux<TextToSpeechResponse> flux = speechModel.stream(prompt);ElevenLabs 在 stream 模式下默认会切分成多段音频块,配合 opus 输出格式非常适合 Web 前端边下边播。
Transcription API(转录 API)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/transcriptions.html 📌 原文版本:Java AI 2.0.1
转录(Transcription)就是把"一段音频"丢给模型,模型吐回识别出的文字。Java AI 用 TranscriptionModel 接口封装这件事,对应厂商实现有 OpenAI Whisper、Azure OpenAI 等。
白话解读
和 TTS 是反过来的方向:TTS 是"文字→音频",转录是"音频→文字"。Spring 把请求/响应对象设计成对称的,习惯 TTS 接口的同学几乎零成本上手转录。
1. TranscriptionModel(同步)
public interface TranscriptionModel extends Model<AudioTranscriptionPrompt, AudioTranscriptionResponse> {
default AudioTranscriptionResponse call(AudioResource audioResource) { ... }
default AudioTranscriptionResponse call(AudioResource audioResource, AudioTranscriptionOptions options) { ... }
@Override
AudioTranscriptionResponse call(AudioTranscriptionPrompt prompt);
}注意 TranscriptionModel 是 Model<I, O> 的特化,方法签名跟 ChatModel / TextToSpeechModel 一致。
2. AudioTranscriptionPrompt(请求)
AudioTranscriptionPrompt 包装一个 AudioResource(音频资源,类比 Spring 的 Resource)和可选的 AudioTranscriptionOptions:
AudioResource audioResource = new ByteArrayAudioResource(mp3Bytes, "audio.mp3");
AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(audioResource);带选项:
AudioTranscriptionOptions options = OpenAiAudioTranscriptionOptions.builder()
.withModel(OpenAiAudioTranscriptionOptions.WhisperModel.WHISPER_1)
.withLanguage("zh") // 强制指定语言
.withResponseFormat(TranscriptResponseFormat.TEXT)
.withTemperature(0f)
.build();
AudioTranscriptionPrompt prompt = new AudioTranscriptionPrompt(audioResource, options);3. AudioTranscriptionResponse(响应)
AudioTranscriptionResponse resp = transcriptionModel.call(prompt);
String text = resp.getResult().getOutput(); // 识别出的文字getResult().getOutput() 返回字符串。OpenAI 还支持返回 JSON / SRT / VTT,这些格式在 OpenAI 转录章节细讲。
4. AudioResource(音频资源)
AudioResource 是音频版的 Resource,构造方式:
// 从字节数组
ByteArrayAudioResource res1 = new ByteArrayAudioResource(bytes, "clip.mp3");
// 从 classpath
AudioResource res2 = new ByteArrayAudioResource(
getClass().getResourceAsStream("/audio/hello.wav"), "hello.wav"
);
// 从 URL
AudioResource res3 = new UrlAudioResource(URI.create("https://example.com/x.m4a"));文件大小上限
大多数转录 API 都有单文件大小限制(OpenAI 是 25 MB)。超过的话需要先切片或者用更长的 API(部分厂商支持)。
5. 下一步
- 具体厂商实现见
OpenAI-Transcription.md、Azure-OpenAI-Transcription.md。
OpenAI Transcription(OpenAI 语音转文字)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/transcriptions/openai-transcriptions.html 📌 原文版本:Java AI 2.0.1
OpenAI 提供了多个转录模型,从最早的 whisper-1 到支持说话人分离的 gpt-4o-transcribe-diarize。Java AI 通过 spring-ai-starter-model-openai 装配 openAiAudioTranscriptionModel bean。
白话解读
OpenAI 这块的产品线分两代:Whisper 系(whisper-1)便宜稳定;GPT-4o 转录系新、贵一点但精度更高,还支持说话人分离。
1. 准备工作
- 申请 OpenAI API key。
- 配置:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
audio:
transcription:
options:
model: gpt-4o-transcribe # 默认模型
language: zh
response-format: json
temperature: 0- 引入依赖(同 TTS,OpenAI starter 一并搞定):
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>2. 基础用法
@RestController
class SttController {
private final TranscriptionModel transcriptionModel;
SttController(TranscriptionModel transcriptionModel) {
this.transcriptionModel = transcriptionModel;
}
@PostMapping(value = "/stt", consumes = MULTIPART_FORM_DATA_VALUE)
String stt(@RequestPart MultipartFile file) throws IOException {
AudioResource audio = new ByteArrayAudioResource(file.getBytes(), file.getOriginalFilename());
return transcriptionModel.call(new AudioTranscriptionPrompt(audio))
.getResult()
.getOutput();
}
}3. 模型一览
| 模型 | 特点 |
|---|---|
whisper-1 | 老牌 Whisper,价格便宜,支持多语言、翻译成英文 |
gpt-4o-transcribe | 新一代基于 GPT-4o 的转录,精度高,支持提示词调教 |
gpt-4o-mini-transcribe | 轻量版,速度更快 |
gpt-4o-transcribe-diarize | 支持说话人分离(speaker diarization) |
4. 选项一览(OpenAiAudioTranscriptionOptions)
| 选项 | 类型 | 说明 |
|---|---|---|
model | enum/str | 模型名(见上表) |
language | String | ISO-639-1 编码,比如 zh、en |
prompt | String | 提示词(gpt-4o-transcribe 系列支持) |
responseFormat | enum | TEXT/JSON/SRT/VTT/DICTATION/DIARIZED_JSON |
temperature | float | 0~1,越高越发散 |
语言提示
显式给 language=zh 比让模型自己猜更快、更准。如果一段音频里中英文混杂,建议不指定。
5. 说话人分离(diarize)
OpenAiAudioTranscriptionOptions options = OpenAiAudioTranscriptionOptions.builder()
.withModel("gpt-4o-transcribe-diarize")
.withResponseFormat(TranscriptResponseFormat.DIARIZED_JSON)
.withKnownSpeakerNames(List.of("张三", "李四")) // 可选:提前告诉模型说话人名字
.build();返回的 JSON 形如:
{
"task": "transcribe",
"segments": [
{ "speaker": "A", "text": "今天咱们聊一下...", "start": 0.0, "end": 3.2 },
{ "speaker": "B", "text": "好的,我先...", "start": 3.4, "end": 6.1 }
]
}DIARIZED_JSON 的 SDK 坑
OpenAI 官方 Java SDK 对 diarized_json 格式的解析有限制。Java AI 2.0.1 通过直接调用 REST 接口绕过了 SDK 的反序列化,开发者可以拿到原始 JSON 字符串自行解析。如果你看到响应里多了额外字段是正常的——那是 Java AI 给的兼容字段。
6. 流式用法
Flux<AudioTranscriptionResponse> stream = transcriptionModel.stream(prompt);OpenAI 转录目前以"整段识别"为主,真正的 token 级流式识别不是所有模型都支持。
Azure OpenAI Transcription(Azure OpenAI 语音转文字)
📌 原文地址:https://docs.spring.io/java-ai/reference/api/audio/transcriptions/azure-openai-transcriptions.html 📌 原文版本:Java AI 2.0.1
迁移通知
Azure OpenAI 的音频转录能力(包括 Whisper 模型部署)已经在 2.0 版本统一合并到 OpenAI 客户端。请改用 spring-ai-starter-model-openai,并把 spring.ai.openai.audio.transcription.endpoint 指向你的 Azure OpenAI 资源地址即可。
1. 为什么迁移
- Azure OpenAI 的 Whisper 部署在协议上和 OpenAI Whisper API 完全一致,分两个 starter 维护成本太高。
- Java AI 2.0 起,
spring-ai-starter-model-azure-openai不再注册转录相关的 bean,统一在spring-ai-starter-model-openai里通过自定义 endpoint 区分。
2. 迁移步骤
旧写法(1.x)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
</dependency>spring:
ai:
azure:
openai:
api-key: ${AZURE_OPENAI_API_KEY}
endpoint: https://<resource>.openai.azure.com
audio:
transcription:
options:
model: whisper-deployment新写法(2.0+)
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>spring:
ai:
openai:
api-key: ${AZURE_OPENAI_API_KEY}
base-url: https://<resource>.openai.azure.com/openai/deployments/<whisper-deployment>
audio:
transcription:
options:
model: whisper-deployment白话解读
说白了,就是把 Azure 的 endpoint 塞到 OpenAI 客户端的 base-url 里,业务代码一行不用动。
3. 验证
迁移完成后,TranscriptionModel bean 仍然存在,注入即可使用,行为与 1.x 一致。