Cloning a voice

Voice cloning is a two-step flow: upload one sample to generate a preview, then save the preview as a reusable voice. Adjust text and instructions on the preview. Speaker consent is required — see consent.

Recording requirements

  • Upload exactly one sample file.
  • Single speaker, no background music or noise.
  • MP3 or WAV only.
  • Maximum duration: 30 seconds.
  • Maximum file size: 5MB.

Step 1: Create a preview

python import os from pathlib import Path from breeze_blue import BreezeBlue client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"]) preview = client.voices.create_clone_preview( name="My narrator", file=Path("narrator.wav"), text="Welcome to the preview.", instructions="Stay close to the reference tone.", ) print(preview["generated_voice_id"]) typescript import { readFile } from "node:fs/promises"; import { BreezeBlueClient } from "@breeze.blue/sdk"; const client = new BreezeBlueClient({ apiKey: process.env.BREEZE_API_KEY!, }); const preview = await client.voices.createClonePreview({ name: "My narrator", file: { data: await readFile("narrator.wav"), filename: "narrator.wav", contentType: "audio/wav", }, text: "Welcome to the preview.", instructions: "Stay close to the reference tone.", }); console.log(preview.generatedVoiceId); curl curl -X POST "https://api.breeze.blue/v1/voice-previews/clone" \ -H "xi-api-key: $BREEZE_API_KEY" \ -F "name=My narrator" \ -F "files=@./narrator.wav" \ -F "text=Welcome to the preview." \ -F "instructions=Stay close to the reference tone."
import os
from pathlib import Path

from breeze_blue import BreezeBlue

client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"])

preview = client.voices.create_clone_preview(
    name="My narrator",
    file=Path("narrator.wav"),
    text="Welcome to the preview.",
    instructions="Stay close to the reference tone.",
)

print(preview["generated_voice_id"])

The response contains a generated_voice_id, not a saved voice_id. text defaults to the Breeze clone script when omitted or empty. instructions defaults to none. SDKs also accept files with exactly one item.

Step 2: Stream the preview

python import os from pathlib import Path from breeze_blue import BreezeBlue, save client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"]) preview_audio = client.voices.stream_preview( generated_voice_id="gvi_01hpreview", ) save(preview_audio, Path("clone-preview.mp3")) typescript import { BreezeBlueClient } from "@breeze.blue/sdk"; import { save } from "@breeze.blue/sdk/node"; const client = new BreezeBlueClient({ apiKey: process.env.BREEZE_API_KEY!, }); const previewAudio = await client.voices.streamPreview( "gvi_01hpreview", ); await save(previewAudio, "clone-preview.mp3"); curl curl "https://api.breeze.blue/v1/voice-previews/$GENERATED_VOICE_ID/stream" \ -H "xi-api-key: $BREEZE_API_KEY" \ --output clone-preview.mp3
import os
from pathlib import Path

from breeze_blue import BreezeBlue, save

client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"])

preview_audio = client.voices.stream_preview(
    generated_voice_id="gvi_01hpreview",
)
save(preview_audio, Path("clone-preview.mp3"))

Step 3: Save the preview as a voice

python import os from breeze_blue import BreezeBlue client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"]) voice = client.voices.save_preview( generated_voice_id="gvi_01hpreview", voice_name="My narrator", ) print(voice["voice_id"]) typescript import { BreezeBlueClient } from "@breeze.blue/sdk"; const client = new BreezeBlueClient({ apiKey: process.env.BREEZE_API_KEY!, }); const voice = await client.voices.savePreview({ generatedVoiceId: "gvi_01hpreview", voiceName: "My narrator", }); console.log(voice.voiceId); curl curl -X POST "https://api.breeze.blue/v1/voice-previews/gvi_01hpreview/save" \ -H "xi-api-key: $BREEZE_API_KEY" \ -H "content-type: application/json" \ -d '{ "voice_name": "My narrator" }'
import os

from breeze_blue import BreezeBlue

client = BreezeBlue(api_key=os.environ["BREEZE_API_KEY"])

voice = client.voices.save_preview(
    generated_voice_id="gvi_01hpreview",
    voice_name="My narrator",
)

print(voice["voice_id"])

Saving consumes a voice slot. Subsequent POST /v1/text-to-speech/{voice_id} calls use the original uploaded sample and transcript, not the preview audio.

Editing or deleting a saved voice