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

# Training Custom Voices

> Learn how to create and train your own custom voice models using the VoiceDub API

Create your own custom voice models by training on audio samples. Perfect for businesses wanting branded voices, content creators building character libraries, or developers creating unique voice applications.

## Overview

Training a custom voice involves three main steps:

<Steps>
  <Step title="Create the voice">
    Initialize a new voice model with your training parameters
  </Step>

  <Step title="Upload training audio">
    Provide high-quality audio samples for the voice to learn from
  </Step>

  <Step title="Start training">
    Begin the AI training process to create your custom voice model
  </Step>
</Steps>

<Info>
  Custom voice training consumes **10 API credits per minute** of training time (specified by `maxMinutes`). Choose your training duration wisely.
</Info>

## Step 1: Create a Voice Model

Start by creating a new voice with your desired training parameters:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://api.voicedub.ai/v1/me/voices' \
    -H 'Authorization: Api-Key YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "name": "My Custom Voice",
      "maxMinutes": 10,
      "separate": true,
      "numberOfFiles": 3
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.voicedub.ai/v1/me/voices', {
    method: 'POST',
    headers: {
      'Authorization': 'Api-Key YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: "My Custom Voice",
      maxMinutes: 10,
      separate: true,
      numberOfFiles: 3
    })
  });

  const data = await response.json();
  console.log('Voice created:', data.voice.id);
  ```

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

  response = requests.post('https://api.voicedub.ai/v1/me/voices',
    headers={
      'Authorization': 'Api-Key YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    json={
      'name': "My Custom Voice",
      'maxMinutes': 10,
      'separate': True,
      'numberOfFiles': 3
    }
  )

  data = response.json()
  print('Voice created:', data['voice']['id'])
  ```
</CodeGroup>

<Accordion title="Show Response">
  ```json theme={null}
  {
    "voice": {
      "id": "789e0123-e89b-12d3-a456-426614174000",
      "name": "My Custom Voice",
      "status": "new",
      "separate": true,
      "maxMinutes": 10,
      "requiredCredits": 100,
      "createdAt": "2024-01-15T10:00:00.000Z",
      ...
    },
    "uploadUrls": [
      "https://s3.amazonaws.com/bucket/models/.../vocals/file_0?signature=...",
      "https://s3.amazonaws.com/bucket/models/.../vocals/file_1?signature=...",
      "https://s3.amazonaws.com/bucket/models/.../vocals/file_2?signature=..."
    ]
  }
  ```
</Accordion>

### Parameters Explained

<ParamField body="name" type="string" required>
  Display name for your voice model (1-50 characters). Choose something descriptive and unique.
</ParamField>

<ParamField body="numberOfFiles" type="integer" required>
  Number of audio files to upload for training (1-5). More diverse files typically yield better results.
</ParamField>

<ParamField body="maxMinutes" type="integer" default={10}>
  Maximum duration of training audio in minutes (5-60). More training data generally produces better quality, but costs more credits.
</ParamField>

<ParamField body="separate" type="boolean" default={true}>
  Whether to use vocal separation during training. Set to `false` if your training audio already contains isolated vocals.
</ParamField>

## Step 2: Upload Training Audio

Use the provided upload URLs to upload your training audio files:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT 'UPLOAD_URL_FROM_RESPONSE' \
    -H 'Content-Type: audio/mpeg' \
    --data-binary @training-audio-1.mp3
  ```

  ```javascript Node.js theme={null}
  const fs = require('fs');
  const fileData = fs.readFileSync('training-audio-1.mp3');

  const response = await fetch('UPLOAD_URL_FROM_RESPONSE', {
    method: 'PUT',
    headers: {
      'Content-Type': 'audio/mpeg'
    },
    body: fileData
  });

  console.log('Training file uploaded successfully');
  ```

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

  with open('training-audio-1.mp3', 'rb') as f:
      response = requests.put('UPLOAD_URL_FROM_RESPONSE',
        headers={'Content-Type': 'audio/mpeg'},
        data=f.read()
      )

  print('Training file uploaded successfully')
  ```
</CodeGroup>

Repeat this for each training file. The training won't start until all files are uploaded.

### Training Audio Guidelines

<Tip>
  Follow these guidelines for best training results:
</Tip>

**Audio Quality:**

* Use high-quality recordings (192kbps+ MP3 or lossless formats)
* A total of 3–5 minutes works well, but longer files (up to 20 minutes) are also supported
* Minimize background noise and reverb
* Ensure consistent audio levels across files
* Avoid heavily processed or auto-tuned vocals

**Content Variety:**

