> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gradium.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Voice Design

> Créez une voix à partir d'une description écrite, écoutez-la, puis convertissez-la en une voix utilisable partout

Voice Design crée des voix naturelles et réalistes à partir d'une description textuelle.
Décrivez le personnage que vous souhaitez pour votre agent vocal ou votre produit, et Gradium
génère quelques candidats. Vous les écoutez, puis vous convertissez celui qui vous plaît en
voix permanente. Elle fonctionne dès lors comme n'importe quel autre `voice_id` : REST,
WebSocket et Speech-to-Speech. Aucun audio de référence n'est nécessaire.

<Card title="Vous avez plutôt un enregistrement ?" icon="microphone" href="/fr/guides/voices/custom-voices">
  Les voix personnalisées clonent un locuteur à partir d'un court échantillon audio.
</Card>

## Fonctionnement

<CardGroup cols={2}>
  <Card title="1. Générer" icon="wand-magic-sparkles">
    Envoyez une description et recevez des voix candidates en quelques secondes.
  </Card>

  <Card title="2. Écouter" icon="headphones">
    Écoutez chaque candidat sur une courte phrase en synthèse vocale (TTS).
  </Card>

  <Card title="3. Convertir" icon="bookmark">
    Transformez votre choix en `voice_id` permanent.
  </Card>

  <Card title="4. Utiliser" icon="waveform-lines">
    La synthèse vocale, le streaming et le Speech-to-Speech l'acceptent tous.
  </Card>
</CardGroup>

Décrivez la voix en une ou deux phrases, jusqu'à 500 caractères, en anglais,
français, espagnol, portugais ou allemand. Gradium développe la description en une
spécification plus complète et en échantillonne de 1 à 5 voix complètes, prêtes en
quelques secondes. Écoutez chacune sur une courte phrase, puis convertissez celle que
vous voulez. Tant qu'il n'est pas converti, un candidat ne peut pas être utilisé en production.

Deux points à connaître. Le modèle échantillonne une nouvelle voix à chaque requête : si
un candidat vous plaît, convertissez-le, car relancer la requête ne le fera pas revenir. Par
ailleurs, les candidats d'une même requête sont des variations d'un même personnage. Pour
un personnage différent, modifiez la description.

## Accès

URL de base `https://api.gradium.ai/api`, clé API dans l'en-tête `x-api-key`.

| Appel | Endpoint |
| :- | :- |
| Générer des candidats | `POST /voice-generator/generate` |
| Vérifier la disponibilité ou lister les candidats | `GET /voice-generator/embeddings` |
| Écouter un candidat | `POST /post/speech/tts` |
| Convertir un candidat | `POST /voices/from-embedding` |
| Supprimer un candidat | `DELETE /voice-generator/embeddings/{embedding_id}` |

## Démarrage rapide

Les étapes s'enchaînent en une seule séquence, en conservant les identifiants dans des variables shell ou des noms Python.

