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

# Clone a voice and speak with it

> Create a custom voice from a short, clean speech sample with the AudioPod Python or Node SDK, then use it for text to speech in the same script.

**What you get:** a custom voice in your account, with an id you can pass to text to speech, the voice changer and audiobook narration.

**Input:** a short recording of one person speaking with no music or background noise. A clean 10–30 second sample works best.

<Warning>
  Only clone your own voice, or a voice whose speaker has given you explicit permission. Do not clone a public figure or anyone else without their consent. See [voice consent](https://audiopod.ai/voice-consent).
</Warning>

## 1. Install and set your key

<CodeGroup>
  ```bash Python theme={null}
  pip install audiopod
  export AUDIOPOD_API_KEY="ap_..."
  ```

  ```bash Node theme={null}
  npm install audiopod
  export AUDIOPOD_API_KEY="ap_..."
  ```
</CodeGroup>

## 2. Clone, wait until it's ready, then speak

A new voice starts as `PENDING` while it is processed, and text to speech with it fails until its status is `COMPLETED`. Wait for it before the first speech request:

<CodeGroup>
  ```python Python theme={null}
  from audiopod import Client

  client = Client()

  voice = client.voice.create_voice(
      name="My Voice",
      audio_file="sample.wav",
      description="Warm, mid-pitched narrator",
      wait_for_ready=True,  # returns once the voice is COMPLETED
  )

  job = client.voice.generate_speech(
      voice_id=voice["id"],
      text="This sentence was never recorded. It is my cloned voice.",
      wait_for_completion=True,
  )
  print(job["output_url"])
  ```

  ```typescript Node theme={null}
  import AudioPod from "audiopod";

  const client = new AudioPod();

  const voice = await client.voice.create({
    name: "My Voice",
    audioFile: "./sample.wav",
    description: "Warm, mid-pitched narrator",
    waitForReady: true, // resolves once the voice is COMPLETED
  });

  const job = await client.voice.generate({
    text: "This sentence was never recorded. It is my cloned voice.",
    voiceId: voice.id,
  });
  console.log(job.output_url);
  ```
</CodeGroup>

`wait_for_ready` / `waitForReady` raise an error with the reason if cloning fails, and after `timeout` (300 seconds by default) if it is still processing.

<Note>
  `wait_for_ready` and `waitForReady` arrive in the next release of both SDKs (after 2.10.1). On 2.10.1 or earlier, poll the voice status yourself before speaking:

  <CodeGroup>
    ```python Python theme={null}
    import time

    voice = client.voice.create_voice(name="My Voice", audio_file="sample.wav")
    deadline = time.monotonic() + 300  # give up after 5 minutes
    while True:
        status = client.voice.get_voice(voice["id"])["status"]
        if status == "COMPLETED":
            break
        if status in ("FAILED", "CANCELLED"):
            raise RuntimeError(f"Voice cloning {status.lower()}")
        if time.monotonic() > deadline:
            raise TimeoutError(f"Voice {voice['id']} still {status} after 5 minutes")
        time.sleep(3)
    ```

    ```typescript Node theme={null}
    const voice = await client.voice.create({ name: "My Voice", audioFile: "./sample.wav" });
    const deadline = Date.now() + 300_000; // give up after 5 minutes
    for (;;) {
      const { status } = (await client.voice.get(voice.id)) as { status?: string };
      if (status === "COMPLETED") break;
      if (status === "FAILED" || status === "CANCELLED") throw new Error(`Voice cloning ${status}`);
      if (Date.now() > deadline) throw new Error(`Voice ${voice.id} still ${status} after 5 minutes`);
      await new Promise((resolve) => setTimeout(resolve, 3000));
    }
    ```
  </CodeGroup>

  Over plain HTTP, poll `GET /api/v1/voice/voices/{id}/status` until `status` is `COMPLETED`.
</Note>

## Tips

* Record in a quiet room with the microphone at a steady distance. Run a noisy sample through [noise reduction](/quickstarts/noise-reduction) first.
* Custom voices count against your plan's voice slots. See [pricing](https://audiopod.ai/pricing).
* Remove a voice with `client.voice.delete_voice(id)` (Python) or `client.voice.delete(id)` (Node).
* Change who is speaking in an existing recording with the [voice changer](/api-reference/voice-changer), using the same voice id.

## From an AI agent

On the full MCP endpoint (`https://mcp.audiopod.ai`, see [AudioPod for AI agents](/agents)) ask: *"Clone my voice from [https://example.com/my-voice.wav](https://example.com/my-voice.wav) and name it 'Me'. It's my own voice."* The `clone_voice` tool requires the agent to confirm consent (`consent_confirmed: true`) before anything is created, so expect it to ask you first.

Full endpoint reference: [Voice Management](/api-reference/voice-management).


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