目标(已确认)
「全部场次 + 点场次」与「选集 + 点同一场次」读写同一
storyboard_graph_state键:(project_id, episode_id=剧集节点 id, chapter_id=场次节点 id)。不需要兜底、不考虑历史兼容:可删除/收紧依赖
__all__/STORYBOARD_SCOPE_ALL的故事板前端路径;遗留库中仅__all__键下的 graph 行可视为可丢弃(不迁移)。以项目最优解落地:单一解析函数 + 全链路同一
episodeId,避免双轨。
核心结论
场次节点已有
chapter_id(剧集 id):list_nodes_by_typescene 分支LEFT JOIN edges ... contains→source_node_id as chapter_id。当前缺口:
StoryboardTab中sceneGraphEpisodeId在未选集时落到STORYBOARD_SCOPE_ALL,与「选集」下的真实episode_id分裂。
推荐实现(最优、改动面收敛)
1. 单一「故事板剧集作用域」解析(前端)
新增小工具(例如 ui/src/domain/storyboardEpisodeScope.ts)或内联 useMemo:
// 语义:显式选集 > App 传入的 chapter > 当前场次所属剧集
resolvedStoryboardEpisodeId =
(activeChapterId?.trim() ||
chapter?.id?.trim() ||
activeScene?.chapter_id?.trim() ||
"");StoryboardTab:sceneGraphEpisodeId改为上述resolvedStoryboardEpisodeId(不再|| STORYBOARD_SCOPE_ALL)。无场次:不加载 graph(现有逻辑已处理)。
有场次但
resolved为空:视为数据损坏/孤儿场次 — 不兜底:toast 固定文案(如「场次未关联剧集,无法加载故事板画布」),loadStoryboardGraph/save不调用;与「不要兼容」一致。
2. 与 graph 键一致的所有调用点(前端)
以下必须使用同一 resolvedStoryboardEpisodeId(从 StoryboardTab 下传或从 App 用相同公式计算,避免分叉):
位置 | 调整 |
|---|---|
|
|
|
|
|
|
| |
与垫图/场次上下文一致:传 | |
|
3. [sceneStoryboardChildNodes.ts](d:/00Dev/bgxiong-ai-story/ui/src/domain/sceneStoryboardChildNodes.ts)
删除
episodeId默认值STORYBOARD_SCOPE_ALL;改为调用方必传 已解析 的剧集 id。若
episodeId为空:直接返回[]或throw(二选一;推荐返回[]+ 上层 toast,避免未处理异常)。
4. 常量与类型清理
[storyboardGraph.ts](d:/00Dev/bgxiong-ai-story/ui/src/domain/storyboardGraph.ts):STORYBOARD_SCOPE_ALL若仅故事板 graph 使用,可删除并全量替换;若 片段画布等仍用__all__(见[types.ts](d:/00Dev/bgxiong-ai-story/ui/src/components/segment-canvas/types.ts)、AppClips),则保留常量但 故事板模块禁止再引用。[useStoryboardSceneGraph](d:/00Dev/bgxiong-ai-story/ui/src/components/storyboard/hooks/useStoryboardSceneGraph.ts):移除仅用于__all__回退的 import/拼接。
5. 后端(可选收紧,与「无兜底」对齐)
[storyboard_graph::normalize_scope_id](d:/00Dev/bgxiong-ai-story/src-tauri/src/storyboard_graph.rs):对load_storyboard_graph_state/upsert_storyboard_graph_state的入口,若trim为空则Err而非写入/读取__all__(需同步改[commands/storyboard.rs](d:/00Dev/bgxiong-ai-story/src-tauri/src/commands/storyboard.rs)三处normalize_scope_id)。风险:仅当保证前端永远传非空剧集 id 时安全;否则 Tauri 命令会报错(符合「严格」)。
文档注释:
chapter_scene_board_pipeline.rs1388 行附近 更新为「episode_scope_id必须为剧集节点 id,与前端一致」。
6. 数据(不兼容策略)
不编写迁移合并
__all__→ 真实剧集:旧行自然废弃。可选(本地开发):手动删
storyboard_graph_state中episode_id='__all__'的行;不作为代码交付必选项。
验证
选集 A → 选场次 S → 改画布 → 切「全部场次」→ 再点 S:布局与节点与选集时一致。
从未选集路径进入:仅点 S(
activeScene.chapter_id有值):同上。清除场次或孤儿场次:
resolved为空时行为符合预期(不静默读__all__)。
实施任务清单
引入
resolvedStoryboardEpisodeId解析并接入StoryboardTab+ 所有子 hook / API 参数。更新
App.refreshStoryboardShots与sceneStoryboardChildNodes(去默认__all__)。删除故事板路径上对
STORYBOARD_SCOPE_ALL的依赖;保留或收缩常量定义。(可选)后端
normalize_scope_id对空串改为Err+cargo check。手动回归两条路径 +
npm run build/ 相关ReadLints。
基于 Rust + WebGPU 的技术栈是目前高性能跨平台开发(Native + Web)的最前沿方案。对于追求性能和系统稳定性的开发者来说,这套组合几乎是“终极形态”。
以下是这套技术栈的核心构成及入门路径:
1. 核心架构:wgpu 生态
在 Rust 社区中,wgpu 是 WebGPU 规范的旗舰级实现。它不仅能让代码运行在浏览器中,还能直接调用 Windows (Direct3D 12)、macOS (Metal) 和 Linux (Vulkan) 的原生驱动。
wgpu-rs(核心库): 提供安全的 Rust 绑定。WGSL (WebGPU Shading Language): 官方指定的着色器语言,语法类似 Rust,易于上手,且避开了 GLSL 的历史包袱。
naga (着色器翻译器): 负责将 WGSL 翻译为底层 API 能理解的指令。
2. 为什么选择 Rust + WebGPU?
这套方案之所以强大,是因为它解决了两个痛点:内存安全与跨平台统一性。
3. 入门技术栈建议
如果你准备从零开始构建一个高性能工具(例如 AI 图像处理或视频滤镜引擎),可以参考以下配置:
UI 层: egui 或 iced。这两个库在 Rust 生态中非常流行,且都完美支持
wgpu后端,适合快速构建跨平台工具界面。窗口管理: winit。这是 Rust 处理窗口、输入事件的事实标准。
数学运算: nalgebra 或 glam。后者专门为图形学优化,性能极佳。
Web 部署: wasm-bindgen。将你的 Rust 逻辑打包成 WebAssembly。
4. 关键应用场景:AI 推理与视频处理
对于本地 AI 推理,你可以利用 WebGPU 的计算着色器 (Compute Shader) 直接对张量进行并行运算。
模型转换: 将模型权重的二进制数据映射到 GPU 的 Storage Buffer。
并行计算: 在 WGSL 中编写计算内核(Kernel),实现类似矩阵乘法 (GEMM) 的操作。
零拷贝: 借助 Rust 的高效内存布局,减少 CPU 与 GPU 之间的数据交换延迟。
快速开始建议
环境配置: 确保 Rust 环境已更新,安装
cargo。克隆 Demo: 到 GitHub 搜索
gfx-rs/wgpu仓库,查看其examples文件夹。里面有从简单的三角形渲染到复杂的计算着色器应用。学习 WGSL: 如果你熟悉 Rust,你会发现 WGSL 的语法非常亲切。
小贴士: 由于你可能处理大量资源或追求极高性能,建议在开发时开启
wgpu的验证层(Validation Layers),它能帮你捕捉到 90% 以上的非法显存访问错误。
到 2026 年,WebGPU 已经正式告别了“试验田”阶段,成为了 Web 高性能计算和图形渲染的绝对标准。
如果说 WebGL 是在浏览器里“画图”,那么 WebGPU 则是在浏览器里“直接操控 GPU”。
以下是 WebGPU 当前发展的关键维度:
1. 核心生态:从“尝鲜”转向“默认”
WebGPU 1.0 在 2023 年发布后,经历了两年的高速迭代。
引擎全面转向: Three.js 和 Babylon.js 等主流 Web 图形引擎已经将 WebGPU 作为首选后端。相比 WebGL,WebGPU 在处理复杂场景(如数万个独立对象的渲染)时,CPU 开销降低了约 80%。
原生级性能: 借助 WebAssembly (Wasm) 和 WebGPU 的深度集成,现在的 Web 应用可以实现接近原生桌面软件的图形表现。这使得云端视频剪辑、高级调色工具和复杂的 3D 设计软件(如 Web 版 CAD)在性能上几乎没有短板。
2. AI 浪潮下的“杀手锏”:计算着色器 (Compute Shaders)
WebGPU 与 WebGL 最大的区别在于其强大的通用计算能力。
端侧 AI (On-device AI): 这是 WebGPU 发展最迅猛的领域。由于其提供了对现代 GPU 特性(如共享内存、原子操作)的访问,诸如 WebLLM 和 Transformers.js 等项目可以让大语言模型(LLM)和 Stable Diffusion 直接在用户的本地 GPU 上运行,无需上传数据到服务器。
视频处理加速: 对于视频后期从业者而言,WebGPU 允许在浏览器内进行实时的 4K 视频滤镜处理、AI 降噪和自动抠图,其效率是传统 JavaScript 或 WebGL 无法比拟的。
3. 浏览器与硬件兼容性
多端统一: 截至 2026 年,Chrome、Edge、Safari 和 Firefox 的稳定版均已全面支持 WebGPU。它在底层完美映射了系统的原生 API(如 Windows 的 Direct3D 12、macOS 的 Metal、Linux 的 Vulkan)。
移动端爆发: 随着高性能移动芯片的普及,手机端的 WebGPU 支持也已趋于成熟,网页端手游的品质已经开始向主机级画质靠拢。
4. 技术特性演进
FP16 与精度优化: 现在的 WebGPU 已经广泛支持 半精度浮点数 (FP16),这对 AI 推理至关重要,能在减少显存占用的同时提升一倍的运算速度。
子组操作 (Subgroups): 这一高级特性的加入,使得开发者可以更精细地控制 GPU 线程间的通信,进一步压榨硬件性能。
总结:对开发者的影响
对于开发者(尤其是熟悉 Rust 或 C++ 这种底层语言的人)来说,WebGPU 极大地拓宽了 Web 的边界。你不再受限于简单的网页交互,而是可以直接开发高性能的跨平台桌面应用(通过 Electron 加速)或高性能的 Web AI 工具。
既然你对 HTML/CSS 非常熟悉,同时又有处理复杂逻辑、文件系统操作以及加载本地大模型 (LLM) 这种高负载需求,目前的跨平台客户端架构主要集中在以下三个“黄金方案”上。
针对你的需求,我按照性能、成熟度和技术栈匹配度进行了排序:
1. Tauri (首选推荐:极致性能与轻量化)
Tauri 是目前增长最快、最受开发者青睐的方案。它将 UI 交给系统原生的 WebView(Win10 用 Edge/WebView2,Mac 用 WebKit),而后台逻辑则交给 Rust。
为什么适合你:
Web 前端: 你可以用任何喜欢的 Web 框架(React, Vue, 或纯 HTML/CSS)构建 UI。
本地大模型: Rust 是目前处理本地 AI 推理最理想的语言之一。你可以直接调用
llama-cpp-rs或candle等 Rust 库,效率远高于 Node.js。安全性与体积: 它的安装包极小(通常只有几 MB),且由于 Rust 的特性,内存安全管理非常出色。
挑战: 你需要学习一点 Rust 语法来编写后端逻辑(操作文件、调用模型)。
2. Electron (最成熟:生态之王)
Electron 是 VS Code、Discord 和 Slack 的底层架构。它将 Chromium 浏览器和 Node.js 打包在一起。
为什么适合你:
上手难度最低: 前端 UI 和后端逻辑(Node.js)全部使用 JavaScript/TypeScript。
生态极其丰富: 对于加载大模型,你可以直接使用
node-llama-cpp或者onnxruntime-node等成熟的 NPM 包。文件操作: Node.js 的
fs模块处理本地文件非常简单直观。
挑战: 资源占用大(内存怪兽)。由于它自带了一个完整的 Chromium,加载本地大模型时,GPU/内存压力会比 Tauri 大得多。
3. Wails (平衡之选:Go 语言后端)
如果觉得 Rust 太难,又觉得 Electron 太重,Wails 是一个绝佳的中间地带。它使用 Go 语言作为后端。
为什么适合你:
Go 语言逻辑: Go 的语法比 Rust 简单得多,且处理并发和系统 API(文件操作)非常高效。
轻量: 和 Tauri 一样,它使用系统原生的 WebView,不打包 Chromium。
模型支持: 通过 Go 的 CGO 调用
llama.cpp的 C++ 接口非常成熟。
挑战: 在三者中,Wails 的社区插件生态相对较小。
技术方案对比表
针对“加载本地大模型”的深度建议
无论你选择哪种架构,加载大模型(如 Llama 3 或 Qwen)通常有两条路径:
侧边进程 (Sidecar) 模式: 不要在 Electron/Tauri 的主进程里直接运行推理。可以打包一个编译好的
llama.cpp二进制文件作为“侧边服务”,你的 Web 视图通过本地端口(如 localhost:11434)与其通信。这是目前最稳定、解耦最好的方式。WebGPU (未来趋势): 如果你希望完全在 Web 视图内处理,可以关注 WebLLM 项目。它利用 WebGPU 接口,让 HTML 页面直接调用显卡进行推理,不需要编写复杂的后端 C++/Rust 代码,直接在 JS 里写逻辑。
如果你希望现在就开始一个稳定且高性能的项目,我建议: 先尝试 Tauri。虽然 Rust 有学习成本,但它处理文件和本地模型的能力是目前跨平台方案的天花板。
您是否需要我为您整理一份基于 Tauri 运行本地 LLM 的基础项目结构示例?