<Steps>
  <Step title="Générer des candidats">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST https://api.gradium.ai/api/voice-generator/generate \
        -H "x-api-key: $GRADIUM_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "prompt": "A British female voice, 20 to 30, glossy and confident, with girly chatter, high pitch, fast pacing, high energy and bright sparkling resonance. Ideal for a friendly receptionist or assistant.",
          "language": "en",
          "n_samples": 3
        }' > candidates.json

      CAND0=$(jq -r '.embeddings[0].embedding_id' candidates.json)
      CAND1=$(jq -r '.embeddings[1].embedding_id' candidates.json)
      ```

      ```python Python theme={null}
      import os
      import requests

      API_KEY = os.environ["GRADIUM_API_KEY"]
      BASE = "https://api.gradium.ai/api"

      resp = requests.post(
          f"{BASE}/voice-generator/generate",
          json={
              "prompt": (
                  "A British female voice, 20 to 30, glossy and confident, with girly "
                  "chatter, high pitch, fast pacing, high energy and bright sparkling "
                  "resonance. Ideal for a friendly receptionist or assistant."
              ),
              "language": "en",
              "n_samples": 3,
          },
          headers={"x-api-key": API_KEY},
      )
      resp.raise_for_status()
      candidates = [e["embedding_id"] for e in resp.json()["embeddings"]]
      ```
    </CodeGroup>

    ```json 201 Created theme={null}
    {
      "embeddings": [
        { "embedding_id": "vox_emb_njsiEgpj5NjHKdZc", "ready": false, "expires_at": "2026-10-03T11:00:00Z" },
        { "embedding_id": "vox_emb_39vb1XVZpnSF5Rt4", "ready": false, "expires_at": "2026-10-03T11:00:00Z" },
        { "embedding_id": "vox_emb_99mdAvteTpRBRBdW", "ready": false, "expires_at": "2026-10-03T11:00:00Z" }
      ]
    }
    ```

    La génération s'exécute en arrière-plan : les identifiants sont donc renvoyés avec `ready: false`.

    <Note>
      Chaque requête crée de nouveaux identifiants. Conservez-les. Pour retrouver des
      identifiants que vous n'avez pas conservés, listez vos candidats avec `GET /voice-generator/embeddings`.
    </Note>
  </Step>

  <Step title="Attendre qu'ils soient prêts">
    <CodeGroup>
      ```bash cURL theme={null}
      until curl -s -H "x-api-key: $GRADIUM_API_KEY" \
          "https://api.gradium.ai/api/voice-generator/embeddings?embedding_id=$CAND0" \
          | jq -e '.embeddings[0].ready' > /dev/null; do
        sleep 2
      done
      ```

      ```python Python theme={null}
      import time

      def wait_until_ready(embedding_id, timeout_s=120):
          deadline = time.monotonic() + timeout_s
          while time.monotonic() < deadline:
              resp = requests.get(
                  f"{BASE}/voice-generator/embeddings",
                  params={"embedding_id": embedding_id},
                  headers={"x-api-key": API_KEY},
              )
              resp.raise_for_status()
              found = resp.json()["embeddings"]
              if found and found[0]["ready"]:
                  return found[0]
              time.sleep(2)
          raise TimeoutError(embedding_id)

      for embedding_id in candidates:
          wait_until_ready(embedding_id)
      ```
    </CodeGroup>

    ```json 200 OK theme={null}
    {
      "embeddings": [{
        "embedding_id": "vox_emb_njsiEgpj5NjHKdZc",
        "ready": true,
        "prompt": "A British female voice, 20 to 30, ...",
        "language": "en",
        "created_at": "2026-09-03T11:00:00.968734",
        "expires_at": "2026-10-03T11:00:00.959626"
      }]
    }
    ```

    Trois candidats prennent généralement de trois à cinq secondes. Limitez la boucle à
    environ deux minutes et proposez de réessayer.

    Un identifiant inconnu renvoie `200` avec une liste `embeddings` vide, et non `404` :
    vérifiez donc la liste avant d'y accéder par index. Les horodatages sont en UTC, avec ou
    sans `Z` final.
  </Step>

  <Step title="Écouter un candidat">
    Passez l'identifiant du candidat comme `voice_id` sur l'endpoint de synthèse vocale habituel. Le
    préfixe `vox_emb_` permet à l'API de distinguer un candidat d'une voix convertie.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST https://api.gradium.ai/api/post/speech/tts \
        -H "x-api-key: $GRADIUM_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
          \"text\": \"Hi there, thanks so much for calling! How can I help you today?\",
          \"voice_id\": \"$CAND0\",
          \"model_name\": \"default\",
          \"output_format\": \"wav\",
          \"only_audio\": true
        }" --output candidate-0.wav
      ```

      ```python Python theme={null}
      resp = requests.post(
          f"{BASE}/post/speech/tts",
          json={
              "text": "Hi there, thanks so much for calling! How can I help you today?",
              "voice_id": candidates[0],
              "model_name": "default",
              "output_format": "wav",
              "only_audio": True,
          },
          headers={"x-api-key": API_KEY},
      )
      resp.raise_for_status()
      with open("candidate-0.wav", "wb") as f:
          f.write(resp.content)
      ```
    </CodeGroup>

    Le corps de la réponse est l'audio, en 48 kHz mono. Répétez l'opération pour les autres candidats.

    Les candidats sont soumis à trois restrictions qui ne s'appliquent pas aux voix converties :

    * Le texte est limité à 100 caractères (`400 input text too long`).
    * REST uniquement. Le WebSocket TTS et le Speech-to-Speech rejettent les identifiants de candidats avec l'erreur `1011`.
    * Un candidat qui n'est pas prêt, inconnu ou appartenant à un autre compte renvoie `404 Embedding not found`.

    <Tip>
      Écoutez les candidats avec le `model_name` et le `json_config` que vous utiliserez en production : la voix
      que vous validez sera ainsi celle que vous obtiendrez.
    </Tip>
  </Step>

  <Step title="Convertir le candidat en voix">
    Un candidat est un brouillon, supprimé 30 jours après sa génération. Le convertir
    crée une voix permanente dans votre bibliothèque.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST https://api.gradium.ai/api/voices/from-embedding \
        -H "x-api-key: $GRADIUM_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
          \"voxium_embedding_id\": \"$CAND0\",
          \"name\": \"Receptionist EN\",
          \"description\": \"Front desk and appointment booking\"
        }" > voice.json

      VOICE=$(jq -r '.uid' voice.json)
      ```

      ```python Python theme={null}
      resp = requests.post(
          f"{BASE}/voices/from-embedding",
          json={
              "voxium_embedding_id": candidates[0],
              "name": "Receptionist EN",
              "description": "Front desk and appointment booking",
          },
          headers={"x-api-key": API_KEY},
      )
      resp.raise_for_status()
      voice_id = resp.json()["uid"]
      ```
    </CodeGroup>

    ```json 201 Created theme={null}
    {
      "uid": "b0ntuVzgFdUGoSPc",
      "name": "Receptionist EN",
      "description": "Front desk and appointment booking",
      "filename": "vox_emb_njsiEgpj5NjHKdZc",
      "start_s": 0.0,
      "is_catalog": false,
      "is_pro_clone": false,
      "language": "en",
      "tags": []
    }
    ```

    `uid` est votre `voice_id` permanent. C'est celui-ci qu'il faut conserver. Il s'agit de la même
    valeur que `voxium_embedding_id` dans la requête et que `voice_id` partout ailleurs.

    * La conversion est gratuite. La voix occupe un emplacement de voix personnalisée, partagé avec les [clones de voix](/fr/guides/voices/custom-voices). Au-delà de votre quota : `409 Custom voice limit reached`.
    * Elle supprime la date d'expiration du candidat.
    * Convertir deux fois le même candidat : `409 A voice was already created from this embedding: <voice_id>`. Conservez vous-même la correspondance entre candidat et voix plutôt que d'analyser ce message.
    * Candidat pas prêt ou inconnu : `409 Embedding is not ready yet`.
  </Step>

  <Step title="Utiliser la voix">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST https://api.gradium.ai/api/post/speech/tts \
        -H "x-api-key: $GRADIUM_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
          \"text\": \"Good morning, and welcome to Northgate! Do you have an appointment with us today, or shall I get you booked in?\",
          \"voice_id\": \"$VOICE\",
          \"model_name\": \"default\",
          \"output_format\": \"wav\",
          \"only_audio\": true
        }" --output line-0.wav
      ```

      ```python Python theme={null}
      resp = requests.post(
          f"{BASE}/post/speech/tts",
          json={
              "text": (
                  "Good morning, and welcome to Northgate! Do you have an appointment "
                  "with us today, or shall I get you booked in?"
              ),
              "voice_id": voice_id,
              "model_name": "default",
              "output_format": "wav",
              "only_audio": True,
          },
          headers={"x-api-key": API_KEY},
      )
      resp.raise_for_status()
      with open("line-0.wav", "wb") as f:
          f.write(resp.content)
      ```
    </CodeGroup>

    Aucune limite de longueur ici. Le même `voice_id` fonctionne avec le
    [SDK Python](/fr/guides/text-to-speech), le
    [WebSocket TTS](/fr/api-reference/endpoint/tts-websocket) et le
    [Speech-to-Speech](/fr/guides/speech-to-speech).
  </Step>

  <Step title="Faire le ménage">
    Les candidats que vous ne convertissez pas sont supprimés au bout de 30 jours. Pour en supprimer un plus tôt :

    ```bash cURL theme={null}
    curl -s -X DELETE \
      -H "x-api-key: $GRADIUM_API_KEY" \
      "https://api.gradium.ai/api/voice-generator/embeddings/$CAND1"
    ```

    Sans risque à tout moment : une voix convertie conserve sa propre copie. Un identifiant déjà
    supprimé renvoie `404`.
  </Step>
