import type { Role } from '../api/tts'; interface VoiceAssignmentSectionProps { roles: Role[]; voiceAssignments: Map; onVoiceChange: (roleId: string, voiceId: string) => void; language: string; onLanguageChange: (lang: string) => void; speed: number; onSpeedChange: (speed: number) => void; onGenerate: () => void; onSkipReview?: () => void; isGenerating: boolean; allRolesAssigned: boolean; } interface VoiceOption { id: string; label: string; gender: 'male' | 'female'; accent: string; } interface LanguageOption { code: string; label: string; } // All available Kokoro voice options (54 voices across 9 languages) const KOKORO_VOICES: VoiceOption[] = [ // American English - Female (11 voices) { id: 'af_alloy', label: 'Alloy (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_aoede', label: 'Aoede (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_bella', label: 'Bella (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_heart', label: 'Heart (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_jessica', label: 'Jessica (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_kore', label: 'Kore (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_nicole', label: 'Nicole (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_nova', label: 'Nova (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_river', label: 'River (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_sarah', label: 'Sarah (Female, American)', gender: 'female', accent: 'American' }, { id: 'af_sky', label: 'Sky (Female, American)', gender: 'female', accent: 'American' }, // American English - Male (10 voices) { id: 'am_adam', label: 'Adam (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_echo', label: 'Echo (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_eric', label: 'Eric (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_fenrir', label: 'Fenrir (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_liam', label: 'Liam (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_michael', label: 'Michael (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_onyx', label: 'Onyx (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_puck', label: 'Puck (Male, American)', gender: 'male', accent: 'American' }, { id: 'am_santa', label: 'Santa (Male, American)', gender: 'male', accent: 'American' }, // British English - Female (4 voices) { id: 'bf_alice', label: 'Alice (Female, British)', gender: 'female', accent: 'British' }, { id: 'bf_emma', label: 'Emma (Female, British)', gender: 'female', accent: 'British' }, { id: 'bf_isabella', label: 'Isabella (Female, British)', gender: 'female', accent: 'British' }, { id: 'bf_lily', label: 'Lily (Female, British)', gender: 'female', accent: 'British' }, // British English - Male (4 voices) { id: 'bm_daniel', label: 'Daniel (Male, British)', gender: 'male', accent: 'British' }, { id: 'bm_fable', label: 'Fable (Male, British)', gender: 'male', accent: 'British' }, { id: 'bm_george', label: 'George (Male, British)', gender: 'male', accent: 'British' }, { id: 'bm_lewis', label: 'Lewis (Male, British)', gender: 'male', accent: 'British' }, // Spanish - Female (1 voice) { id: 'ef_dora', label: 'Dora (Female, Spanish)', gender: 'female', accent: 'Spanish' }, // Spanish - Male (2 voices) { id: 'em_alex', label: 'Alex (Male, Spanish)', gender: 'male', accent: 'Spanish' }, { id: 'em_santa', label: 'Santa (Male, Spanish)', gender: 'male', accent: 'Spanish' }, // French - Female (1 voice) { id: 'ff_siwis', label: 'Siwis (Female, French)', gender: 'female', accent: 'French' }, // Hindi - Female (2 voices) { id: 'hf_alpha', label: 'Alpha (Female, Hindi)', gender: 'female', accent: 'Hindi' }, { id: 'hf_beta', label: 'Beta (Female, Hindi)', gender: 'female', accent: 'Hindi' }, // Hindi - Male (2 voices) { id: 'hm_omega', label: 'Omega (Male, Hindi)', gender: 'male', accent: 'Hindi' }, { id: 'hm_psi', label: 'Psi (Male, Hindi)', gender: 'male', accent: 'Hindi' }, // Italian - Female (1 voice) { id: 'if_sara', label: 'Sara (Female, Italian)', gender: 'female', accent: 'Italian' }, // Italian - Male (1 voice) { id: 'im_nicola', label: 'Nicola (Male, Italian)', gender: 'male', accent: 'Italian' }, // Japanese - Female (4 voices) { id: 'jf_alpha', label: 'Alpha (Female, Japanese)', gender: 'female', accent: 'Japanese' }, { id: 'jf_gongitsune', label: 'Gongitsune (Female, Japanese)', gender: 'female', accent: 'Japanese' }, { id: 'jf_nezumi', label: 'Nezumi (Female, Japanese)', gender: 'female', accent: 'Japanese' }, { id: 'jf_tebukuro', label: 'Tebukuro (Female, Japanese)', gender: 'female', accent: 'Japanese' }, // Japanese - Male (1 voice) { id: 'jm_kumo', label: 'Kumo (Male, Japanese)', gender: 'male', accent: 'Japanese' }, // Portuguese - Female (1 voice) { id: 'pf_dora', label: 'Dora (Female, Portuguese)', gender: 'female', accent: 'Portuguese' }, // Portuguese - Male (2 voices) { id: 'pm_alex', label: 'Alex (Male, Portuguese)', gender: 'male', accent: 'Portuguese' }, { id: 'pm_santa', label: 'Santa (Male, Portuguese)', gender: 'male', accent: 'Portuguese' }, // Chinese/Mandarin - Female (4 voices) { id: 'zf_xiaobei', label: 'Xiaobei (Female, Chinese)', gender: 'female', accent: 'Chinese' }, { id: 'zf_xiaoni', label: 'Xiaoni (Female, Chinese)', gender: 'female', accent: 'Chinese' }, { id: 'zf_xiaoxiao', label: 'Xiaoxiao (Female, Chinese)', gender: 'female', accent: 'Chinese' }, { id: 'zf_xiaoyi', label: 'Xiaoyi (Female, Chinese)', gender: 'female', accent: 'Chinese' }, // Chinese/Mandarin - Male (4 voices) { id: 'zm_yunjian', label: 'Yunjian (Male, Chinese)', gender: 'male', accent: 'Chinese' }, { id: 'zm_yunxi', label: 'Yunxi (Male, Chinese)', gender: 'male', accent: 'Chinese' }, { id: 'zm_yunxia', label: 'Yunxia (Male, Chinese)', gender: 'male', accent: 'Chinese' }, { id: 'zm_yunyang', label: 'Yunyang (Male, Chinese)', gender: 'male', accent: 'Chinese' }, ]; // Language options - all supported by Kokoro TTS const LANGUAGES: LanguageOption[] = [ { code: 'a', label: 'American English' }, { code: 'b', label: 'British English' }, { code: 'e', label: 'Spanish (Español)' }, { code: 'f', label: 'French (Français)' }, { code: 'h', label: 'Hindi (हिन्दी)' }, { code: 'i', label: 'Italian (Italiano)' }, { code: 'j', label: 'Japanese (日本語)' }, { code: 'p', label: 'Portuguese (Português)' }, { code: 'z', label: 'Chinese (中文)' }, ]; export default function VoiceAssignmentSection({ roles, voiceAssignments, onVoiceChange, language, onLanguageChange, speed, onSpeedChange, onGenerate, onSkipReview, isGenerating, allRolesAssigned, }: VoiceAssignmentSectionProps) { const handleVoiceSelect = (roleId: string, voiceId: string) => { onVoiceChange(roleId, voiceId); }; const handleLanguageSelect = (e: React.ChangeEvent) => { onLanguageChange(e.target.value); }; const handleSpeedChange = (e: React.ChangeEvent) => { const newSpeed = parseFloat(e.target.value); onSpeedChange(newSpeed); }; const isGenerateDisabled = !allRolesAssigned || isGenerating; return (

Assign Voices

Choose a voice for each character in your story.

{/* Voice Assignments */}
{roles.map((role, index) => (
{index + 1}
))}
{/* Settings Grid */}
{/* Language */}
{/* Speed */}
0.5x 1.5x
{/* Validation Message */} {!allRolesAssigned && !isGenerating && (

⚠️ Please assign voices to all roles before continuing.

)} {/* Action Buttons */}
{onSkipReview && ( )}
); }