fix: #1794 AI数字人页面 7 项实测问题(P0白屏/按钮无响应/素材库选择/文案句选/标题预设样式) #1809

Closed
opened 2026-09-09 00:29:47 +08:00 by xiaoxia · 0 comments
Owner

硬性要求

严格按下列问题修复,只改列出的问题;修改过程中发现的其他 BUG 可一并修,但不允许改动未列出的 UI 设计和功能(避免改这里坏那里)。改动后必须回归验证不破坏现有功能。


问题1(P0 页面白屏):TypeError n.filter is not a function

根因:后端列表接口统一返回分页结构 {items:[...], total},但 apps/web/src/pages/ai-avatar/api/aiAvatar.tsgetScripts() 直接 return response.data(是对象不是数组)。AiAvatarPage.tsx:272scripts.filter(...) 对对象调用 filter 崩溃。
(注:/voices 已正确用 res.items||[]getAssetsByKind 已正确返回 response.data.items||[],这两处不用动。)

修复

  • getScripts:改为返回 response.data.items ?? [](Script[])。
  • getLipsyncJob/createLipsyncJob/submitRender/getRenderJob 等单条返回的接口,核对响应是否被 {items} 或其他包装;单条对象保持返回 data。
  • 全量排查 ai-avatar 页面所有 .filter/.map 调用点,确保数据源一定是数组(加 Array.isArray / ?? [] 防御)。

问题2:点击「生成对口型视频」无任何反应

根因AiAvatarPage.tsx handleGenerateLipsync 前置条件 if (!selectedVideo || !selectedVoice || !scriptText) return 静默返回无提示;请求失败也只 console.error。用户不知道缺什么。

修复:条件不满足时用页面内可见提示(toast/内联提示,复用项目现有提示组件,不新造 UI 风格)明确说明缺哪项,例如「请先选择出镜视频」「请先选择音色」「请先选择或输入文案」;请求 catch 时同样给用户可见的失败提示。handleGenerate(渲染提交)同样补提示。

问题3:出镜视频选择素材,应先选素材库再选素材

现状ModalAssetPicker 直接按 kind(video/image) 拉素材,没有「素材库」概念。现在只有一个默认库,以后会建多个素材库。

修复:出镜视频选择流程改为「先选素材库 → 再选该库里的视频素材」。

  • 复用现有素材库 API:getAssetLibraries(kind)@/api/assets/libraries)拉取 video 类型素材库列表;getAssets 支持 library_id 过滤(@/api/assets/assets)。
  • 交互参考智能剪辑现有「选择素材/素材库」的做法,保持一致。
  • 出镜视频限定 video 库/视频素材。

问题4:插入画中画(画面插入)选择素材也应先选素材库

修复ModalBRollEditor 左侧素材网格同样加「素材库选择」步骤(video 库),选中库后用 library_id 拉取该库素材,再选具体素材。复用问题3同一套选库组件/逻辑,不重复造。

问题5:画面插入「文案段落索引」用户无法理解,要让用户看到每一句文案

现状ModalBRollEditor 右侧是一个数字输入框「文案段落索引」,用户不知道第几句是什么。

修复:把数字输入框换成文案句子列表——把当前文案按句(句号/问号/感叹号/换行)分句,每句一行可点击选中,选中即对应 script_segment_index。让用户看到并点选要插入画面的那一句,而不是填数字。

问题6:画面插入的「开始时间/结束时间」用户不理解

说明:这两个时间是「插入的画面在最终口播视频时间轴上出现的起止时刻(秒)」,即这段画面对应口播的哪一段时间。

现状问题:MediaKit 对口型只返回成品视频+总时长,没有逐句时间戳,让用户手填秒数既看不懂也填不准。

修复:去掉手动填写的开始/结束秒数输入框。由系统自动确定——用户在问题5中点选了文案句子后,按「该句字数 ÷ 全文总字数 × 口播视频总时长(output_duration)」估算该句在视频中的起止时间,作为 segment 的 start_time/end_time 提交(渲染管线 build_broll_overlay_filter 仍按 start_time/end_time 做 overlay,字段不变,只是改为自动算、不让用户填)。句子列表可显示每句对应的估算时间段。

问题7:标题预设样式 UI 与智能剪辑完全不一致、布局混乱

根因PanelTitleConfig.tsx 已 import 智能剪辑的 TitleStylePanel/TITLE_PRESETS(组件和数据是复用的),但 AiAvatarPage 只 import 了 ./AiAvatar.css没有加载智能剪辑标题样式所在的 generate.css.xx-title-presets-grid/.xx-title-preset-card 等网格布局定义在 apps/web/src/pages/generate/generate.css 约 1730 行)。缺少 grid 布局导致 24 个预设 T 格子全部堆叠、行与行重叠。