</Steps>

## Exemple complet

L'ensemble du processus dans un seul fichier. Définissez `GRADIUM_API_KEY` et exécutez-le. Il crée une
vraie voix dans votre compte.

<CodeGroup>
  ```python voice_design.py theme={null}
  import os
  import time

  import requests

  BASE_URL = "https://api.gradium.ai/api"
  HEADERS = {"x-api-key": os.environ["GRADIUM_API_KEY"]}

  DESCRIPTION = (
      "A British female voice, 20 to 30, glossy and confident, with high pitch, "
      "fast pacing, high energy and bright sparkling resonance. Ideal for a "
      "friendly receptionist or assistant."
  )
  AUDITION_LINE = "Hi there, thanks so much for calling Northgate! How can I help you today?"


  def check(resp):
      if not resp.ok:
          raise RuntimeError(f"HTTP {resp.status_code}: {resp.text}")
      return resp


  def generate(prompt, language="en", n_samples=3, json_config=None):
      body = {"prompt": prompt, "language": language, "n_samples": n_samples}
      if json_config:
          body["json_config"] = json_config
      resp = check(requests.post(f"{BASE_URL}/voice-generator/generate", headers=HEADERS, json=body))
      return [c["embedding_id"] for c in resp.json()["embeddings"]]


  def wait_until_ready(candidate_ids, timeout_s=120.0):
      deadline = time.monotonic() + timeout_s
      pending = set(candidate_ids)
      while pending:
          for candidate_id in sorted(pending):
              resp = check(requests.get(
                  f"{BASE_URL}/voice-generator/embeddings",
                  headers=HEADERS,
                  params={"embedding_id": candidate_id},
              ))
              embeddings = resp.json()["embeddings"]
              if not embeddings:
                  raise RuntimeError(f"candidate {candidate_id} not found")
              if embeddings[0]["ready"]:
                  pending.discard(candidate_id)
          if pending:
              if time.monotonic() > deadline:
                  raise TimeoutError(f"still not ready: {sorted(pending)}")
              time.sleep(2.0)


  def synthesise(voice_id, text, path):
      resp = check(requests.post(
          f"{BASE_URL}/post/speech/tts",
          headers=HEADERS,
          json={"text": text, "voice_id": voice_id, "output_format": "wav", "only_audio": True},
      ))
      with open(path, "wb") as f:
          f.write(resp.content)


  def convert(candidate_id, name, description=None):
      resp = check(requests.post(
          f"{BASE_URL}/voices/from-embedding",
          headers=HEADERS,
          json={"voxium_embedding_id": candidate_id, "name": name, "description": description},
      ))
      return resp.json()["uid"]


  def delete_candidate(candidate_id):
      requests.delete(f"{BASE_URL}/voice-generator/embeddings/{candidate_id}", headers=HEADERS)


  if __name__ == "__main__":
      print("[1/5] generating candidates")
      candidate_ids = generate(DESCRIPTION, language="en", n_samples=3)

      print("[2/5] waiting until ready")
      wait_until_ready(candidate_ids)

      print("[3/5] auditioning")
      for i, candidate_id in enumerate(candidate_ids):
          synthesise(candidate_id, AUDITION_LINE, f"candidate-{i}.wav")
          print(f"      candidate-{i}.wav  {candidate_id}")

      # Listen to the files, then pick one. This example keeps the first.
      chosen = candidate_ids[0]

      print("[4/5] converting the chosen candidate into a voice")
      voice_id = convert(chosen, "Receptionist EN", "Front desk and appointment booking")
      print(f"      voice_id={voice_id}")

      print("[5/5] synthesising with the new voice")
      synthesise(
          voice_id,
          "Good morning, and welcome to Northgate! Do you have an appointment with us "
          "today, or shall I get you booked in?",
          "welcome.wav",
      )

      for candidate_id in candidate_ids:
          if candidate_id != chosen:
              delete_candidate(candidate_id)
      print("done")
  ```

  ```javascript voice_design.mjs theme={null}
  import { writeFile } from "node:fs/promises";

  const BASE_URL = "https://api.gradium.ai/api";
  const HEADERS = {
    "x-api-key": process.env.GRADIUM_API_KEY,
    "Content-Type": "application/json",
  };

  const DESCRIPTION =
    "A British female voice, 20 to 30, glossy and confident, with high pitch, " +
    "fast pacing, high energy and bright sparkling resonance. Ideal for a " +
    "friendly receptionist or assistant.";
  const AUDITION_LINE =
    "Hi there, thanks so much for calling Northgate! How can I help you today?";

  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

  async function check(resp) {
    if (!resp.ok) throw new Error(`HTTP ${resp.status}: ${await resp.text()}`);
    return resp;
  }

  async function generate(prompt, { language = "en", nSamples = 3, jsonConfig } = {}) {
    const body = { prompt, language, n_samples: nSamples };
    if (jsonConfig) body.json_config = jsonConfig;
    const resp = await check(
      await fetch(`${BASE_URL}/voice-generator/generate`, {
        method: "POST",
        headers: HEADERS,
        body: JSON.stringify(body),
      }),
    );
    return (await resp.json()).embeddings.map((c) => c.embedding_id);
  }

  async function waitUntilReady(ids, timeoutMs = 120_000) {
    const deadline = Date.now() + timeoutMs;
    const pending = new Set(ids);
    while (pending.size > 0) {
      for (const id of [...pending]) {
        const resp = await check(
          await fetch(`${BASE_URL}/voice-generator/embeddings?embedding_id=${id}`, {
            headers: HEADERS,
          }),
        );
        const { embeddings } = await resp.json();
        if (embeddings.length === 0) throw new Error(`candidate ${id} not found`);
        if (embeddings[0].ready) pending.delete(id);
      }
      if (pending.size > 0) {
        if (Date.now() > deadline) throw new Error(`still not ready: ${[...pending]}`);
        await sleep(2000);
      }
    }
  }

  async function synthesise(voiceId, text, path) {
    const resp = await check(
      await fetch(`${BASE_URL}/post/speech/tts`, {
        method: "POST",
        headers: HEADERS,
        body: JSON.stringify({ text, voice_id: voiceId, output_format: "wav", only_audio: true }),
      }),
    );
    await writeFile(path, Buffer.from(await resp.arrayBuffer()));
  }

  async function convert(candidateId, name, description) {
    const resp = await check(
      await fetch(`${BASE_URL}/voices/from-embedding`, {
        method: "POST",
        headers: HEADERS,
        body: JSON.stringify({ voxium_embedding_id: candidateId, name, description }),
      }),
    );
    return (await resp.json()).uid;
  }

  async function deleteCandidate(candidateId) {
    await fetch(`${BASE_URL}/voice-generator/embeddings/${candidateId}`, {
      method: "DELETE",
      headers: HEADERS,
    });
  }

  console.log("[1/5] generating candidates");
  const candidateIds = await generate(DESCRIPTION, { language: "en", nSamples: 3 });

  console.log("[2/5] waiting until ready");
  await waitUntilReady(candidateIds);

  console.log("[3/5] auditioning");
  for (const [i, candidateId] of candidateIds.entries()) {
    await synthesise(candidateId, AUDITION_LINE, `candidate-${i}.wav`);
    console.log(`      candidate-${i}.wav  ${candidateId}`);
  }

  // Listen to the files, then pick one. This example keeps the first.
  const chosen = candidateIds[0];

  console.log("[4/5] converting the chosen candidate into a voice");
  const voiceId = await convert(chosen, "Receptionist EN", "Front desk and appointment booking");
  console.log(`      voice_id=${voiceId}`);

  console.log("[5/5] synthesising with the new voice");
  await synthesise(
    voiceId,
    "Good morning, and welcome to Northgate! Do you have an appointment with us " +
      "today, or shall I get you booked in?",
    "welcome.wav",
  );

  for (const candidateId of candidateIds) {
    if (candidateId !== chosen) await deleteCandidate(candidateId);
  }
  console.log("done");
  ```