* Include diverse vocal expressions (soft, loud, emotional)
* Mix different tempos and rhythms
* Include both sustained notes and quick phrases
* Vary pitch range throughout the samples

**Technical Requirements:**

* Each file: 1-20 minutes duration
* Total training duration: Up to your specified `maxMinutes`
* Supported formats: MP3, WAV, M4A, FLAC, OGG
* Video files are supported (audio will be extracted)

<Warning>
  Only use audio you have legal rights to. Training on copyrighted material without permission is prohibited.
</Warning>

## Step 3: Start Training

Once all files are uploaded, start the training process:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000/clone' \
    -H 'Authorization: Api-Key YOUR_API_KEY'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000/clone', {
    method: 'POST',
    headers: {
      'Authorization': 'Api-Key YOUR_API_KEY'
    }
  });

  const data = await response.json();
  console.log('Training started:', data.voice.status);
  ```

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

  response = requests.post('https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000/clone',
    headers={
      'Authorization': 'Api-Key YOUR_API_KEY'
    }
  )

  data = response.json()
  print('Training started:', data['voice']['status'])
  ```
</CodeGroup>

<Accordion title="Show Response">
  ```json theme={null}
  {
    "voice": {
      "id": "789e0123-e89b-12d3-a456-426614174000",
      "status": "queued",
      "apiCreditsUsed": 100,
      "apiCreditsLeft": 900,
      ...
    }
  }
  ```
</Accordion>

## Step 4: Monitor Training Progress

Poll the voice status to track training progress:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET 'https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000' \
    -H 'Authorization: Api-Key YOUR_API_KEY'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000', {
    headers: {
      'Authorization': 'Api-Key YOUR_API_KEY'
    }
  });

  const data = await response.json();
  console.log('Training status:', data.voice.status);
  ```

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

  response = requests.get('https://api.voicedub.ai/v1/me/voices/789e0123-e89b-12d3-a456-426614174000',
    headers={
      'Authorization': 'Api-Key YOUR_API_KEY'
    }
  )

  data = response.json()
  print('Training status:', data['voice']['status'])
  ```
</CodeGroup>

<Accordion title="Show Response">
  ```json theme={null}
  {
    "voice": {
      "id": "789e0123-e89b-12d3-a456-426614174000",
      "name": "My Custom Voice",
      "status": "training",
      "maxMinutes": 10,
      "apiCreditsUsed": 100,
      ...
    }
  }
  ```
</Accordion>

### Status Values

* `new` - Voice created, waiting for file uploads
* `queued` - All files uploaded, waiting in training queue
* `starting` - Training initialization beginning
* `processing` - AI model training in progress
* `finalizing` - Completing training and validating model
* `done` - Training complete! Voice ready for use
* `error` - Training failed (check `errorMessage`)

<Info>
  Training typically takes up to `maxMinutes` +  setup time (a couple minutes) depending on the amount of training audio, but can be higher based on current queue load.
</Info>

<Warning>
  Poll the voice status **maximum once every 3 seconds** to avoid rate limiting.
</Warning>

## Step 5: Use Your Trained Voice

Once training is complete (`status: "done"`), your voice is ready for dubbing:

<Accordion title="Show Response (when complete)">
  ```json theme={null}
  {
    "voice": {
      "id": "789e0123-e89b-12d3-a456-426614174000",
      "name": "My Custom Voice", 
      "status": "done",
      "completedAt": "2024-01-15T11:30:00.000Z",
      "apiCreditsUsed": 100,
      ...
    }
  }
  ```
</Accordion>

Now you can use this voice ID in the [dubbing API](/guides/dubs) just like any public voice:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://api.voicedub.ai/v1/me/dubs' \
    -H 'Authorization: Api-Key YOUR_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '{
      "voiceId": "789e0123-e89b-12d3-a456-426614174000",
      "link": "https://example.com/audio-to-dub.mp3"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.voicedub.ai/v1/me/dubs', {
    method: 'POST',
    headers: {
      'Authorization': 'Api-Key YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      voiceId: "789e0123-e89b-12d3-a456-426614174000",
      link: "https://example.com/audio-to-dub.mp3"
    })
  });

  const data = await response.json();
  console.log('Dub created with custom voice:', data.dub.id);
  ```

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

  response = requests.post('https://api.voicedub.ai/v1/me/dubs',
    headers={
      'Authorization': 'Api-Key YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    json={
      'voiceId': "789e0123-e89b-12d3-a456-426614174000",
      'link': "https://example.com/audio-to-dub.mp3"
    }
  )

  data = response.json()
  print('Dub created with custom voice:', data['dub']['id'])
  ```