修复:让 TitleStylePanel 在数字人页呈现得和智能剪辑一模一样——

  • 让标题预设所需的 .xx-title-presets-grid/.xx-title-preset-card/.xx-title-preset-preview-text 等样式在 ai-avatar 页生效(对照智能剪辑页面的引入方式处理;可抽取标题样式为独立 css 共用,或按需引入,注意避免污染/冲突)。
  • 以智能剪辑页面实际渲染效果为唯一标准对齐:网格列数、格子尺寸、T 字配色/描边/发光、选中态,全部一致,不自己发挥。
  • 不得改动智能剪辑原页面的样式。

验收标准

  • 打开 AI数字人页不再白屏;选择文案弹窗、素材弹窗、音色列表正常加载
  • 未选出镜视频/音色/文案时点生成,有明确可见提示;接口失败有提示
  • 出镜视频:先选素材库、再选该库视频素材
  • 画面插入:先选素材库再选素材;已选素材仍标灰防重复(保留现有逻辑)
  • 画面插入:文案以句子列表展示、可点选,不再是数字索引输入框
  • 画面插入:无手动起止时间输入框,时间段按所选句子自动估算
  • 标题预设网格与智能剪辑视觉完全一致、不再重叠
  • 严格只改上述问题,其他 UI/功能保持不变,不破坏现有页面
  • TypeScript 类型安全,PR CI 全绿

参考文件:

  • 前端页面目录:apps/web/src/pages/ai-avatar/
  • 智能剪辑标题样式:apps/web/src/pages/generate/components/title/TitleStylePanel.tsx、TitlePresetsGrid.tsx;样式 apps/web/src/pages/generate/generate.css(~1656-1760行)
  • 素材库 API:apps/web/src/api/assets/libraries.ts、assets.ts
  • 后端渲染:apps/api/app/services/ai_avatar_render_service.py;packages/domain/video_filter_builder.py(build_broll_overlay_filter)
