fix(voice-clone): persist clone info in localStorage, auto-merge into project knobs, fix clone ID detection in CreateModal

- Move voice clone cache from module-level memory to localStorage
  so it survives page refresh and works across browser tabs
- VoiceAvatarPlaceholder now syncs clone result to localStorage
  immediately after creation (both design and clone paths)
- usePodcastProjectState auto-merges voice clone cache into project
  knobs when loading a project (fills gap for projects created
  before voice clone or when voice clone was created after)
- CreateModal now detects voice clone IDs by prefix (vc_*) not
  just by VOICE_CLONE_ID constant, fixing the mismatch where
  VoiceSelector passes the actual clone ID but CreateModal
  expected the placeholder ID
- AudioRegenerateModal is intentionally per-scene override and
  does not write back to knobs (by design)
- trends.py handler added for podcast topic trend analysis
This commit is contained in:
ajaysi
2026-04-24 20:36:35 +05:30
parent d518365c87
commit fc47445181
6 changed files with 191 additions and 16 deletions

View File

@@ -319,13 +319,19 @@ export const CreateModal: React.FC<CreateModalProps> = ({ onCreate, open, defaul
// Include selected voice in knobs
// If voice clone is selected, include voice clone metadata
const isVoiceClone = selectedVoiceId === VOICE_CLONE_ID || knobs.custom_voice_id === selectedVoiceId;
// VoiceSelector may pass VOICE_CLONE_ID, the actual clone ID (vc_*), or a system voice ID
const selectedLooksLikeClone = selectedVoiceId?.startsWith("vc_") || selectedVoiceId === "MY_VOICE_CLONE";
const isVoiceClone = selectedVoiceId === VOICE_CLONE_ID || selectedLooksLikeClone || knobs.custom_voice_id === selectedVoiceId;
let voiceSampleUrl: string | undefined;
let voiceCloneEngine: string | undefined;
let customVoiceId: string | undefined;
if (isVoiceClone) {
// If VoiceSelector already gave us the real clone ID, use it as fallback
if (selectedLooksLikeClone && selectedVoiceId !== VOICE_CLONE_ID) {
customVoiceId = selectedVoiceId;
}
try {
const voiceCloneInfo = await getLatestVoiceClone();
if (voiceCloneInfo?.success && voiceCloneInfo.custom_voice_id) {