--- title: "Voice Profiles" description: "How voice profile management works in Voicebox" --- ## Overview Voice profiles are the foundation of Voicebox's voice cloning capability. Each profile stores reference audio samples and metadata that the TTS model uses to clone a voice. ## Architecture The voice profile system consists of three main components: **Database Layer:** SQLite tables store profile metadata and sample references. **File Storage:** Audio samples are stored on disk in a structured directory format. **Profile Module:** The `profiles.py` module provides the business logic for CRUD operations. ## Data Model ### VoiceProfile Table ```python class VoiceProfile(Base): __tablename__ = "profiles" id = Column(String, primary_key=True) name = Column(String, unique=True, nullable=False) description = Column(Text) language = Column(String, default="en") created_at = Column(DateTime) updated_at = Column(DateTime) ``` ### ProfileSample Table ```python class ProfileSample(Base): __tablename__ = "profile_samples" id = Column(String, primary_key=True) profile_id = Column(String, ForeignKey("profiles.id")) audio_path = Column(String, nullable=False) reference_text = Column(Text, nullable=False) ``` ## File Structure Profiles are stored in the data directory: ``` data/ └── profiles/ └── {profile_id}/ ├── {sample_id_1}.wav ├── {sample_id_2}.wav └── ... ``` ## Core Functions ### Creating a Profile ```python async def create_profile(data: VoiceProfileCreate, db: Session) -> VoiceProfileResponse: # 1. Create database record db_profile = DBVoiceProfile( id=str(uuid.uuid4()), name=data.name, description=data.description, language=data.language, ) db.add(db_profile) db.commit() # 2. Create profile directory profile_dir = profiles_dir / db_profile.id profile_dir.mkdir(parents=True, exist_ok=True) return VoiceProfileResponse.model_validate(db_profile) ``` ### Adding Samples When a sample is added, the audio is validated and copied to the profile directory: ```python async def add_profile_sample( profile_id: str, audio_path: str, reference_text: str, db: Session, ) -> ProfileSampleResponse: # 1. Validate audio (duration, format, quality) is_valid, error_msg = validate_reference_audio(audio_path) if not is_valid: raise ValueError(f"Invalid reference audio: {error_msg}") # 2. Copy to profile directory sample_id = str(uuid.uuid4()) dest_path = profile_dir / f"{sample_id}.wav" audio, sr = load_audio(audio_path) save_audio(audio, str(dest_path), sr) # 3. Create database record db_sample = DBProfileSample( id=sample_id, profile_id=profile_id, audio_path=str(dest_path), reference_text=reference_text, ) db.add(db_sample) db.commit() ``` ### Voice Prompt Creation When generating speech, samples are combined into a voice prompt: ```python async def create_voice_prompt_for_profile( profile_id: str, db: Session, ) -> dict: samples = db.query(DBProfileSample).filter_by(profile_id=profile_id).all() if len(samples) == 1: # Single sample - use directly voice_prompt, _ = await tts_model.create_voice_prompt( sample.audio_path, sample.reference_text, ) else: # Multiple samples - combine them combined_audio, combined_text = await tts_model.combine_voice_prompts( [s.audio_path for s in samples], [s.reference_text for s in samples], ) voice_prompt, _ = await tts_model.create_voice_prompt( combined_audio_path, combined_text, ) return voice_prompt ``` ## Audio Validation Reference audio is validated before being accepted: - **Duration:** 3-30 seconds recommended - **Format:** WAV, MP3, FLAC, OGG supported - **Sample Rate:** Resampled to 24kHz - **Channels:** Converted to mono if stereo ## Export/Import Profiles can be exported as ZIP archives for sharing: ``` profile_export.zip ├── profile.json # Metadata ├── samples/ │ ├── sample_1.wav │ └── sample_1.json # Reference text └── ... ``` ## API Endpoints | Method | Endpoint | Description | |--------|----------|-------------| | GET | `/profiles` | List all profiles | | POST | `/profiles` | Create a profile | | GET | `/profiles/{id}` | Get profile by ID | | PUT | `/profiles/{id}` | Update profile | | DELETE | `/profiles/{id}` | Delete profile | | GET | `/profiles/{id}/samples` | Get profile samples | | POST | `/profiles/{id}/samples` | Add sample to profile | | PUT | `/profiles/samples/{id}` | Update sample text | | DELETE | `/profiles/samples/{id}` | Delete sample | | GET | `/profiles/{id}/export` | Export as ZIP | | POST | `/profiles/import` | Import from ZIP | ## Best Practices ### Sample Quality - Use clean audio with minimal background noise - Ensure the reference text exactly matches what is spoken - Multiple samples (3-5) improve voice cloning quality ### Language Matching - Set the profile language to match the reference audio - Supported languages: en, zh, ja, ko, de, fr, ru, pt, es, it ### Naming Conventions - Use descriptive names that identify the voice - Avoid special characters that may cause filesystem issues