voice-clone
Clone a voice for use in TTS generation. Covers voice sample upload, cloning workflow, and integration with ElevenLabs.
SKILL.mdAutoAnimation/.claude/skills/voice-clone/SKILL.md
GitHubPurpose
Clone a custom voice from audio samples using ElevenLabs, then use it for TTS generation throughout the app. The cloned voice appears in the voice library alongside built-in voices and can be selected for any character dialogue.
Steps
Collect audio samples. The user uploads audio files through the drag-and-drop zone in
VoiceClonePanel.tsx. Requirements:- Supported formats: WAV, MP3, M4A, WebM, OGG (checked by extension regex)
- Max 25 files total (
MAX_FILES) - Max 10MB per file (
MAX_FILE_SIZE) - Minimum 60 seconds total duration recommended (
MIN_TOTAL_DURATION) - 5+ minutes total duration is ideal for best quality
Validate samples. The panel automatically decodes each file using
AudioContext.decodeAudioData()to measure duration. A quality indicator bar shows:- Red: under 60s total duration
- Yellow: 60s-300s (meets minimum but not ideal)
- Green: 300s+ (good quality expected)
- Warnings for oversized files or unsupported formats
Provide voice metadata. The user enters:
- Voice Name (required): A label for the cloned voice
- Description (optional): Characteristics of the voice
Submit clone request. Call
getElevenLabsService().cloneVoice(name, description, files)which:- Builds a
FormDatawith name, description, and all audio files - Posts to
/api/proxy/elevenlabs/voices/add(server-side proxy to avoid CORS) - Returns
{ voice_id: string }on success
- Builds a
Preview the cloned voice. After successful cloning, the panel offers a preview button that generates speech for the phrase "Hello, this is my cloned voice. How does it sound?" using the new voice ID via
getElevenLabsService().generateSpeech().Use the cloned voice. The cloned voice becomes available in
useVoiceStore.clonedVoicesand can be selected like any built-in voice for dialogue generation. Use it withgenerateWithAlignment()by passing the newvoice_id.Delete a cloned voice. Call
getElevenLabsService().deleteVoice(voiceId)which sends a DELETE to/api/proxy/elevenlabs/voices/{voiceId}. The voice is removed from both ElevenLabs and the local store.
Key Files
src/components/panels/VoiceClonePanel.tsx-- Full voice cloning UI with upload, quality indicator, metadata form, progress, previewsrc/services/elevenlabs.ts--cloneVoice(name, description, files),deleteVoice(voiceId),generateSpeech(text, voiceId)src/stores/useVoiceStore.ts--clonedVoicesarray,isCloningflag,cloneErrorstate,cloneVoice()action,deleteClonedVoice()actionsrc/components/ui/AudioSampleCard.tsx-- Individual audio sample display cardsrc/components/credits/CreditCostTag.tsx-- Credit cost indicator for the clone operation
Common Issues
- Insufficient sample duration: Voice quality degrades significantly below 60 seconds. The UI warns but does not block cloning. Recommend at least 1 minute, ideally 5 minutes.
- File size limits: Individual files over 10MB may be rejected by ElevenLabs. The panel warns but does not prevent upload.
- Server proxy required: Voice cloning goes through
/api/proxy/elevenlabs/voices/addto inject the API key server-side and avoid exposing it in the browser. - Credit cost: Voice cloning consumes credits. The
CreditCostTagcomponent shows the cost. Check withcreditGatebefore proceeding. - Cloning takes time: The ElevenLabs API processes samples asynchronously. The UI shows a loading spinner during the operation.
Examples
// Clone a voice
const service = getElevenLabsService()
const result = await service.cloneVoice(
'My Custom Voice',
'Warm male voice with slight British accent',
[file1, file2, file3] // File objects from input
)
console.log('New voice ID:', result.voice_id)
// Use the cloned voice for TTS
const { audioUrl, alignment } = await service.generateWithAlignment(
'Hello world, this is my cloned voice!',
result.voice_id,
{ stability: 0.5, similarityBoost: 0.75 }
)
// Delete the voice
await service.deleteVoice(result.voice_id)