L'API TTS : générer de la parole
Sur cette page
Mise à jour du 2 novembre 2026 — modèles audio. Plusieurs modèles de ce cours sont dépréciés :
tts-1,tts-1-hdetgpt-4o-mini-ttss’arrêtent le 6 janvier 2027 (remplaçant indiqué :gpt-realtime-2.1-mini, que le guide TTS d’OpenAI déclare non pris en charge par/v1/audio/speech: la migration de la synthèse vocale passe par l’API Realtime) ;gpt-realtime,gpt-4o-realtimeet les anciens modèles audio le 20 janvier 2027 (gpt-realtime-2.1,gpt-realtime-2.1-mini,gpt-audio-1.5) ;whisper-1,gpt-4o-transcribeet/v1/audio/translationsle 26 février 2027 (gpt-transcribe,gpt-live-transcribe,v1/realtime/translations). Pour la voix full-duplex, GPT-Live 1 est disponible dans l’API depuis le 10 septembre 2026. Leçon corrigée le 3 novembre 2026 :response.stream_to_file()sur le résultat despeech.create()est déprécié par le SDK (« Due to a bug, this method doesn’t actually stream ») →with_streaming_response, comme dans le guide officiel ; modèles et voix mis à jour (gpt-4o-mini-ttset ses consignes de voix, 13 voix dontmarinetcedar) ; nouvelle section sur la migration versgpt-realtime-2.1-miniavant le 6 janvier 2027, d’après le guide Realtime conversations. Sources : Text to speech · Create speech · Realtime conversations · Deprecations.
L’API TTS : générer de la parole
L’API Text-to-Speech (TTS) d’OpenAI convertit du texte en audio de haute qualité. Contrairement à la Realtime API qui gère des conversations vocales complètes, l’API TTS est un service unitaire : vous envoyez du texte, vous recevez un fichier audio. C’est l’outil idéal pour générer des annonces, des notifications vocales, des audiobooks ou du contenu accessible.
Premier appel TTS
Générer de la parole est remarquablement simple :
from openai import OpenAI
from pathlib import Path
client = OpenAI()
speech_file = Path("bienvenue.mp3")
with client.audio.speech.with_streaming_response.create(
model="gpt-4o-mini-tts",
voice="coral",
input="Bienvenue sur Corsen Academy. "
"Votre formation sur les agents vocaux commence maintenant.",
instructions="Parle d'un ton chaleureux et posé.",
) as response:
response.stream_to_file(speech_file)
L’API retourne un flux audio que vous pouvez sauvegarder directement ou streamer vers un lecteur. Passez par with_streaming_response, comme ici : appelée sur le résultat d’un simple speech.create(), la méthode stream_to_file() est dépréciée par le SDK, qui précise qu’elle ne diffuse pas réellement le flux.
Modèles disponibles
Les trois modèles de l’API Audio sont dépréciés et s’arrêtent le 6 janvier 2027 : c’est la période de transition pendant laquelle vous les utiliserez encore.
| Modèle | Particularité | Voix |
|---|---|---|
gpt-4o-mini-tts | Accepte des consignes (instructions) : accent, émotion, intonation, vitesse, ton, chuchotement | 13 voix, dont marin et cedar, recommandées pour la qualité |
tts-1 | Latence plus faible, qualité moindre | 9 voix : alloy, ash, coral, echo, fable, onyx, nova, sage, shimmer |
tts-1-hd | Qualité supérieure à tts-1, latence plus élevée | Les mêmes 9 voix |
Les consignes ne fonctionnent pas avec tts-1 et tts-1-hd. Le paramètre speed, de 0,25 à 4,0, règle le débit avec tous les modèles. D’après le guide, les voix sont optimisées pour l’anglais : écoutez-les en français sur OpenAI.fm avant de choisir. Les usages d’OpenAI exigent aussi d’indiquer clairement à vos utilisateurs que la voix qu’ils entendent est générée par une IA.
Formats de sortie
L’API produit six formats, choisis avec response_format :
| Format | Usage |
|---|---|
mp3 (par défaut) | Usage général |
opus | Streaming sur Internet et communication, faible latence |
aac | Compression numérique, privilégiée par YouTube, Android et iOS |
flac | Compression sans perte, pour l’archivage |
wav | Non compressé, pour éviter le coût du décodage |
pcm | Échantillons bruts à 24 kHz, 16 bits signés, sans en-tête |
for fmt in ("mp3", "opus", "aac", "flac", "wav", "pcm"):
with client.audio.speech.with_streaming_response.create(
model="gpt-4o-mini-tts",
voice="marin",
input="Texte à convertir",
response_format=fmt,
) as response:
response.stream_to_file(f"exemple.{fmt}")
Pour un agent vocal bâti sur l’API Realtime, le format pcm est le plus pratique : ses échantillons à 24 kHz sur 16 bits correspondent au format audio/pcm à 24 kHz de l’API Realtime.
Générer de l’audio par lots
Pour de grands volumes de texte, traitez les segments en parallèle :
import asyncio
from openai import AsyncOpenAI
async_client = AsyncOpenAI()
async def generate_speech_batch(segments: list[dict]) -> list[bytes]:
"""Génère l'audio pour plusieurs segments en parallèle."""
async def generate_one(segment):
response = await async_client.audio.speech.create(
model="gpt-4o-mini-tts",
voice=segment.get("voice", "alloy"),
input=segment["text"],
response_format="mp3"
)
return await response.aread()
tasks = [generate_one(seg) for seg in segments]
return await asyncio.gather(*tasks)
# Utilisation
segments = [
{"text": "Chapitre un. Introduction aux agents vocaux.", "voice": "onyx"},
{"text": "Les agents vocaux transforment l'interaction homme-machine.", "voice": "onyx"},
{"text": "Dans ce chapitre, nous explorerons les fondamentaux.", "voice": "onyx"},
]
audio_chunks = asyncio.run(generate_speech_batch(segments))
# Concaténer les fichiers
from pydub import AudioSegment
import io
combined = AudioSegment.empty()
for chunk in audio_chunks:
segment = AudioSegment.from_mp3(io.BytesIO(chunk))
combined += segment
combined.export("chapitre_1.mp3", format="mp3")
Limite de caractères et découpage
L’API TTS a une limite de 4096 caractères par requête. Pour des textes plus longs, découpez intelligemment :
def split_text_for_tts(text: str, max_chars: int = 4000) -> list[str]:
"""Découpe un texte en segments respectant les limites TTS."""
sentences = text.replace(". ", ".\n").split("\n")
segments = []
current = ""
for sentence in sentences:
if len(current) + len(sentence) + 1 > max_chars:
if current:
segments.append(current.strip())
current = sentence
else:
current += " " + sentence if current else sentence
if current:
segments.append(current.strip())
return segments
Après le 6 janvier 2027 : faire parler un modèle Realtime
OpenAI désigne gpt-realtime-2.1-mini comme remplaçant des trois modèles, et prévient : ce n’est pas un modèle de l’endpoint /v1/audio/speech, la migration change de méthode de travail. On passe par une session Realtime. Le guide Realtime conversations montre comment obtenir une réponse sans contexte, qui ignore la conversation et ne suit que ses instructions : c’est le moyen de faire dire un texte donné.
import base64
import json
import os
import wave
import websocket # pip install websocket-client
TEXTE = "Bienvenue sur Corsen Academy. Votre formation sur les agents vocaux commence maintenant."
ws = websocket.WebSocket()
ws.connect(
"wss://api.openai.com/v1/realtime?model=gpt-realtime-2.1-mini",
header=[f"Authorization: Bearer {os.environ['OPENAI_API_KEY']}"],
)
# Sortie audio seule, en PCM 16 bits à 24 kHz, avec la voix choisie
ws.send(json.dumps({
"type": "session.update",
"session": {
"type": "realtime",
"output_modalities": ["audio"],
"audio": {"output": {"format": {"type": "audio/pcm", "rate": 24000}, "voice": "marin"}},
},
}))
# Une réponse sans contexte (input vide), qui doit dire le texte tel quel
ws.send(json.dumps({
"type": "response.create",
"response": {
"input": [],
"output_modalities": ["audio"],
"instructions": f"Dis exactement le texte suivant, sans rien ajouter :\n{TEXTE}",
},
}))
audio, transcription = bytearray(), []
while True:
event = json.loads(ws.recv())
if event["type"] == "response.output_audio.delta":
audio += base64.b64decode(event["delta"])
elif event["type"] == "response.output_audio_transcript.delta":
transcription.append(event["delta"])
elif event["type"] == "error":
raise RuntimeError(event["error"]["message"])
elif event["type"] == "response.done":
break
ws.close()
with wave.open("bienvenue.wav", "wb") as wav:
wav.setnchannels(1)
wav.setsampwidth(2) # 16 bits
wav.setframerate(24000)
wav.writeframes(bytes(audio))
print("Texte prononcé :", "".join(transcription))
Deux différences avec l’API Audio comptent en production. Le résultat n’est plus garanti mot pour mot : un modèle Realtime suit une consigne, il ne lit pas un fichier. Comparez donc la transcription de ce qu’il a dit, renvoyée dans response.output_audio_transcript.delta, au texte attendu, et régénérez en cas d’écart. La facturation change aussi : elle suit les tarifs du modèle Realtime, en tokens texte et audio, indiqués sur sa fiche. Une clé refusée, enfin, n’empêche pas la connexion : elle arrive juste après, dans un événement error.
Points clés à retenir
gpt-4o-mini-tts,tts-1ettts-1-hds’arrêtent le 6 janvier 2027 ;gpt-4o-mini-ttsest le seul à accepter des consignes de voix (instructions)- Enregistrez l’audio avec
with_streaming_response:stream_to_file()sur un simplespeech.create()est déprécié - Six formats de sortie : MP3, Opus, AAC, FLAC, WAV et PCM brut
- Le format PCM est idéal pour l’intégration avec la Realtime API
- Limite de 4096 caractères par requête : découpez les textes longs aux frontières de phrases
- Le traitement par lots avec le client asynchrone accélère la génération de contenu volumineux
- La migration passe par une session Realtime avec
gpt-realtime-2.1-mini: réponse sans contexte, audio PCM 24 kHz, transcription à comparer au texte