</CodeGroup>

<Note>
  L'audio est diffusé en streaming : les en-têtes WAV contiennent donc des longueurs fictives. Les lecteurs qui se fient à l'en-tête, comme le module `wave` de Python, indiquent une durée erronée. Réécrivez les tailles RIFF et `data` après l'enregistrement si cela compte pour vous.
</Note>

## Rédiger une description

La description est la seule entrée dont dispose le modèle. Il réagit aux attributs que
contiendrait une fiche de casting, et plus vous en nommez, plus le résultat est précis.

| Attribut | Exemples |
| - | - |
| Genre | féminin, masculin, androgyne |
| Âge | 20 à 30 ans, d'âge moyen, âgé |
| Accent ou origine | britannique, du sud des États-Unis, parisien, brésilien |
| Hauteur | aiguë, grave, médium |
| Débit | rapide, posé, sans hâte |
| Énergie | énergique, calme, retenue |
| Timbre et résonance | brillant, rocailleux, soufflé, résonance claire et pétillante, chaleureux |
| Registre et manière | assuré, bavardage enjoué, formel, complice |
| Usage prévu | un réceptionniste aimable, un narrateur de livres audio, un présentateur de journal télévisé |

Terminez par l'usage prévu. Il oriente l'interprétation et le registre, pas seulement la couleur
de la voix.

