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
- Update labels and the description with
PATCH /v1/voices/{voice_id}. - Tune defaults with
PATCH /v1/voices/{voice_id}/settings. - Remove the voice entirely with
DELETE /v1/voices/{voice_id}.