</CodeGroup>

<Info>
  When filtering public voices (languages, genres, styles), multiple values inside the same filter are matched using <b>OR</b> (for example, languages: English <i>or</i> Spanish). Different filter types are combined using <b>AND</b> (for example, languages <i>and</i> genres <i>and</i> styles must all match). See the <a href="/api-reference/voices/get-public-voices">API reference</a> for details.
</Info>

## Complete Example

Here's a complete Node.js example for training a custom voice:

<CodeGroup>
  ```javascript Node.js expandable theme={null}
  const fs = require('fs');
  const apiKey = process.env.VOICEDUB_API_KEY;
  const baseUrl = 'https://api.voicedub.ai';

  async function trainCustomVoice(name, audioFiles, maxMinutes = 10) {
    // Step 1: Create the voice
    const createResponse = await fetch(`${baseUrl}/v1/me/voices`, {
      method: 'POST',
      headers: {
        'Authorization': `Api-Key ${apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: name,
        maxMinutes: maxMinutes,
        separate: true,
        numberOfFiles: audioFiles.length
      })
    });
    
    const { voice, uploadUrls } = await createResponse.json();
    console.log('Voice created:', voice.id);
    console.log('Required credits:', voice.requiredCredits);
    
    // Step 2: Upload training files
    for (let i = 0; i < audioFiles.length; i++) {
      const fileData = fs.readFileSync(audioFiles[i]);
      
      await fetch(uploadUrls[i], {
        method: 'PUT',
        headers: { 'Content-Type': 'audio/mpeg' },
        body: fileData
      });
      
      console.log(`Uploaded file ${i + 1}/${audioFiles.length}`);
    }
    
    // Step 3: Start training
    await fetch(`${baseUrl}/v1/me/voices/${voice.id}/clone`, {
      method: 'POST',
      headers: { 'Authorization': `Api-Key ${apiKey}` }
    });
    
    console.log('Training started...');
    
    // Step 4: Wait for completion
    let status = 'queued';
    while (!['done', 'error'].includes(status)) {
      await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30 seconds
      
      const statusResponse = await fetch(`${baseUrl}/v1/me/voices/${voice.id}`, {
        headers: { 'Authorization': `Api-Key ${apiKey}` }
      });
      
      const voiceData = await statusResponse.json();
      status = voiceData.voice.status;
      
      console.log('Training status:', status);
      
      if (status === 'done') {
        console.log('Training completed! Voice ID:', voice.id);
        return voice.id;
      } else if (status === 'error') {
        throw new Error(`Training failed: ${voiceData.voice.errorMessage}`);
      }
    }
  }

  // Usage
  const audioFiles = [
    './training-audio-1.mp3',
    './training-audio-2.mp3', 
    './training-audio-3.mp3'
  ];

  trainCustomVoice('My Custom Voice', audioFiles, 15)
    .then(voiceId => console.log('Success! Voice ID:', voiceId))
    .catch(err => console.error('Error:', err));
  ```

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

  API_KEY = 'your_api_key'
  BASE_URL = 'https://api.voicedub.ai'

  def train_custom_voice(name, audio_files, max_minutes=10):
      headers = {'Authorization': f'Api-Key {API_KEY}'}
      
      # Step 1: Create the voice
      create_response = requests.post(f'{BASE_URL}/v1/me/voices',
          headers={**headers, 'Content-Type': 'application/json'},
          json={
              'name': name,
              'maxMinutes': max_minutes,
              'separate': True,
              'numberOfFiles': len(audio_files)
          }
      )
      
      data = create_response.json()
      voice = data['voice']
      upload_urls = data['uploadUrls']
      
      print(f'Voice created: {voice["id"]}')
      print(f'Required credits: {voice["requiredCredits"]}')
      
      # Step 2: Upload training files
      for i, file_path in enumerate(audio_files):
          with open(file_path, 'rb') as f:
              requests.put(upload_urls[i], 
                          headers={'Content-Type': 'audio/mpeg'},
                          data=f.read())
          
          print(f'Uploaded file {i + 1}/{len(audio_files)}')
      
      # Step 3: Start training
      requests.post(f'{BASE_URL}/v1/me/voices/{voice["id"]}/clone',
                    headers=headers)
      
      print('Training started...')
      
      # Step 4: Wait for completion
      while True:
          time.sleep(30)  # Wait 30 seconds
          
          status_response = requests.get(f'{BASE_URL}/v1/me/voices/{voice["id"]}',
                                         headers=headers)
          voice_data = status_response.json()['voice']
          
          print(f'Training status: {voice_data["status"]}')
          
          if voice_data['status'] == 'done':
              print(f'Training completed! Voice ID: {voice["id"]}')
              return voice['id']
          elif voice_data['status'] == 'error':
              raise Exception(f'Training failed: {voice_data["errorMessage"]}')

  # Usage  
  audio_files = [
      './training-audio-1.mp3',
      './training-audio-2.mp3',
      './training-audio-3.mp3'
  ]

  voice_id = train_custom_voice('My Custom Voice', audio_files, 15)
  print(f'Success! Voice ID: {voice_id}')
  ```