> A British female voice, 20 to 30, glossy and confident, with girly
> chatter, high pitch, fast pacing, high energy and bright sparkling
> resonance. Ideal for a friendly receptionist or assistant.

### Règles empiriques

* **Utilisez l'espace disponible.** Jusqu'à 500 caractères, tous utilisables. Des phrases complètes valent mieux qu'une liste d'adjectifs.
* **Décrivez la voix, pas le script.** Les mots à prononcer vont dans la phrase d'écoute.
* **Définissez `language` sur la langue que parlera la voix.** Ce paramètre façonne l'accent et l'interprétation, pas seulement les mots. Les accents régionaux restent à préciser dans la description : « de Bristol » ou « parisien » doit être écrit explicitement.
* **Le concret l'emporte sur l'appréciation.** « Voix grave, débit lent, timbre rocailleux » en dit plus au modèle que « une super voix de narrateur ».

### Exemples

| Voix | Langue | Conçue pour |
| :- | :- | :- |
| **Pirate** | Anglais, Bristol | Narration de personnage |
| **Fionn** | Anglais, Irlande | Service client |
| **Freya** | Anglais, Royaume-Uni | Réceptionniste |
| **Desmond** | Anglais, États-Unis | Narration longue |

Les descriptions telles qu'envoyées :

