# Audio (voix et transcription)

> Référence de POST /v1/audio/speech, qui lit un texte à voix haute, et de POST /v1/audio/transcriptions, qui transcrit un enregistrement, au format d’OpenAI.

Deux points d’accès au format de l’API Audio d’OpenAI : l’un transforme un texte en voix, l’autre un enregistrement en texte. Le son envoyé est lu en mémoire et n’est jamais écrit sur nos serveurs. Moon Blur ne s’applique ni au texte lu ni à l’audio (`X-Moon-Blur: not_applied`).

## Lire un texte à voix haute

```http
POST https://api.realmoon.ai/v1/audio/speech
```

- Authentification : clé `sk-moon-…` avec la portée `inference` (voir [Authentification](https://realmoon.ai/documentation/api/authentification/)).
- Corps : JSON, 256 Ko au plus.
- Réponse : le fichier audio lui-même.

### Paramètres

| Paramètre | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `model` | chaîne | oui | Un modèle de type `speech` de `GET /v1/models?type=speech`. |
| `input` | chaîne | oui | Le texte à lire, 4 096 caractères au plus. Découpez un texte plus long en plusieurs requêtes. |
| `voice` | chaîne | non | Identifiant d’une voix du modèle : lettres, chiffres, espaces et `_ . : ( ) + -`, 128 caractères au plus. Vide : la voix par défaut du modèle (`default_voice` dans `/v1/models`). |
| `response_format` | chaîne | non | `mp3` (par défaut). Les voix Gemini acceptent aussi `wav` et `pcm` (`response_formats` dans `/v1/models`). |
| `instructions` | chaîne | non | Style de lecture (ton, rythme), 500 caractères au plus. Voix Gemini seulement. |
| `speed` | nombre | non | Seule la valeur `1` est acceptée. |
| `language` | chaîne | non | Accepté, sans effet. |

Tout autre paramètre est refusé avec `400 unknown_parameter`.

> [!TIP]
> **Voix d’OpenAI**
>
> Un client écrit pour OpenAI fonctionne tel quel : si le modèle a une voix par défaut, un nom de voix d’OpenAI comme `alloy` ou `nova` est remplacé par celle-ci. Pour les autres modèles, donnez un identifiant de voix de leur fournisseur.

### Exemple

```bash title="cURL"
curl https://api.realmoon.ai/v1/audio/speech \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "mistralai/voxtral-mini-tts-2603", "voice": "fr_marie_neutral", "input": "Bonjour et bienvenue."}' \
  -o bonjour.mp3
```

```python title="Python"
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.realmoon.ai/v1", api_key=os.environ["MOONAI_API_KEY"])

with client.audio.speech.with_streaming_response.create(
    model="mistralai/voxtral-mini-tts-2603",
    voice="fr_marie_neutral",
    input="Bonjour et bienvenue.",
) as response:
    print("Crédits :", response.headers.get("x-moon-credits"))
    response.stream_to_file("bonjour.mp3")
```

```javascript title="JavaScript"
import fs from 'node:fs';
import OpenAI from 'openai';

const client = new OpenAI({ baseURL: 'https://api.realmoon.ai/v1', apiKey: process.env.MOONAI_API_KEY });

const speech = await client.audio.speech.create({
  model: 'mistralai/voxtral-mini-tts-2603',
  voice: 'fr_marie_neutral',
  input: 'Bonjour et bienvenue.',
});
fs.writeFileSync('bonjour.mp3', Buffer.from(await speech.arrayBuffer()));
```

### Réponse

Le corps de la réponse est le fichier audio :

| `response_format` | `Content-Type` | Contenu |
| --- | --- | --- |
| `mp3` | `audio/mpeg` | MP3 |
| `wav` | `audio/wav` | WAV, 16 bits, 24 kHz, mono |
| `pcm` | `audio/pcm` | PCM brut, 16 bits, 24 kHz, mono |

| En-tête | Valeur |
| --- | --- |
| `X-Moon-Credits` | Crédits facturés pour la requête. |
| `X-Moon-Request-Id` | Identifiant de la requête, pour [`/v1/generation`](https://realmoon.ai/documentation/api/solde/#generation). |
| `X-Moon-Prompt-Storage` | `none`. |
| `X-Moon-Blur` | `not_applied`. |

### Modèles de voix

Liste au 5 novembre 2026 ; la liste à jour, avec les prix, vient de `GET /v1/models?type=speech`.

| Modèle | Voix par défaut | Formats |
| --- | --- | --- |
| `mistralai/voxtral-mini-tts-2603` | `fr_marie_neutral` | mp3 |
| `mistralai/voxtral-mini-tts-3-0` | aucune | mp3 |
| `microsoft/mai-voice-2.1-flash` | `fr-FR-Soleil:MAI-Voice-2.1-Flash` | mp3 |
| `microsoft/mai-voice-2.1` | aucune | mp3 |
| `elevenlabs/eleven-flash-v2.5`, `eleven-multilingual-v2`, `eleven-v3` | aucune | mp3 |
| `fish-audio/s2.1-pro`, `deepgram/aura-2`, `qwen/qwen-audio-3.0-tts-flash`, `hexgrad/kokoro-82m` | aucune | mp3 |
| `google/gemini-3.8-flash-lite-tts`, `google/gemini-3.8-flash-tts` | `Sulafat` | mp3, wav, pcm |

### Coûts

La plupart des voix sont facturées au caractère du texte lu (`billing: per_character`). Les voix Gemini sont facturées sur le texte envoyé et sur la durée du son réellement produit. La requête retient le prix du texte avant l’appel ; une requête qui échoue ou que notre délai coupe ne coûte rien.

### Erreurs

| HTTP | `code` | Signification |
| --- | --- | --- |
| 400 | `missing_required_parameter` | `model` ou `input` absent. |
| 400 | `unknown_parameter` | Paramètre inconnu. |
| 400 | `unsupported_value` | `response_format` non proposé par le modèle. |
| 400 | `unsupported_parameter` | `speed` différent de 1, `instructions` sur une voix qui n’est pas Gemini, ou voix, langue ou format refusés par le modèle (avec une indication). |
| 400 | `string_above_max_length` | Texte de plus de 4 096 caractères. |
| 400 | `null` | `voice` mal formé, `instructions` de plus de 500 caractères, corps JSON invalide. |
| 404 | `model_not_found` | Modèle inconnu ou qui ne sert pas ce point d’accès. |
| 413 | `request_too_large` | Corps de plus de 256 Ko. |
| 429 | `too_many_concurrent` | Déjà 8 lectures en cours pour ce workspace. |
| 429 | `upstream_rate_limited` | Le modèle est surchargé : réessayez après `Retry-After` (10 secondes). |
| 502, 504 | `upstream_error`, `upstream_timeout` | Le modèle a échoué, n’a pas produit de son, ou n’a pas répondu à temps. |

## Transcrire un enregistrement

```http
POST https://api.realmoon.ai/v1/audio/transcriptions
```

- Authentification : clé `sk-moon-…` avec la portée `inference`.
- Corps : `multipart/form-data` seulement, avec l’en-tête `Content-Length`. Le fichier va dans le champ `file`.
- Réponse : la transcription, en JSON ou en texte.

### Paramètres

| Champ | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `file` | fichier | oui | L’enregistrement : wav, mp3, flac, m4a (ou mp4), ogg, webm ou aac. 25 Mo et 20 minutes au plus. |
| `model` | chaîne | oui | Un modèle de type `transcription` de `GET /v1/models?type=transcription`. |
| `language` | chaîne | non | Code de langue ISO 639-1 (`fr`, `en`…). Améliore la transcription. |
| `prompt` | chaîne | non | Contexte ou vocabulaire attendu (noms propres, sigles), 1 000 caractères au plus. |
| `response_format` | chaîne | non | `json` (par défaut), `text` ou `verbose_json`. |
| `temperature`, `timestamp_granularities[]` |  | non | Acceptés, sans effet. |

Tout autre champ est refusé avec `400 unknown_parameter`. Un enregistrement de plus de 20 minutes est refusé (`400 audio_too_long`) : découpez-le en morceaux. La durée d’un fichier compressé est comptée au moins d’après sa taille.

### Exemple

```bash title="cURL"
curl https://api.realmoon.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $MOONAI_API_KEY" \
  -F model=mistralai/voxtral-mini-transcribe \
  -F language=fr \
  -F file=@reunion.m4a
```

```python title="Python"
with open("reunion.m4a", "rb") as audio:
    transcript = client.audio.transcriptions.create(
        model="mistralai/voxtral-mini-transcribe",
        file=audio,
        language="fr",
    )
print(transcript.text)
```

```javascript title="JavaScript"
const transcript = await client.audio.transcriptions.create({
  model: 'mistralai/voxtral-mini-transcribe',
  file: fs.createReadStream('reunion.m4a'),
  language: 'fr',
});
console.log(transcript.text);
```

### Réponse

```json title="response_format: json"
{
  "text": "Bonjour à tous, on commence par le point budget.",
  "usage": { "type": "duration", "seconds": 312.4, "credits": 0 }
}
```

La valeur de `credits` est fictive.

| Champ | Type | Description |
| --- | --- | --- |
| `text` | chaîne | Le texte transcrit. |
| `usage.type` | chaîne | Toujours `duration`. |
| `usage.seconds` | nombre | Durée de l’audio prise en compte, en secondes. |
| `usage.credits` | entier | Crédits facturés. |
| `task` | chaîne | Avec `verbose_json` : `transcribe`. |
| `language` | chaîne ou `null` | Avec `verbose_json` : la langue détectée ou demandée. |
| `duration` | nombre ou `null` | Avec `verbose_json` : la durée en secondes. |

Avec `response_format: "text"`, la réponse est le texte seul, en `text/plain`. Dans tous les cas, l’en-tête `X-Moon-Credits` donne les crédits facturés, et `X-Moon-Request-Id` l’identifiant de la requête.

### Modèles de transcription

Liste au 5 novembre 2026 ; la liste à jour, avec les prix à la minute, vient de `GET /v1/models?type=transcription`.

- `mistralai/voxtral-mini-transcribe`, `mistralai/voxtral-mini-transcribe-3-0`, `mistralai/voxtral-small-transcribe-3-0`
- `openai/whisper-large-v3-turbo`, `openai/whisper-large-v3`, `openai/gpt-4o-mini-transcribe`, `openai/gpt-4o-transcribe`
- `elevenlabs/scribe-v2`, `deepgram/nova-3`, `assemblyai/universal-3-6-pro`
- `nvidia/parakeet-tdt-0.6b-v3`, `qwen/qwen3-asr-1.7b`

### Coûts

La transcription est facturée au coût réel annoncé par le fournisseur, selon la durée de l’audio (à défaut, au prix de la liste). Avant l’appel, la requête retient au moins le prix d’une minute, avec une marge. Une transcription qui échoue ne coûte rien.

### Erreurs

| HTTP | `code` | Signification |
| --- | --- | --- |
| 400 | `invalid_content_type` | Requête envoyée autrement qu’en `multipart/form-data`. |
| 400 | `missing_required_parameter` | `model` ou `file` absent. |
| 400 | `unknown_parameter` | Champ inconnu. |
| 400 | `unsupported_value` | `response_format` inconnu. |
| 400 | `unsupported_format` | Format audio non reconnu. |
| 400 | `audio_too_long` | Enregistrement de plus de 20 minutes. |
| 400 | `unsupported_parameter` | Langue ou format refusés par le modèle (avec une indication). |
| 400 | `null` | `language` mal formé, `prompt` de plus de 1 000 caractères, fichier vide, champ de fichier inattendu. |
| 404 | `model_not_found` | Modèle inconnu ou qui ne sert pas ce point d’accès. |
| 411 | `length_required` | Envoi sans en-tête `Content-Length`. |
| 413 | `file_too_large`, `request_too_large` | Fichier de plus de 25 Mo, ou corps trop volumineux. |
| 429 | `too_many_concurrent` | Déjà 4 transcriptions en cours pour ce workspace. |
| 429 | `upstream_rate_limited` | Le modèle est surchargé : réessayez après `Retry-After` (10 secondes). |
| 502, 504 | `upstream_error`, `upstream_timeout` | Le modèle a échoué ou n’a pas répondu à temps. |

Les erreurs de clé, de solde et de plafonds, communes aux deux points d’accès, sont dans [Erreurs](https://realmoon.ai/documentation/api/erreurs/).

## Limites

| Limite | Voix | Transcription |
| --- | --- | --- |
| Taille | 4 096 caractères, corps de 256 Ko | fichier de 25 Mo, 20 minutes d’audio |
| Requêtes en cours par workspace | 8 | 4 |
| Attente de la réponse du modèle | 85 secondes au plus | 85 secondes au plus |

## Voir aussi

- [Modèles](https://realmoon.ai/documentation/api/modeles/#medias) : les champs `default_voice`, `response_formats` et `max_file_mb`.
- [Confidentialité](https://realmoon.ai/documentation/api/confidentialite/#garde) : ce que Moon AI garde des requêtes audio.

---

Documentation Moon AI › API développeur › Audio. Page : https://realmoon.ai/documentation/api/audio/. Modifiée le 5 novembre 2026.

© 2026 Stellarr Studio SAS. Tous droits réservés. Moon AI, Moon Blur et Stellarr Studio sont des marques déposées à l’INPI.