</CodeGroup>

## Training Duration Guidelines

Choose your `maxMinutes` based on your quality needs and budget:

<CardGroup cols={3}>
  <Card title="Basic (5-10 min)" icon="clock">
    **Cost:** 50-100 credits

    **Quality:** Good for simple voices

    **Best for:** Testing, basic character voices
  </Card>

  <Card title="Standard (10-30 min)" icon="clock">
    **Cost:** 100-300 credits

    **Quality:** High quality results

    **Best for:** Most use cases, content creation
  </Card>

  <Card title="Premium (30-60 min)" icon="clock">
    **Cost:** 300-600 credits

    **Quality:** Exceptional quality

    **Best for:** Professional projects, complex voices
  </Card>
</CardGroup>

## Voice Quality Tips

<AccordionGroup>
  <Accordion title="Recording Environment">
    * **Quiet space:** Record in a quiet room with minimal echo
    * **Consistent microphone:** Use the same mic for all training files
    * **Stable distance:** Maintain consistent distance from microphone
    * **Audio levels:** Keep input levels consistent but avoid clipping
  </Accordion>

  <Accordion title="Content Selection">
    * **Emotional range:** Include happy, sad, excited, and calm expressions
    * **Pitch variety:** Cover the full vocal range of the target voice
    * **Speech patterns:** Include natural speech or singing rhythm and pacing
    * **Phonetic coverage:** Ensure good coverage of different sounds
  </Accordion>

  <Accordion title="Technical Quality">
    * **Sample rate:** 44.1kHz minimum, 48kHz preferred
    * **Bit depth:** 16-bit minimum, 24-bit preferred
    * **Format:** WAV or FLAC for best quality, high-bitrate MP3 acceptable
    * **Editing:** Light noise reduction okay, avoid heavy processing
  </Accordion>
</AccordionGroup>

## Pricing & Credits

Custom voice training consumes **10 API credits per minute** of training time (based on your `maxMinutes` setting):

* **5-minute training** = 50 credits
* **10-minute training** = 100 credits
* **30-minute training** = 300 credits
* **60-minute training** = 600 credits

<Info>
  The exact cost is shown in the `requiredCredits` field when you create the voice, before training starts.
</Info>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Training failed with poor quality">
    Common causes and solutions:

    * **Low-quality source audio:** Use higher bitrate recordings
    * **Inconsistent audio:** Ensure similar recording conditions for all files
    * **Insufficient data:** Try increasing `maxMinutes` for more training material
    * **Poor vocal separation:** If audio has backing tracks, ensure `separate: true`
  </Accordion>

  <Accordion title="Training stuck or taking too long">
    Training typically takes the length of your `maxMinutes` setting, plus 1–2 minutes for setup and processing.

    If your training is taking significantly longer than this, please reach out to our support team for assistance.
  </Accordion>

  <Accordion title="Upload failures">
    * **File too large:** Max 50MB per file, consider compressing audio
    * **Unsupported format:** Use MP3, WAV, M4A, FLAC, or OGG
    * **Network timeout:** Try uploading smaller files or check connection
  </Accordion>

  <Accordion title="Voice doesn't sound right">
    * **Try different source material:** More diverse audio often helps
    * **Adjust pitch in dubbing:** Use `pitchShift` parameter when creating dubs
    * **Increase training duration:** More training data usually improves quality
    * **Use dry acapella recordings:** Training works best with clean vocals free from background noise or music. Our vocal separation can help, but starting with isolated vocals gives the best results.
  </Accordion>
</AccordionGroup>

## Voice Management

Once trained, your custom voices:

* **Persist indefinitely** - No expiration or maintenance required
* **Are private to your account** - Only you can use them for dubbing
* **Can be used unlimited times** - Usage incurs standard API dubbing credits, in addition to the training cost
* **Work with all dubbing features** - Pitch shifting, vocal separation, etc.

<Check>
  Your trained voice is now ready! Use it in the [dubbing API](/guides/dubs) or integrate it into your applications.
</Check>