## 硬性要求 严格按下列问题修复,**只改列出的问题**;修改过程中发现的其他 BUG 可一并修,但**不允许改动未列出的 UI 设计和功能**(避免改这里坏那里)。改动后必须回归验证不破坏现有功能。 --- ## 问题1(P0 页面白屏):TypeError n.filter is not a function **根因**:后端列表接口统一返回分页结构 `{items:[...], total}`,但 `apps/web/src/pages/ai-avatar/api/aiAvatar.ts` 的 `getScripts()` 直接 `return response.data`(是对象不是数组)。`AiAvatarPage.tsx:272` 的 `scripts.filter(...)` 对对象调用 filter 崩溃。 (注:`/voices` 已正确用 `res.items||[]`;`getAssetsByKind` 已正确返回 `response.data.items||[]`,这两处不用动。) **修复**: - `getScripts`:改为返回 `response.data.items ?? []`(Script[])。 - `getLipsyncJob`/`createLipsyncJob`/`submitRender`/`getRenderJob` 等单条返回的接口,核对响应是否被 `{items}` 或其他包装;单条对象保持返回 data。 - 全量排查 ai-avatar 页面所有 `.filter/.map` 调用点,确保数据源一定是数组(加 `Array.isArray` / `?? []` 防御)。 ## 问题2:点击「生成对口型视频」无任何反应 **根因**:`AiAvatarPage.tsx handleGenerateLipsync` 前置条件 `if (!selectedVideo || !selectedVoice || !scriptText) return` 静默返回无提示;请求失败也只 `console.error`。用户不知道缺什么。 **修复**:条件不满足时用页面内可见提示(toast/内联提示,复用项目现有提示组件,不新造 UI 风格)明确说明缺哪项,例如「请先选择出镜视频」「请先选择音色」「请先选择或输入文案」;请求 catch 时同样给用户可见的失败提示。`handleGenerate`(渲染提交)同样补提示。 ## 问题3:出镜视频选择素材,应先选素材库再选素材 **现状**:`ModalAssetPicker` 直接按 kind(video/image) 拉素材,没有「素材库」概念。现在只有一个默认库,以后会建多个素材库。 **修复**:出镜视频选择流程改为「先选素材库 → 再选该库里的视频素材」。 - 复用现有素材库 API:`getAssetLibraries(kind)`(`@/api/assets/libraries`)拉取 video 类型素材库列表;`getAssets` 支持 `library_id` 过滤(`@/api/assets/assets`)。 - 交互参考智能剪辑现有「选择素材/素材库」的做法,保持一致。 - 出镜视频限定 video 库/视频素材。 ## 问题4:插入画中画(画面插入)选择素材也应先选素材库 **修复**:`ModalBRollEditor` 左侧素材网格同样加「素材库选择」步骤(video 库),选中库后用 `library_id` 拉取该库素材,再选具体素材。复用问题3同一套选库组件/逻辑,不重复造。 ## 问题5:画面插入「文案段落索引」用户无法理解,要让用户看到每一句文案 **现状**:`ModalBRollEditor` 右侧是一个数字输入框「文案段落索引」,用户不知道第几句是什么。 **修复**:把数字输入框换成**文案句子列表**——把当前文案按句(句号/问号/感叹号/换行)分句,每句一行可点击选中,选中即对应 `script_segment_index`。让用户看到并点选要插入画面的那一句,而不是填数字。 ## 问题6:画面插入的「开始时间/结束时间」用户不理解 **说明**:这两个时间是「插入的画面在最终口播视频时间轴上出现的起止时刻(秒)」,即这段画面对应口播的哪一段时间。 **现状问题**:MediaKit 对口型只返回成品视频+总时长,没有逐句时间戳,让用户手填秒数既看不懂也填不准。 **修复**:去掉手动填写的开始/结束秒数输入框。由系统自动确定——用户在问题5中点选了文案句子后,按「该句字数 ÷ 全文总字数 × 口播视频总时长(output_duration)」估算该句在视频中的起止时间,作为 segment 的 start_time/end_time 提交(渲染管线 `build_broll_overlay_filter` 仍按 start_time/end_time 做 overlay,字段不变,只是改为自动算、不让用户填)。句子列表可显示每句对应的估算时间段。 ## 问题7:标题预设样式 UI 与智能剪辑完全不一致、布局混乱 **根因**:`PanelTitleConfig.tsx` 已 import 智能剪辑的 `TitleStylePanel`/`TITLE_PRESETS`(组件和数据是复用的),但 `AiAvatarPage` 只 import 了 `./AiAvatar.css`,**没有加载智能剪辑标题样式所在的 `generate.css`**(`.xx-title-presets-grid`/`.xx-title-preset-card` 等网格布局定义在 `apps/web/src/pages/generate/generate.css` 约 1730 行)。缺少 grid 布局导致 24 个预设 T 格子全部堆叠、行与行重叠。 **修复**:让 TitleStylePanel 在数字人页呈现得和智能剪辑**一模一样**—— - 让标题预设所需的 `.xx-title-presets-grid`/`.xx-title-preset-card`/`.xx-title-preset-preview-text` 等样式在 ai-avatar 页生效(对照智能剪辑页面的引入方式处理;可抽取标题样式为独立 css 共用,或按需引入,注意避免污染/冲突)。 - 以智能剪辑页面实际渲染效果为唯一标准对齐:网格列数、格子尺寸、T 字配色/描边/发光、选中态,全部一致,不自己发挥。 - 不得改动智能剪辑原页面的样式。 --- ## 验收标准 - [ ] 打开 AI数字人页不再白屏;选择文案弹窗、素材弹窗、音色列表正常加载 - [ ] 未选出镜视频/音色/文案时点生成,有明确可见提示;接口失败有提示 - [ ] 出镜视频:先选素材库、再选该库视频素材 - [ ] 画面插入:先选素材库再选素材;已选素材仍标灰防重复(保留现有逻辑) - [ ] 画面插入:文案以句子列表展示、可点选,不再是数字索引输入框 - [ ] 画面插入:无手动起止时间输入框,时间段按所选句子自动估算 - [ ] 标题预设网格与智能剪辑视觉完全一致、不再重叠 - [ ] 严格只改上述问题,其他 UI/功能保持不变,不破坏现有页面 - [ ] TypeScript 类型安全,PR CI 全绿 参考文件: - 前端页面目录:apps/web/src/pages/ai-avatar/ - 智能剪辑标题样式:apps/web/src/pages/generate/components/title/TitleStylePanel.tsx、TitlePresetsGrid.tsx;样式 apps/web/src/pages/generate/generate.css(~1656-1760行) - 素材库 API:apps/web/src/api/assets/libraries.ts、assets.ts - 后端渲染:apps/api/app/services/ai_avatar_render_service.py;packages/domain/video_filter_builder.py(build_broll_overlay_filter)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: xiaoxia/xiaoxia-saas#1809