Voice Cloning Using API

Note: If you haven't prepared your audio samples, refer to the preparation guide.

You can integrate voice cloning functionality into your application using Mirako's API. Below is an sample code snippet that demonstrates how to start a voice cloning task using the API.

python
# API configuration
API_KEY = "your_api_key_here"
BASE_URL = "https://mirako.co"

headers = {
    "Authorization": f"Bearer {API_KEY}"
}

def start_voice_cloning(audio_files, annotation_file, voice_name, clean_data=False, webhook_url=None):
    """Start voice cloning process"""

    # Prepare files for upload
    files = {}

    # Add audio files
    for i, audio_file in enumerate(audio_files):
        with open(audio_file, 'rb') as f:
            files[f'audio_samples'] = (audio_file.name, f.read(), 'audio/wav')

    # Add annotation file
    with open(annotation_file, 'rb') as f:
        files['annotation_list'] = (annotation_file, f.read(), 'text/plain')

    # Prepare form data
    data = {
        'name': voice_name,
        'clean_data': str(clean_data).lower()
    }

    # Add webhook if provided
    if webhook_url:
        data['webhook'] = webhook_url

    # Make request
    response = requests.post(
        f"{BASE_URL}/v1/voice/clone",
        headers=headers,
        files=files,
        data=data
    )

    if response.status_code == 200:
        result = response.json()
        task_id = result['data']['task_id']
        print(f"✅ Voice cloning started!")
        print(f"Task ID: {task_id}")
        return task_id
    else:
        print(f"❌ Error: {response.status_code}")
        print(response.text)
        return None

# Start cloning
task_id = start_voice_cloning(
    audio_files=audio_files,
    annotation_file="voice_annotations.txt",
    voice_name="My Custom Voice",
    # clean_data=True  # Optionally apply denoising
)

Poll Cloning Progress

python
import time

def check_cloning_status(task_id):
    """Check voice cloning task status"""

    response = requests.get(
        f"{BASE_URL}/v1/voice/clone/{task_id}/status",
        headers=headers
    )

    if response.status_code == 200:
        result = response.json()['data']
        status = result['status']

        print(f"Status: {status}")

        if status == "COMPLETED":
            profile_id = result.get('profile_id')
            print(f"🎉 Voice cloning completed!")
            print(f"Profile ID: {profile_id}")
            return {"status": "completed", "profile_id": profile_id}

        elif status in ["IN_QUEUE", "IN_PROGRESS"]:
            print("⏳ Voice cloning in progress...")
            return {"status": "processing"}

        elif status in ["FAILED", "CANCELED", "TIMED_OUT"]:
            error = result.get('error', 'Unknown error')
            print(f"❌ Voice cloning failed: {error}")
            return {"status": "failed", "error": error}

        else:
            print(f"Unknown status: {status}")
            return {"status": "unknown"}
    else:
        print(f"Error checking status: {response.text}")
        return {"status": "error"}

def wait_for_cloning_completion(task_id, max_wait_time=1800):  # 30 minutes
    """Wait for voice cloning to complete"""

    start_time = time.time()

    while time.time() - start_time < max_wait_time:
        result = check_cloning_status(task_id)

        if result["status"] == "completed":
            return result["profile_id"]
        elif result["status"] == "failed":
            print(f"Cloning failed: {result.get('error', 'Unknown error')}")
            return None

        # Wait 30 seconds before next check
        time.sleep(30)

    print("⏰ Timeout: Voice cloning didn't complete within time limit")
    return None

# Wait for completion
if task_id:
    profile_id = wait_for_cloning_completion(task_id)

    if profile_id:
        print(f"✅ Voice profile ready! ID: {profile_id}")
    else:
        print("❌ Voice cloning failed or timed out")

Dive Deeper