feat(storyboard): SB-6 序列预览——按叙事链把整条分镜从头播一遍 - #222
Merged
Conversation
M4 E1。分镜线第一个「打开就能看见」的成果:顶栏点「序列预览」,按 narrative 链顺序把每镜的最新产物依次放出来,没生成的镜显备注占位且照样计时——预览的 总时长就是成片的预期时长。 新 features/storyboard 三层: - models/sequence_shot.dart 播放清单条目(一镜放什么、放多久) - util/sequence_builder.dart 画布节点+边 → 播放清单(纯函数,全单测) - widgets/sequence_preview_dialog.dart 只负责「放」与「推进」 排序复用 SB-5 的 narrative_order、产物查找复用 EX-1' 首建的 node_artifacts ——本卡只消费,不再造第二套(卡面裁决)。 **关键设计:折叠。** 「用本镜备注生成图像」建出来的真实拓扑是 shot ──narrative──> image config ──sourceNodeId──> image result, 也就是 config 节点也在 narrative 链上。照单把每个链上节点都当一镜,一条 3 镜的分镜会播出 6 条(占位/出图交替)。而那是当前把图接进分镜链的**唯一** 入口——不折叠等于这张卡不可用。规则:节点把产物借给前面的 shot 后不再单独 成镜;已被借走的产物不会被第二个 shot 再借(多 shot 指向同一 config 时)。 **推进两套。** 图片/占位走定时器(缺省 3s);视频以真实播放进度推进 (position ≥ duration),**外加兜底定时器**——播放器打不开文件、进度流不动、 时长拿不到时,没有它就永远卡死在这一镜(余量 +1.5s,正常播放先于它触发)。 **media_kit 生命周期**(卡面点名泄漏高发):全对话框只 create 一个 handle、 换镜靠 open 换源、只在 initState 建只在 dispose 放、**纯图片序列完全不 create**(不该为一堆静态图唤起 media_kit);_epoch 计数器防迟到回调推进一个 早已翻过去的镜。 入口=顶栏「序列预览」,画布有 narrative 边才可用(可用性只 watch 边,拖动 节点不重建顶栏)。 ARB +11 键(en/zh 同 commit,gen-l10n 已跑并提交 generated/)。 测试 +30:builder 14 例(折叠/借用只发生一次/时长优先级/取最新产物/跳过 规则)、dialog 12 例(handle 只建一个且必被 dispose、纯图不 create、按时长 推进、暂停真停、末镜不越界、position 推进先于兜底、拿不到 duration 时兜底 接管)、顶栏 4 例(门控只认 narrative 边)。 顺带被仓库硬编码视觉值闸门抓到一处 `InkSpacing.xs / 2`——改用整档而不是 放松守卫。 analyze 0 issue;全量非 golden +1878 / 0 失败 / 66 skip(原 1848)。 文档:features/storyboard/README.md、BOARD M3 分镜行 + 近期落地表、 docs/CLAUDE.md 结构快照(新增目录同 commit 更新,含 canvas/export util 补注)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
M4 E1,接 #219(SB-5)/ #220(artifacts util)/ #221(SB-3)。分镜线第一个「打开就能看见」的成果:顶栏点「序列预览」,按 narrative 链顺序把每镜的最新产物依次放出来。没生成的镜显备注占位且照样计时 —— 预览的总时长就是成片的预期时长。
分层
排序复用 SB-5 的
narrative_order,产物查找复用 EX-1′ 首建的node_artifacts—— 本卡只消费,不再造第二套(卡面裁决)。关键设计:折叠
「用本镜备注生成图像」建出来的真实拓扑是:
config 节点也在 narrative 链上。 照单把每个链上节点都当一镜,一条 3 镜的分镜会播出 6 条(shot1 占位、cfg1 出图、shot2 占位、cfg2 出图……)。
这不是边角情况 ——
_generateImageFromNotes是当前把图接进分镜链的唯一入口,不折叠等于这张卡不可用。规则:节点把产物借给前面的 shot 后不再单独成镜;已被借走的产物不会被第二个 shot 再借(多个 shot 指向同一 config 的分叉/汇合场景)。第二条是我写完实现跑测试才发现漏的 —— 原先只挡住了 config 不单独成镜,没挡住同一张图被两镜共用。
推进两套
durationMs(缺省 3s)position ≥ duration),外加兜底定时器视频那条兜底不是冗余:播放器打不开文件、进度流不动、时长拿不到时,没有它就永远卡死在这一镜。余量
+1.5s,正常播放先于它触发。有两条用例分别钉「position 推进先于兜底」和「拿不到 duration 时兜底接管」。media_kit 生命周期(卡面点名泄漏高发)
open()换源initState建、只在dispose放,中途任何路径都不再 create_epoch计数器防迟到回调:换镜时自增,异步回调(open 完成、position 事件)拿它比对,不会推进一个早已翻过去的镜三条都有用例钉死,包括「拆掉 widget 后
handle.dispose被调用一次」。入口
顶栏「序列预览」,画布有 narrative 边才可用。可用性只 watch 边不 watch 节点 —— 拖动节点不重建顶栏,且"一堆互不相连的节点"本来就不构成序列。有用例钉死只有 data / generation_source 边时仍禁用。
验证
gen-l10n已跑并提交generated/)flutter analyze lib test→ 0 issuesflutter test --exclude-tags golden→ +1878 / 0 失败 / 66 skip(feat(canvas): SB-3 镜头级参数——shot 面板预期时长 / 预期运镜 #221 后是 1848)顺带被仓库的硬编码视觉值闸门抓到一处
InkSpacing.xs / 2—— 改用整档而不是放松守卫。文档
features/storyboard/README.md(含折叠的来龙去脉与 media_kit 约束)、BOARD M3 分镜行 + 近期落地表、docs/CLAUDE.md结构快照(新增目录同 commit 更新,顺带补注 canvas/export 的新 util)。说明
未跑两路对抗评审 —— 本会话指令是不主动派 subagent。这张卡是 L 级、含 media_kit 生命周期与定时器竞态,是这一轮四张卡里最该过一次
/code-review的。另外真实播放(媒体解码、换源时序)测试覆盖不到,需要手动回归。🤖 Generated with Claude Code