> ## 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 Enhance

> Améliorez une voix existante, sans changer sa langue ni la personne qui parle

Voice Enhance part d'une voix existante (une voix phare, un clone ou une voix
créée avec Voice Design) et produit des candidats plus propres du même locuteur,
dans la même langue. Un clone issu d'un enregistrement bruité revient avec un
bruit de fond réduit et une cible de qualité appliquée ; le locuteur, la langue
et le débit sont conservés. Vous écoutez les candidats, convertissez celui qui
vous plaît, et il fonctionne comme n'importe quel autre `voice_id` : REST,
WebSocket et Speech-to-Speech.

<Tip>
  Comparez chaque candidat à sa source avant de le convertir.
</Tip>

<CardGroup cols={2}>
  <Card title="Vous partez d'un enregistrement ?" icon="microphone" href="/fr/guides/voices/custom-voices">
    Clonez d'abord le locuteur, puis améliorez le clone.
  </Card>

  <Card title="Vous partez d'une description ?" icon="wand-magic-sparkles" href="/fr/guides/voices/voice-design">
    Voice Design crée une nouvelle voix à partir de mots. Enhance améliore une voix que vous avez déjà.
  </Card>
</CardGroup>

## Fonctionnement

<CardGroup cols={2}>
  <Card title="1. Choisir une source" icon="user">
    Une voix phare, l'un de vos clones ou un candidat Voice Design.
  </Card>

  <Card title="2. Améliorer" icon="sparkles">
    Une seule requête, aucun autre réglage. Les candidats sont prêts en une vingtaine de secondes.
  </Card>

  <Card title="3. Écouter" icon="headphones">
    Comparez chaque candidat à la source sur la même phrase en synthèse vocale.
  </Card>

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

La source n'est jamais modifiée. Chaque requête crée `n_samples` nouveaux
candidats, des brouillons dotés d'un identifiant `vox_emb_`, exactement comme
les candidats Voice Design : vous les écoutez via `POST /post/speech/tts`, les
convertissez avec `POST /voices/from-embedding`, et ils expirent au bout de
30 jours s'ils ne sont pas convertis.

## Accès

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

| Appel | Endpoint |
| :- | :- |
| Améliorer une voix | `POST /voice-generator/enhance` |
| 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

L'exemple améliore un clone français. Remplacez `$SOURCE` par n'importe quel
identifiant de voix ou de candidat qui vous appartient, ou par l'identifiant
d'une voix phare.

