From 07069144c7cfdc6774eab5ade7534dcd11d769ac Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 1 Oct 2026 22:42:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(viral-video):=20=E9=A2=84=E8=AE=BE=E9=9F=B3?= =?UTF-8?q?=E8=89=B2ID=E4=B8=8E=E5=90=8E=E7=AB=AF=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=EF=BC=88longxiaochun=5Fv3=E7=AD=89v3=E5=90=8E=E7=BC=80?= =?UTF-8?q?=EF=BC=89+=20=E5=8F=96=E6=B6=88=E6=A8=A1=E7=B3=8A=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=85=9C=E5=BA=95=20(#2130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/PresetVoicePickerModal.tsx | 89 +++++++------------ 1 file changed, 34 insertions(+), 55 deletions(-) diff --git a/apps/web/src/pages/viral-video/components/PresetVoicePickerModal.tsx b/apps/web/src/pages/viral-video/components/PresetVoicePickerModal.tsx index 6a0d704b5..1041ff13f 100644 --- a/apps/web/src/pages/viral-video/components/PresetVoicePickerModal.tsx +++ b/apps/web/src/pages/viral-video/components/PresetVoicePickerModal.tsx @@ -34,83 +34,63 @@ interface Props { /** 兜底 mock 音色(后端 /api/v1/tts/presets 返回字段不够时使用) */ const MOCK_VOICES: PresetVoice[] = [ + // ⚠️ 兜底 mock,仅在 /voices/presets 接口不可达时使用;ID 必须与后端 + // packages/domain/preset_voices.py PRESET_VOICES 的 voice_id 对齐(v3后缀) { - id: "long-xiaochun", + id: "longxiaochun_v3", name: "龙小淳", gender: "female", category: "女声", desc: "知性积极女声,适合语音助手", }, { - id: "long-xiaoxia", + id: "longxiaoxia_v3", name: "龙小夏", gender: "female", category: "女声", desc: "沉稳权威女声,适合新闻播报", }, { - id: "long-xiaoyan", - name: "龙小颜", - gender: "female", - category: "女声", - desc: "温柔甜美女声,适合情感口播", - }, - { - id: "long-xiaotong", - name: "龙小彤", - gender: "female", - category: "女声", - desc: "活力少女音,适合短视频带货", - }, - { - id: "long-sanshu", + id: "longsanshu_v3", name: "龙三叔", gender: "male", category: "男声", desc: "沉稳质感男声,适合有声书", }, { - id: "long-xiaogang", - name: "龙小刚", - gender: "male", - category: "男声", - desc: "阳光活力男声,适合解说", - }, - { - id: "long-xiaocheng", - name: "龙小诚", - gender: "male", - category: "男声", - desc: "磁性商务男声,适合品牌宣传", - }, - { - id: "long-xiaozhi", - name: "龙小智", - gender: "child", - category: "童声", - desc: "可爱童声,适合亲子内容", - }, - { - id: "long-yue", + id: "longyue_v3", name: "龙悦", gender: "female", - category: "情绪", - desc: "温柔治愈女声,适合睡前/助眠", + category: "女声", + desc: "温暖磁性女声,适合广告配音", }, { - id: "long-xiaodong", - name: "龙晓东", + id: "longshu_v3", + name: "龙书", gender: "male", - category: "方言", - desc: "东北方言男声,接地气", + category: "男声", + desc: "沉稳青年男声,适合教育讲解", }, - { id: "long-xiaoling", name: "龙小玲", gender: "female", category: "方言", desc: "粤语女声" }, { - id: "long-xiaoxiao-neural", - name: "晓晓", + id: "longyingjing_v3", + name: "龙应静", gender: "female", category: "女声", - desc: "温柔女声", + desc: "低调冷静女声,适合纪录片解说", + }, + { + id: "longshuo_v3", + name: "龙硕", + gender: "male", + category: "男声", + desc: "博才干练男声,适合科技类内容", + }, + { + id: "longtian_v3", + name: "龙甜", + gender: "female", + category: "女声", + desc: "活泼女声,适合短视频配音", }, ] @@ -178,23 +158,22 @@ const PresetVoicePickerModal: React.FC = ({ // 合并真实数据和 mock:如果真实数据 gender/category 缺失,用 mock 兜底 const allVoices: PresetVoice[] = useMemo(() => { + // 真实 API 返回的 voice_id 以 API 为准(如 longxiaochun_v3),前端不做硬编码覆盖 const realList: PresetVoice[] = (voices || []).map((v) => { - // 按 name 模糊匹配 mock 获取补充信息 - const mockMatch = MOCK_VOICES.find( - (m) => v.name?.includes(m.name.slice(1)) || m.name.includes(v.name?.slice(0, 2) || "___"), - ) + // 按 id 精确匹配 mock 获取补充元信息(id 即 voice_id,唯一稳定键) + const mockMatch = MOCK_VOICES.find((m) => m.id === v.id) return { ...v, gender: v.gender || mockMatch?.gender, category: v.category || mockMatch?.category || - (v.gender === "female" ? "女声" : v.gender === "male" ? "男声" : undefined), + (v.gender === "female" ? "女声" : v.gender === "male" ? "男声" : "其他"), desc: v.desc || mockMatch?.desc, sample_audio_url: v.sample_audio_url, } }) - // 如果没有真实数据,使用 mock + // 如果没有真实数据,使用兜底 mock(接口失败时) return realList.length > 0 ? realList : MOCK_VOICES }, [voices])