OpenAI テキスト読み上げ (TTS)
導入
オーディオ API は、OpenAI の TTS (テキスト読み上げ) モデルに基づく音声エンドポイントを提供し、ユーザーは次のことが可能になります。
書かれたブログ投稿をナレーションします。
複数の言語で音声を生成します。
ストリーミングを使用してリアルタイムのオーディオ出力を提供します。
前提条件
OpenAI アカウントを作成し、API キーを取得します。OpenAI サインアップページ (英語) でサインアップし、API キーページ (英語) で API キーを生成できます。
プロジェクトのビルドファイルに
spring-ai-openai依存関係を追加します。詳細については、依存関係管理セクションを参照してください。
自動構成
Spring AI 自動構成、スターターモジュールのアーティファクト名に大きな変更がありました。詳細については、アップグレードノートを参照してください。 |
Spring AI は、OpenAI テキスト読み上げクライアント用の Spring Boot 自動構成を提供します。これを有効にするには、プロジェクトの Maven pom.xml ファイルに次の依存関係を追加します。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency> または、Gradle build.gradle ビルドファイルに次の内容を追加します。
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}| Spring AI BOM をビルドファイルに追加するには、"依存関係管理" セクションを参照してください。 |
音声プロパティ
接続プロパティ
接頭辞 spring.ai.openai は、OpenAI への接続を可能にするプロパティ接頭辞として使用されます。
プロパティ | 説明 | デフォルト |
spring.ai.openai.base-url | 接続先の URL | |
spring.ai.openai.api-key | API キー | - |
spring.ai.openai.organization-id | オプションで、API リクエストに使用する組織を指定できます。 | - |
spring.ai.openai.project-id | 必要に応じて、API リクエストに使用するプロジェクトを指定できます。 | - |
| 複数の組織に属しているユーザー(または従来のユーザー API キーを使用してプロジェクトにアクセスしているユーザー)の場合は、オプションで、API リクエストに使用する組織とプロジェクトを指定できます。これらの API リクエストからの使用量は、指定された組織とプロジェクトの使用量としてカウントされます。 |
プロパティの構成
オーディオ音声自動構成の有効化と無効化は、プレフィックス 有効にするには、spring.ai.model.audio.speech=openai (デフォルトで有効になっています) 無効にするには、spring.ai.model.audio.speech=none (または openai と一致しない値) この変更は、複数のモデルの構成を可能にするために行われます。 |
プレフィックス spring.ai.openai.audio.speech は、OpenAI テキスト読み上げクライアントを構成できるプロパティプレフィックスとして使用されます。
| プロパティ | 説明 | デフォルト |
|---|---|---|
spring.ai.model.audio.speech | オーディオ音声モデルを有効にする | 開く |
spring.ai.openai.audio.speech.base-url | 接続先の URL | |
spring.ai.openai.audio.speech.api-key | API キー | - |
spring.ai.openai.audio.speech.organization-id | オプションで、API リクエストに使用する組織を指定できます。 | - |
spring.ai.openai.audio.speech.project-id | 必要に応じて、API リクエストに使用するプロジェクトを指定できます。 | - |
spring.ai.openai.audio.speech.options.model | オーディオ生成に使用するモデルの ID。使用可能なモデル: | gpt-4o-mini-tts |
spring.ai.openai.audio.speech.options.voice | 合成に使用する音声。OpenAI の TTS API の場合、選択したモデルで利用可能な音声(alloy、echo、fable、onyx、nova、shimmer)のいずれかになります。 | 合金 |
spring.ai.openai.audio.speech.options.response-format | オーディオ出力の形式。サポートされている形式は、mp3、opus、aac、flac、wav、pcm です。 | mp3 |
spring.ai.openai.audio.speech.options.speed | 音声合成の速度。許容範囲は 0.25 (最も遅い) から 4.0 (最も速い) までです。 | 1.0 |
共通の spring.ai.openai.base-url、spring.ai.openai.api-key、spring.ai.openai.organization-id、spring.ai.openai.project-id プロパティをオーバーライドできます。spring.ai.openai.audio.speech.base-url、spring.ai.openai.audio.speech.api-key、spring.ai.openai.audio.speech.organization-id、spring.ai.openai.audio.speech.project-id プロパティが設定されている場合は、共通のプロパティよりも優先されます。これは、異なるモデルや異なるモデルエンドポイントに異なる OpenAI アカウントを使用する場合に便利です。 |
spring.ai.openai.audio.speech.options で始まるすべてのプロパティは、実行時にオーバーライドできます。 |
ランタイムオプション
OpenAiAudioSpeechOptions クラスは、テキスト読み上げリクエストを行うときに使用するオプションを提供します。起動時には、spring.ai.openai.audio.speech で指定されたオプションが使用されますが、実行時にこれらを上書きできます。
OpenAiAudioSpeechOptions クラスは TextToSpeechOptions インターフェースを実装し、移植可能な構成オプションと OpenAI 固有の構成オプションの両方を提供します。
例:
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.model("gpt-4o-mini-tts")
.voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.speed(1.0)
.build();
TextToSpeechPrompt speechPrompt = new TextToSpeechPrompt("Hello, this is a text-to-speech example.", speechOptions);
TextToSpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);手動構成
spring-ai-openai 依存関係をプロジェクトの Maven pom.xml ファイルに追加します。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
</dependency> または、Gradle build.gradle ビルドファイルに次の内容を追加します。
dependencies {
implementation 'org.springframework.ai:spring-ai-openai'
}| Spring AI BOM をビルドファイルに追加するには、"依存関係管理" セクションを参照してください。 |
次に、OpenAiAudioSpeechModel を作成します。
var openAiAudioApi = new OpenAiAudioApi()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi);
var speechOptions = OpenAiAudioSpeechOptions.builder()
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.speed(1.0)
.model(OpenAiAudioApi.TtsModel.GPT_4_O_MINI_TTS.value)
.build();
var speechPrompt = new TextToSpeechPrompt("Hello, this is a text-to-speech example.", speechOptions);
TextToSpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
// Accessing metadata (rate limit info)
OpenAiAudioSpeechResponseMetadata metadata = (OpenAiAudioSpeechResponseMetadata) response.getMetadata();
byte[] responseAsBytes = response.getResult().getOutput();リアルタイムオーディオのストリーミング
Speech API は、チャンク転送エンコーディングを使用したリアルタイムオーディオストリーミングをサポートします。つまり、完全なファイルが生成されてアクセス可能になる前にオーディオを再生できます。
OpenAiAudioSpeechModel は StreamingTextToSpeechModel インターフェースを実装し、標準機能とストリーミング機能の両方を提供します。
var openAiAudioApi = new OpenAiAudioApi()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi);
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
.speed(1.0)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.model(OpenAiAudioApi.TtsModel.GPT_4_O_MINI_TTS.value)
.build();
TextToSpeechPrompt speechPrompt = new TextToSpeechPrompt("Today is a wonderful day to build something people love!", speechOptions);
Flux<TextToSpeechResponse> responseStream = openAiAudioSpeechModel.stream(speechPrompt);
// You can also stream raw audio bytes directly
Flux<byte[]> audioByteStream = openAiAudioSpeechModel.stream("Hello, world!");移行ガイド
非推奨の SpeechModel および SpeechPrompt クラスからアップグレードする場合、このガイドには、新しい共有インターフェースに移行するための詳細な手順が記載されています。
重大な変更の概要
この移行には、次の重大な変更が含まれます。
削除されたクラス :
org.springframework.ai.openai.audio.speechパッケージから 6 つの非推奨クラスが削除されましたパッケージの変更 : コア TTS クラスは
org.springframework.ai.audio.ttsパッケージに移動されました型の変更 : すべての OpenAI TTS コンポーネントで、
speedパラメーターがFloatからDoubleに変更されました。インターフェース階層 :
TextToSpeechModelはStreamingTextToSpeechModelを継承するようになりました
クラスマッピングリファレンス
| 非推奨 (除去) | 新規インターフェース |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
ステップバイステップの移行手順
ステップ 1: インポートの更新
古い org.springframework.ai.openai.audio.speech パッケージからのすべてのインポートを新しい共有インターフェースに置き換えます。
Find: import org.springframework.ai.openai.audio.speech.SpeechModel;
Replace: import org.springframework.ai.audio.tts.TextToSpeechModel;
Find: import org.springframework.ai.openai.audio.speech.StreamingSpeechModel;
Replace: import org.springframework.ai.audio.tts.StreamingTextToSpeechModel;
Find: import org.springframework.ai.openai.audio.speech.SpeechPrompt;
Replace: import org.springframework.ai.audio.tts.TextToSpeechPrompt;
Find: import org.springframework.ai.openai.audio.speech.SpeechResponse;
Replace: import org.springframework.ai.audio.tts.TextToSpeechResponse;
Find: import org.springframework.ai.openai.audio.speech.SpeechMessage;
Replace: import org.springframework.ai.audio.tts.TextToSpeechMessage;
Find: import org.springframework.ai.openai.audio.speech.Speech;
Replace: import org.springframework.ai.audio.tts.Speech;ステップ 2: 型参照の更新
コード内のすべての型参照を置き換えます。
Find: SpeechModel
Replace: TextToSpeechModel
Find: StreamingSpeechModel
Replace: StreamingTextToSpeechModel
Find: SpeechPrompt
Replace: TextToSpeechPrompt
Find: SpeechResponse
Replace: TextToSpeechResponse
Find: SpeechMessage
Replace: TextToSpeechMessageステップ 3: 速度パラメーターの更新 (フロート→ ダブル)
speed パラメーターが Float から Double に変更されました。すべての出現箇所を更新してください。
Find: .speed(1.0f)
Replace: .speed(1.0)
Find: .speed(0.5f)
Replace: .speed(0.5)
Find: Float speed
Replace: Double speed直列化されたデータや Float 値を含む設定ファイルがある場合は、それらも更新する必要があります。
// Before
{
"speed": 1.0
}
// After (no code change needed for JSON, but be aware of type change in Java)
{
"speed": 1.0
}ステップ 4: Bean 宣言の更新
Spring Boot 自動構成または手動の Bean 定義がある場合:
// Before
@Bean
public SpeechModel speechModel(OpenAiAudioApi audioApi) {
return new OpenAiAudioSpeechModel(audioApi);
}
// After
@Bean
public TextToSpeechModel textToSpeechModel(OpenAiAudioApi audioApi) {
return new OpenAiAudioSpeechModel(audioApi);
}コード移行の例
例 1: 基本的なテキスト音声変換
以前(非推奨):
import org.springframework.ai.openai.audio.speech.*;
@Service
public class OldNarrationService {
private final SpeechModel speechModel;
public OldNarrationService(SpeechModel speechModel) {
this.speechModel = speechModel;
}
public byte[] createNarration(String text) {
SpeechPrompt prompt = new SpeechPrompt(text);
SpeechResponse response = speechModel.call(prompt);
return response.getResult().getOutput();
}
}後(共有インターフェースを使用):
import org.springframework.ai.audio.tts.*;
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
@Service
public class NarrationService {
private final TextToSpeechModel textToSpeechModel;
public NarrationService(TextToSpeechModel textToSpeechModel) {
this.textToSpeechModel = textToSpeechModel;
}
public byte[] createNarration(String text) {
TextToSpeechPrompt prompt = new TextToSpeechPrompt(text);
TextToSpeechResponse response = textToSpeechModel.call(prompt);
return response.getResult().getOutput();
}
}例 2: カスタムオプションによるテキスト読み上げ
以前(非推奨):
import org.springframework.ai.openai.audio.speech.*;
import org.springframework.ai.openai.api.OpenAiAudioApi;
SpeechModel model = new OpenAiAudioSpeechModel(audioApi);
OpenAiAudioSpeechOptions options = OpenAiAudioSpeechOptions.builder()
.model("tts-1")
.voice(OpenAiAudioApi.SpeechRequest.Voice.NOVA)
.speed(1.0f) // Float value
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.build();
SpeechPrompt prompt = new SpeechPrompt("Hello, world!", options);
SpeechResponse response = model.call(prompt);
byte[] audio = response.getResult().getOutput();後(共有インターフェースを使用):
import org.springframework.ai.audio.tts.*;
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
import org.springframework.ai.openai.OpenAiAudioSpeechOptions;
import org.springframework.ai.openai.api.OpenAiAudioApi;
TextToSpeechModel model = new OpenAiAudioSpeechModel(audioApi);
OpenAiAudioSpeechOptions options = OpenAiAudioSpeechOptions.builder()
.model("tts-1")
.voice(OpenAiAudioApi.SpeechRequest.Voice.NOVA)
.speed(1.0) // Double value
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.build();
TextToSpeechPrompt prompt = new TextToSpeechPrompt("Hello, world!", options);
TextToSpeechResponse response = model.call(prompt);
byte[] audio = response.getResult().getOutput();例 3: ストリーミングテキスト読み上げ
以前(非推奨):
import org.springframework.ai.openai.audio.speech.*;
import reactor.core.publisher.Flux;
StreamingSpeechModel model = new OpenAiAudioSpeechModel(audioApi);
SpeechPrompt prompt = new SpeechPrompt("Stream this text");
Flux<SpeechResponse> stream = model.stream(prompt);
stream.subscribe(response -> {
byte[] audioChunk = response.getResult().getOutput();
// Process audio chunk
});後(共有インターフェースを使用):
import org.springframework.ai.audio.tts.*;
import org.springframework.ai.openai.OpenAiAudioSpeechModel;
import reactor.core.publisher.Flux;
TextToSpeechModel model = new OpenAiAudioSpeechModel(audioApi);
TextToSpeechPrompt prompt = new TextToSpeechPrompt("Stream this text");
Flux<TextToSpeechResponse> stream = model.stream(prompt);
stream.subscribe(response -> {
byte[] audioChunk = response.getResult().getOutput();
// Process audio chunk
});例 4: Spring Boot による依存性注入
以前(非推奨):
@RestController
public class OldSpeechController {
private final SpeechModel speechModel;
@Autowired
public OldSpeechController(SpeechModel speechModel) {
this.speechModel = speechModel;
}
@PostMapping("/narrate")
public ResponseEntity<byte[]> narrate(@RequestBody String text) {
SpeechPrompt prompt = new SpeechPrompt(text);
SpeechResponse response = speechModel.call(prompt);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("audio/mpeg"))
.body(response.getResult().getOutput());
}
}後(共有インターフェースを使用):
@RestController
public class SpeechController {
private final TextToSpeechModel textToSpeechModel;
@Autowired
public SpeechController(TextToSpeechModel textToSpeechModel) {
this.textToSpeechModel = textToSpeechModel;
}
@PostMapping("/narrate")
public ResponseEntity<byte[]> narrate(@RequestBody String text) {
TextToSpeechPrompt prompt = new TextToSpeechPrompt(text);
TextToSpeechResponse response = textToSpeechModel.call(prompt);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("audio/mpeg"))
.body(response.getResult().getOutput());
}
}Spring Boot 構成の変更
Spring Boot の自動構成プロパティは変更されません。application.properties ファイルまたは application.yml ファイルに変更を加える必要はありません。
ただし、明示的な Bean 参照または修飾子がある場合は、更新します。
// Before
@Qualifier("speechModel")
// After
@Qualifier("textToSpeechModel")移行のメリット
ポータビリティ : 一度コードを記述すれば、OpenAI、ElevenLabs、その他の TTS プロバイダーを簡単に切り替えることができます。
一貫性 : ChatModel や他の Spring AI 抽象化と同じパターン
型安全性 : 適切なインターフェース実装による型階層の改善
将来を見据えた : 新しい TTS プロバイダーは既存のコードで自動的に動作します
標準化 : すべての TTS プロバイダー間で速度パラメーターの一貫した
Double型
一般的な移行の課題と解決策
第 1 号: コンパイルエラー - シンボル SpeechModel が見つかりません
エラー:
error: cannot find symbol SpeechModel ソリューション : 手順 1 の説明に従ってインポートを更新し、SpeechModel を TextToSpeechModel に変更します。
サンプルコード
OpenAiSpeechModelIT.java [GitHub] (英語) テストでは、ライブラリの使用方法に関する一般的な例がいくつか提供されます。