<Steps>
  <Step title="Améliorer la voix">
    <CodeGroup>
      ```bash cURL theme={null}
      curl -s -X POST https://api.gradium.ai/api/voice-generator/enhance \
        -H "x-api-key: $GRADIUM_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
          \"src_voice\": \"$SOURCE\",
          \"n_samples\": 2
        }" > candidates.json

      CAND0=$(jq -r '.embeddings[0].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"
      SOURCE = os.environ["SOURCE"]  # a voice id or a vox_emb_ candidate id

      resp = requests.post(
          f"{BASE}/voice-generator/enhance",
          json={"src_voice": SOURCE, "n_samples": 2},
          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_XeBcXDgoigTfL9Cv", "ready": false, "expires_at": "2026-10-21T13:03:52Z" },
        { "embedding_id": "vox_emb_ni8lehVHTb35siXI", "ready": false, "expires_at": "2026-10-21T13:03:53Z" }
      ]
    }
    ```

    | Champ | | |
    | :- | :- | :- |
    | `src_voice` | obligatoire | Un identifiant de voix (votre clone, un candidat converti ou une voix phare) ou un identifiant de candidat `vox_emb_`. |
    | `n_samples` | facultatif | De 1 à 5 candidats, 1 par défaut. |

    Il n'y a rien d'autre à régler : la langue vient de la voix source, tout
    comme le locuteur. La requête est vérifiée avant toute mise en file
    d'attente : une source inconnue ou une source qui ne peut pas être améliorée
    échoue dès cette étape avec `404` ou `409`, et rien n'est facturé.
  </Step>

  <Step title="Attendre les candidats">
    <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_XeBcXDgoigTfL9Cv",
        "ready": true,
        "kind": "enhance",
        "language": "fr",
        "created_at": "2026-09-21T13:03:52.591128",
        "expires_at": "2026-10-21T13:03:52.495534",
        "enhance_config": {
          "src_voice": "H5oin0KHqRTAxaeL",
          "src_language": "fr"
        },
        "prompt": null
      }]
    }
    ```

    Les candidats améliorés sont généralement prêts en quinze à vingt secondes.
    Dans la liste, `kind` vaut `enhance` et `enhance_config` contient
    l'identifiant de la source et sa langue. `language` est la langue de la voix
    source, que le candidat conserve. `prompt` est vide pour un candidat amélioré.
  </Step>

  <Step title="Écouter un candidat">
    Passez l'identifiant du candidat comme `voice_id` sur l'endpoint de synthèse
    vocale, avec un texte dans la langue de la voix. Synthétisez aussi la même
    phrase avec la voix source : la différence entre les deux fichiers
    correspond à ce qu'a fait Enhance.

    <CodeGroup>
      ```bash cURL theme={null}
      for VOICE in "$CAND0" "$SOURCE"; do
        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\": \"Bonjour, c'est Constance. Même voix, un peu plus propre, j'espère.\",
            \"voice_id\": \"$VOICE\",
            \"model_name\": \"default\",
            \"output_format\": \"wav\",
            \"only_audio\": true
          }" --output "$VOICE.wav"
      done
      ```

      ```python Python theme={null}
      LINE = "Bonjour, c'est Constance. Même voix, un peu plus propre, j'espère."

      for voice_id, path in [(candidates[0], "candidate-0.wav"), (SOURCE, "source.wav")]:
          resp = requests.post(
              f"{BASE}/post/speech/tts",
              json={
                  "text": LINE,
                  "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(path, "wb") as f:
              f.write(resp.content)
      ```
    </CodeGroup>

    Les candidats sont soumis aux mêmes restrictions que les candidats Voice
    Design : REST uniquement, texte d'écoute plafonné, et une erreur opaque
    `404 Embedding not found` tant qu'ils ne sont pas prêts.
  </Step>

  <Step title="Convertir le candidat en voix">
    <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\": \"Constance (enhanced)\",
          \"description\": \"French support voice, enhanced\"
        }" > 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": "Constance (enhanced)",
              "description": "French support voice, enhanced",
          },
          headers={"x-api-key": API_KEY},
      )
      resp.raise_for_status()
      voice_id = resp.json()["uid"]
      ```
    </CodeGroup>

    ```json 201 Created theme={null}
    {
      "uid": "w0F73K2fcf3X2Vcn",
      "name": "Constance (enhanced)",
      "description": "French support voice, enhanced",
      "filename": "vox_emb_XeBcXDgoigTfL9Cv",
      "start_s": 0.0,
      "is_catalog": false,
      "is_pro_clone": false,
      "language": "fr",
      "tags": []
    }
    ```

    `uid` est votre `voice_id` permanent. Conservez-le. La nouvelle voix garde
    la `language` de la source. La conversion est gratuite, occupe un
    emplacement de voix personnalisée et supprime l'expiration du candidat. Les
    candidats issus d'une même requête sont des variations : si l'un d'eux vous
    plaît, convertissez-le plutôt que de relancer la requête. La voix source
    n'est pas modifiée : vous pouvez donc conserver les deux, ou supprimer la
    source une fois satisfait de la version améliorée.
  </Step>
</Steps>

## Exemple complet

Définissez `GRADIUM_API_KEY` et `SOURCE`, puis lancez le script. Il crée une
vraie voix dans votre compte.

```python voice_enhance.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"]}
SOURCE = os.environ["SOURCE"]
LINE = "Hi, this is your assistant. How can I help you today?"  # in the source voice's language
N_SAMPLES = 3


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


def enhance(src_voice, n_samples=1):
    resp = check(requests.post(
        f"{BASE_URL}/voice-generator/enhance",
        headers=HEADERS,
        json={"src_voice": src_voice, "n_samples": n_samples},
    ))
    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"]


if __name__ == "__main__":
    print("[1/4] enhancing")
    candidates = enhance(SOURCE, N_SAMPLES)

    print("[2/4] waiting until ready")
    wait_until_ready(candidates)

    print("[3/4] auditioning")
    synthesise(SOURCE, LINE, "source.wav")  # the same line without enhancement
    for i, candidate_id in enumerate(candidates):
        synthesise(candidate_id, LINE, f"candidate-{i}.wav")
        print(f"      candidate-{i}.wav vs source.wav")

    # Listen, then convert the one you keep. This example keeps the first.
    print("[4/4] converting")
    voice_id = convert(candidates[0], "Assistant (enhanced)", f"Enhanced from {SOURCE}")
    print(f"      voice_id={voice_id}")
    print("done")
```

## Sources compatibles

| Source | Compatible | Remarques |
| :- | :- | :- |
| Voix phare | Oui | N'importe quel identifiant des [voix phares](/fr/guides/voices/flagship-voices). |
| Clone instantané | Oui, s'il a une langue | Les clones créés sans `language` renvoient `409 The source voice has no language`. Définissez-la une fois avec [`PUT /voices/{voice_id}`](/fr/guides/voices/manage-voices#modifier-une-voix) et réessayez. La langue doit être celle parlée dans l'enregistrement : une mauvaise étiquette est acceptée mais dégrade discrètement le résultat. |
| Candidat ou voix convertie issus de Voice Design | Oui | Utilisez l'identifiant `vox_emb_` ou le `voice_id` converti. |
| Candidat amélioré | Oui | Le candidat doit être prêt (`409` sinon). |
| Clone pro | Non | `409 This voice has no embedding the voice generator can edit.` |
| Voix d'un autre compte | Non | `404` opaque. |

## Conseils issus de nos tests

* **Comparez avec la source lisant le même texte.** Enhance change la façon
  dont la voix sonne, pas ce qu'elle dit ni la langue dans laquelle elle parle.
  Placez la source et le candidat côte à côte dans votre interface de
  validation, sur la même phrase.
* **Commencez par un clone.** Les voix phares sont déjà produites à partir
  d'enregistrements propres ; le clone que vous aimeriez entendre plus propre
  est la source naturelle.
* **Les candidats varient.** Cinq échantillons issus d'une requête, ou cinq
  requêtes distinctes, donnent cinq résultats légèrement différents.
  Convertissez celui qui vous plaît ; ne comptez pas sur une nouvelle exécution
  pour le reproduire.
* **Conservez la source.** Convertir un candidat ne remplace pas la voix
  source. Basculez votre `voice_id` une fois que vous avez écouté, et supprimez
  l'ancienne voix lorsque vous n'en avez plus besoin.
* **Prévoyez l'attente.** Les candidats améliorés prennent quinze à vingt
  secondes, plus que les candidats Voice Design. Interrogez régulièrement leur
  état plutôt que de bloquer une requête dessus.

## Cycle de vie des candidats

Les candidats améliorés suivent le [cycle de vie des candidats Voice
Design](/fr/guides/voices/voice-design#cycle-de-vie-des-candidats) : conservation de
30 jours, levée à la conversion, et `DELETE /voice-generator/embeddings/{embedding_id}`
pour en supprimer un plus tôt. Supprimer la voix ou le candidat source après le
`201` ne fait jamais échouer la requête : chaque candidat conserve sa propre
copie de la source.

## Limites

| Limite | Valeur |
| - | - |
| Candidats par requête | De 1 à 5, 1 par défaut |
| Langues | La langue de la voix source : `en`, `fr`, `es`, `pt` ou `de` |
| Texte d'écoute | REST uniquement, même plafond que pour les candidats Voice Design |
| Conservation des candidats | 30 jours, levée une fois le candidat converti |
| Voix converties | Décomptées du quota de voix personnalisées |

## Erreurs

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

| Statut | Où | Signification |
| - | - | - |
| `401` | Partout | Clé API invalide ou expirée |
| `404` | Enhance | Source inconnue, ou voix ou candidat d'un autre compte |
| `404` | Écoute | Candidat pas encore prêt, inconnu ou supprimé |
| `409` | Enhance | La source n'a pas de langue, la source est un candidat qui n'est pas prêt, ou la source est un clone pro. `detail` précise le cas. |
| `409` | Conversion | Déjà converti, pas prêt, ou quota de voix personnalisées atteint |
| `422` | Enhance | `n_samples` invalide, ou `src_voice` vide |
| `503` | Enhance | L'audio source n'a pas pu être copié, ou aucun générateur de voix n'est disponible. Réessayez. |

## Étapes suivantes

<CardGroup cols={2}>
  <Card title="Voix personnalisées" icon="microphone" href="/fr/guides/voices/custom-voices">
    Clonez un locuteur, avec une langue, afin que le clone puisse être amélioré.
  </Card>

  <Card title="Voice Design" icon="wand-magic-sparkles" href="/fr/guides/voices/voice-design">
    Créez plutôt une voix à partir d'une description.
  </Card>

  <Card title="Gérer les voix" icon="sliders" href="/fr/guides/voices/manage-voices">
    Définissez une langue sur un ancien clone, listez et supprimez des voix.
  </Card>

  <Card title="Référence API" icon="code" href="/fr/api-reference/endpoint/enhance-voice">
    L'endpoint enhance dans son intégralité.
  </Card>
</CardGroup>


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