**Pirate**

> A gruff Bristolian English male pirate voice, 45 to 60, for game and character
> narration: weathered low pitch, gravelly timbre with heavy vocal fry, strong
> projection, at a steady, unhurried pace, boisterous and commanding energy.

**Fionn**

> An Irish English male voice, 40 to 55, for customer service: calm and crisp,
> with mid-low pitch, steady natural pacing, medium energy and warm rounded
> resonance. Ideal for reassuring walkthroughs, empathic de-escalation and
> complex IT support.

**Freya**

> A British female voice, 20 to 30, glossy and confident, with girly chatter,
> high pitch, fast pacing, high energy and bright sparkling resonance. Ideal for
> a friendly receptionist or assistant.

**Desmond**

> An American English male voice, 55 to 65: clean, deliberate and precise, with
> low pitch, slow pacing and low-to-mid energy, resonant timbre and a gentle
> low-to-high flow. Ideal for projecting academic authority.

### Itérer

Modifiez l'attribut qui ne convient pas plutôt que de réécrire la description.

| Les candidats semblent... | Modification |
| - | - |
| Trop jeunes ou trop âgés | Une tranche explicite : « 40 à 55 ans » plutôt que « d'âge moyen » |
| Trop rapides ou trop lents | « sans hâte », « posé » ou « débit rapide » |
| Plats | Un mot sur l'énergie et un mot sur la manière |
| Trop lisses | Un mot sur le timbre : « rocailleux », « soufflé », « usé » |
| Bonne voix, mauvaise interprétation | Une mention de l'usage prévu à la fin |
| Incohérents entre eux | Un [`cfg_scale`](#cfg_scale) plus élevé |

### Intégrer Voice Design dans un produit

Si vous proposez la conception de voix à vos propres utilisateurs, préremplissez un formulaire avec les
attributs ci-dessus et composez la phrase à partir de celui-ci, avec une zone de texte libre comme
solution de repli. Affichez la limite de 500 caractères. Proposez « garder celle-ci » comme moyen de
conserver une voix, et faites en sorte que « régénérer » envoie une nouvelle description plutôt que davantage
d'échantillons.

## Paramètres de génération

Les paramètres de génération façonnent la voix et se placent dans `json_config` sur
`POST /voice-generator/generate`. Les [paramètres de synthèse](#paramètres-de-synthèse)
façonnent chaque énoncé et se placent dans `json_config` sur la requête TTS. Voice Design
prend toujours en charge `cfg_scale` pour contrôler à quel point la voix suit littéralement votre
description.

Tous les paramètres de génération sont facultatifs. Les valeurs par défaut sont optimisées : n'envoyez que les
clés que vous avez une raison de modifier.

```json theme={null}
{
  "prompt": "A calm Irish male voice, 40 to 55, warm and steady, for customer support.",
  "language": "en",
  "n_samples": 3,
  "json_config": { "cfg_scale": 8.0 }
}
```

| Clé | Plage | Valeur par défaut | Effet |
| - | - | - | - |
| `cfg_scale` | `1.0` à `20.0` | `5.0` | Fidélité de la voix à la description. Plus la valeur est élevée, plus le résultat est littéral et moins il est varié. |

### `cfg_scale`

* **`5.0`**, la valeur par défaut, pour explorer avec 3 à 5 candidats lorsque vous voulez qu'ils diffèrent.
* **`8.0` à `12.0`** lorsque les candidats s'éloignent de la description, ou lorsque vous générez un seul candidat à la fois. Les assistants de conception conversationnels qui génèrent un candidat par tour utilisent généralement `10.0`.
* **Au-delà de `12.0`**, la voix suit la description de plus en plus littéralement au détriment du naturel, et les candidats convergent les uns vers les autres.

`cfg_scale` ne peut pas ajouter un attribut que la description ne mentionne pas. Corrigez d'abord la
[description](#rédiger-une-description).

### La liste des clés autorisées dans `json_config`

<Warning>
  N'envoyez que `cfg_scale`. **Une clé inconnue ou une valeur hors plage n'est pas rejetée.** La requête renvoie `201` et les candidats ne passent jamais à `ready`. Limitez votre boucle d'interrogation et traitez un dépassement de délai comme une requête invalide.

  Causes habituelles : un paramètre de synthèse comme `temp`, ou un `cfg_scale` hors de sa plage.
</Warning>

## Paramètres de synthèse

Écouter un candidat ou synthétiser avec une voix convertie est une requête TTS
ordinaire : tout ce qui figure dans [Paramètres de voix](/fr/guides/voice-settings) s'applique donc.
Consultez [Choix du modèle](/fr/guides/text-to-speech#choix-du-modèle) pour l'accès aux modèles TTS.

<Callout color="#DC2626">
  **Obsolète : `cfg_coef` pour le TTS**

  Le nouveau modèle TTS ignore `cfg_coef` lors de la synthèse avec une voix conçue. Supprimez-le
  de vos requêtes TTS. `cfg_scale` s'applique toujours lors de la génération de la voix.
</Callout>

```json theme={null}
{
  "text": "Hi there, thanks so much for calling Northgate!",
  "voice_id": "vox_emb_njsiEgpj5NjHKdZc",
  "output_format": "wav",
  "only_audio": true,
  "json_config": { "temp": 0.5 }
}
```

### Température (`temp`)

`0.0` à `1.4`, valeur par défaut `0.7`.

* **Écoutez les candidats avec la valeur par défaut.** `0.0` rend une voix vive plus plate qu'elle ne le sera en production.
* **`0.3` à `0.5`** pour une production scénarisée à fort volume où les prises doivent être identiques : messages de SVI, annonces fixes.
* **Valeur par défaut ou légèrement au-dessus** pour les agents conversationnels et la narration.

## Balises prises en charge

Les modèles lisent du texte brut. Deux balises en ligne sont reconnues, aussi bien sur les candidats que
sur les voix converties. **Tout le reste est prononcé à voix haute comme du texte.**

| Balise | Effet |
| - | - |
| `<break time="1.5s" />` | Une pause de `0.1` à `2.0` secondes. Entourez la balise d'espaces. |
| `<flush>` | Émet l'audio de tout le texte reçu jusque-là. N'a de sens qu'en streaming sur le WebSocket. |

Sur un candidat, les balises comptent dans la limite de 100 caractères.

### Non pris en charge

Le SSML n'est pas interprété. `<speak><prosody rate="slow">Hello there.</prosody></speak>`
produit une voix qui dit « speak prosody rate slow, hello there, slash prosody,
slash speak ». Utilisez plutôt :

| Au lieu de | Utilisez |
| - | - |
| `<prosody rate>` | `padding_bonus`, voir [Contrôle de la vitesse](/fr/guides/voice-settings#contrôle-de-la-vitesse) |
| `<prosody pitch>`, `<prosody volume>` | La description. La hauteur et l'énergie sont des attributs de la voix. |
| `<emphasis>` | La ponctuation et la structure des phrases |
| `<say-as>`, `<sub>`, `<phoneme>` | [`rewrite_rules`](/fr/guides/text-rewriting) ou un [dictionnaire de prononciation](/fr/api-reference/endpoint/create-pronunciation) |
| `<voice>` | Une requête distincte avec un autre `voice_id` |

Le Markdown et le HTML sont eux aussi lus comme du texte. Retirez la mise en forme avant l'envoi.

## Cycle de vie des candidats

| | |
| - | - |
| **Conservation** | Les candidats sont supprimés 30 jours après leur génération. La conversion d'un candidat supprime sa date d'expiration. |
| **Accumulation** | Une génération n'évince jamais les candidats précédents. Les conserver est gratuit. |
| **Nettoyage** | `DELETE /voice-generator/embeddings/{embedding_id}`. Toujours sans risque : une voix convertie conserve sa propre copie. Identifiant inconnu : `404`. |
| **Supprimer une voix** | `DELETE /voices/{voice_id}` laisse le candidat intact, sans date d'expiration. Il peut être converti à nouveau. |
| **Identifiant perdu** | `GET /voice-generator/embeddings` liste tous les candidats, du plus récent au plus ancien, avec leur description. Paginez avec `skip` et `limit` (1 à 1000, 100 par défaut). `expires_at: null` signale les candidats convertis. |

## Limites

| Limite | Valeur |
| - | - |
| Description | 1 à 500 caractères |
| Candidats par requête | 1 à 5, 1 par défaut |
| Texte d'écoute | 100 caractères, REST uniquement |
| Langues | `en`, `fr`, `es`, `pt`, `de` |
| Conservation des candidats | 30 jours, levée après conversion |
| Voix converties | Décomptées du quota de voix personnalisées |

## Erreurs

Les erreurs ont la forme `{"detail": "..."}`, sauf `422`, qui contient une liste d'erreurs par champ.

| Statut | Où | Signification |
| - | - | - |
| `400` | Écoute | Texte de plus de 100 caractères |
| `401` | Partout | Clé API invalide ou expirée |
| `404` | Écoute, suppression | Identifiant inconnu, pas prêt ou appartenant à un autre compte |
| `409` | Conversion | Déjà converti, pas prêt, ou quota de voix personnalisées atteint. `detail` précise lequel. |
| `422` | Génération, liste | `language`, `n_samples`, `prompt` ou `limit` invalide |

Un candidat qui ne devient jamais prêt est presque toujours dû à une valeur de `json_config` hors
plage ou à une clé que l'API ne reconnaît pas. Consultez [la
liste des clés autorisées](#la-liste-des-clés-autorisées-dans-json_config).

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Voice Localization" icon="language" href="/fr/guides/voices/voice-localization">
    Faites parler un candidat ou une voix convertie dans une autre langue ou avec un autre accent.
  </Card>

  <Card title="Gérer les voix" icon="sliders" href="/fr/guides/voices/manage-voices">
    Listez, modifiez et supprimez les voix que vous convertissez.
  </Card>

  <Card title="Paramètres de voix" icon="sliders-up" href="/fr/guides/voice-settings">
    Vitesse, température et autres options de synthèse.
  </Card>

  <Card title="Synthèse vocale en streaming" icon="waveform-lines" href="/fr/guides/text-to-speech">
    Utilisez votre nouvelle voix sur le WebSocket à faible latence.
  </Card>

  <Card title="Référence de l'API" icon="code" href="/fr/api-reference/endpoint/generate-voice">
    Tous les endpoints de Voice Design en détail.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.