# 快速预览故事板系统 — 调研综合 + 设计方案 ## 一、调研结论 ### 1.1 当前 P10b 的产出(现状) 当前 P10b 快速预览产出的是**逐镜头的短视频片段(MP4)**——用 FFmpeg 把 E-Konte 关键帧图 + TTS 音频合成 slideshow 视频。这些片段散落在画布上,无法一览全局。 **Kai 的需求**:不是看每个镜头的小视频,而是要一张**全景故事板(Storyboard Board)**——像日本动画的 E-Konte 纸面一样,一页看到全部镜头的构图、运镜、时长、对白,用于拍摄前的整体审查。 ### 1.2 业内最佳实践 #### 日本 E-Konte 模式(信息密度最高) - 每页 5 格分镜(Koma),每格包含: - 上半:构图 sketch(人物位置/背景简略/镜头方向箭头) - 下半:CUT编号 | 景别 | 运镜 | 秒数 | 对白 | 动作 | 背景 | 音效 | 转场 | 演出备注 - 哲学:**演出家在纸上完成 80% 的导演工作** #### 西方 Storyboard 工具模式(交互性最强) - StudioBinder / Boords / Shot Lister: - Grid 布局(3-5 列),每卡 = 缩略图 + shot 元数据 - 支持拖拽排序、过滤(按场景/角色/景别)、缩放 - Timeline 视图:横向时间轴展示镜头时长比例 - Table 视图:纯数据表格,可编辑 ### 1.3 我们应该取什么 **融合 E-Konte 的信息密度 + 西方工具的交互性**: | 维度 | 选择 | 理由 | |------|------|------| | 布局 | Grid 分镜网格(竖向滚动,按场景分组) | 一览全局,符合 Kai "一张图看全"需求 | | 每格信息层 | E-Konte 式 6 层 | 缩略图 + 编号 + 景别运镜 + 时长 + 对白摘要 + 转场 | | 交互 | 缩放 + 场景分组折叠 + hover 详情 | 审查时需要快速扫览 + 深入查看 | | 数据来源 | P09 分镜表 + P09 E-Konte 图 + P10 语音时长 | 已有数据,不需新增生成步骤 | --- ## 二、系统设计 ### 2.1 新增产物:Storyboard Board(分镜故事板) **不是新增管线阶段**,而是 P10b 的**新增产出类型**——在现有快速预览基础上,增加一个结构化的故事板 JSON + 渲染 HTML。 #### 产出数据结构 ```json { "type": "storyboard_board", "episode_id": "ep-xxx", "generated_at": "2026-08-08T10:00:00Z", "scenes": [ { "scene_id": "S1", "scene_title": "陆衍舟的办公室", "shots": [ { "shot_id": "S1_001", "shot_number": "A-1", "thumbnail": "/oss/xxx/e_konte_S1_001.png", "shot_scale": "CU", "camera_motion": "static", "framing": "居中构图", "duration_sec": 3.5, "dialogue_summary": "陆衍舟:「你找我?」", "characters": ["陆衍舟"], "transition_from": "cut", "transition_to": "cut", "emotion": "tense", "action_note": "翻看文件,头也不抬", "preview_clip": "/oss/xxx/preview_S1_001.mp4" } ] } ], "stats": { "total_shots": 28, "total_duration_sec": 145.5, "total_scenes": 6 } } ``` ### 2.2 数据来源映射 | 故事板字段 | 来源 | 备注 | |-----------|------|------| | shot_id / shot_number | P09 shot-list | 直接取 | | thumbnail | P09 E-Konte 图 | 优先用 E-Konte,fallback 用场景图 | | shot_scale | P06 时空剧本 L2 cinematographer | CU/MS/LS 等 | | camera_motion | P06 时空剧本 L2 cinematographer | static/pan/tilt/dolly 等 | | framing | P06 时空剧本 L2 cinematographer | 构图描述 | | duration_sec | P09 shot-list | 每镜头时长 | | dialogue_summary | P03 剧本初稿 / P09 shot-list | 截取前 20 字 | | characters | P09 shot-list character_refs | 角色名列表 | | transition_from/to | P09 transition-design | cut/fade/dissolve/whip_pan | | emotion | P06 时空剧本 L2 cinematographer | 镜头情绪 | | action_note | P03 剧本 / P06 时空剧本 | 动作描述 | | preview_clip | P10b rapid-preview-clips | 可选,有则显示播放按钮 | ### 2.3 KMC 管线变更 #### P10b 新增 OUTPUT_SLOT ```python OUTPUT_SLOTS = ["rapid-preview-clips", "episode-meta", "storyboard-board"] ``` P10b 在生成快速预览后,**用已有数据组装** storyboard-board JSON: - 读 P09 shot-list(已有 INPUT:e-konte-sheets,但需要追加 shot-list) - 读 P06 spatio-temporal-script(新增 INPUT_SLOT) - 读 P09 transition-design(新增 INPUT_SLOT) - 组装为 storyboard_board JSON → asset_bus_write("storyboard-board", payload) #### P10b INPUT_SLOTS 变更 ```python # 旧 INPUT_SLOTS = ["voice-clips", "voice-timeline", "e-konte-sheets"] # 新 INPUT_SLOTS = ["voice-clips", "voice-timeline", "e-konte-sheets", "shot-list", "spatio-temporal-script", "transition-design"] ``` ### 2.4 画布集成 #### 方案:独立页面(新 viewMode) 在无限画布中新增一个 viewMode:`storyboard`(与现有 `canvas` / `timeline` 并列)。 访问路径:`/infinite-canvas/?view=storyboard` 或画布内切换按钮。 #### 页面布局 ``` ┌──────────────────────────────────────────────────────┐ │ ← 返回画布 │ 分镜故事板 │ 总镜头: 28 总时长: 2:25 │ ├──────────────────────────────────────────────────────┤ │ ▼ 场景1:陆衍舟的办公室 (5 shots, 18.5s) │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ [缩略图] │ │ [缩略图] │ │ [缩略图] │ │ [缩略图] │ │ [缩略图] │ │ │ A-1 CU │ │ A-2 MS │ │ A-3 CU │ │ A-4 LS │ │ A-5 CU │ │ │ static │ │ pan→ │ │ static │ │ dolly↓ │ │ static │ │ │ 3.5s │ │ 4.0s │ │ 2.5s │ │ 5.0s │ │ 3.5s │ │ │ "你找我"│ │ "坐" │ │ "..." │ │ "出去" │ │ "..." │ │ │ ▶播放 │ │ │ │ │ │ ▶播放 │ │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ ▼ 场景2:走廊 (3 shots, 12.0s) │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ ... │ │ ... │ │ ... │ │ │ └────────┘ └────────┘ └────────┘ │ ├──────────────────────────────────────────────────────┤ │ 场景3 | 场景4 | 场景5 | 场景6 [全部展开/折叠] │ └──────────────────────────────────────────────────────┘ ``` #### 每格卡片设计 ``` ┌─────────────────────┐ │ │ │ [E-Konte 缩略图] │ ← 16:9 裁切展示 │ │ ├─────────────────────┤ │ A-1 CU · static │ ← 编号 + 景别 + 运镜 │ 3.5s ✂ cut → cut │ ← 时长 + 转场 │ "你找我?" │ ← 对白摘要(灰色小字) │ 🎭 陆衍舟 │ ← 角色(图标+名) │ ▶ 播放预览 │ ← 有 preview_clip 时显示 └─────────────────────┘ ``` hover 展开: - action_note(动作描述) - emotion(情绪标签) - framing(构图说明) - 完整对白 ### 2.5 自动同步设计 #### canvas_sync 变更 P10b 的 `_PHASE_OUTPUT_MAP` 追加 storyboard-board 条目: ```python "p10b": [ ("variants_generated", "预览生成数", "script", False), ("variants_degraded", "预览降级数", "script", False), ("rapid_preview_clips", "快速预览片段", "video", False), ("storyboard_board", "分镜故事板", "script", False), # 新增 ], ``` storyboard-board 作为 `script` 类型节点(不展开为子节点,而是一个摘要节点,点击打开故事板页面)。 #### API 设计 新增 API 端点: ``` GET /api/v1/storyboard/:projectId/:episodesId ``` 返回 storyboard_board JSON。前端 storyboard viewMode 调用此 API 渲染。 数据来源: 1. 优先从 o_assets 查询 type=storyboard_board 2. fallback 从 `.pipeline-assets/storyboard-board.json` 读取 3. 实时组装(如果前两者都没有,从 shot-list + e-konte 实时拼装) --- ## 三、执行计划 ### Phase 1: KMC 管线变更(P10b 组装故事板 JSON) - 改 p10b_rapid_preview.py:新增 INPUT_SLOTS + storyboard-board 产出 - 改 ASSET_SCHEMA:新增 storyboard-board slot 定义 - 改 runner.py:确保新 slot 正确分发 - 测试:storyboard-board JSON 生成正确 ### Phase 2: 画布后端 API - 新增 `/api/v1/storyboard/:projectId/:episodesId` 路由 - canvas_sync 追加 storyboard-board 映射 - 测试:API 返回正确数据 ### Phase 3: 画布前端页面 - 新增 viewMode: storyboard - 新增 StoryboardBoard.tsx 组件 - Grid 布局 + 场景分组 + 卡片设计 - hover 详情展开 - preview clip 播放 ### Phase 4: canvas_sync 自动同步 - P10b 完成后自动同步 storyboard-board 到画布 - 验证端到端流程