Video Process Demo

Rust 后端原样提供 video.h264Next.js 前端用 WebCodecs 在浏览器里完成流式切帧、本地帧缓存、单画布播放和帧拖动定位。刷新后优先恢复本地帧,不需要重新拉完整视频再解码。

启动后端

cargo run

后端默认监听 http://localhost:8080,视频地址是 http://localhost:8080/video.h264。 仓库里不包含这个大体积示例视频,请把 video.h264 放到项目根目录,或通过 NEXT_PUBLIC_VIDEO_URL 指向你自己的 H.264 地址。

启动前端

cd web
npm install
NEXT_PUBLIC_VIDEO_URL=http://localhost:8080/video.h264 npm run dev

打开 http://localhost:3000 即可。

前端架构

前端分成四层:

  • 传输缓存:web/lib/video-cache.tsCache Storage 保存原始 video.h264 响应。
  • 解析切帧:web/lib/h264.ts 把 Annex B 字节流拆成 access unit识别 SPS/PPS 和帧边界。
  • 帧持久化:web/lib/frame-store.tsIndexedDB 保存 CachedFrameSession,每帧以 Blob 形式落盘,刷新后可直接恢复。
  • 播放控制:web/components/VideoFrameViewer.tsx 负责切帧、恢复、单画布播放、拖动条跳帧和缓存清理。

运行流程

  1. 页面先查本地帧会话,命中则直接把 Blob 恢复成 objectURL,无需重新请求后端。
  2. 未命中时再去请求 video.h264,并边下载边解析 SPS/PPS 和 access unit。
  3. 每个 VideoFrame 会先画到离屏 canvas再导出成 WebP Blob,同时生成缩略图对象 URL。
  4. 全部帧完成后,会把会话写入 IndexedDB,然后尽量清掉原始 video.h264 的缓存,减少重复占用。
  5. 播放区只用一个 canvas通过 requestAnimationFrame 按时间戳切帧;拖动条则直接 jumpToFrame() 到指定帧。

缓存策略

  • 原始视频缓存放在 Cache Storage,适合保存完整的 fetch 响应。
  • 切好的帧和元数据放在 IndexedDB,避免把大体积帧塞进一个 JSON。
  • 页面提供“申请持久化”按钮,会调用 navigator.storage.persist(),降低浏览器回收缓存的概率。
  • “清空缓存”会同时删除帧会话和原始视频缓存;下次打开会重新请求后端并重新切帧。
  • 当前实现还保留了旧版 Cache Storage 帧清单的迁移逻辑,便于升级已有缓存。

关键文件

  • web/components/VideoFrameViewer.tsx:主界面、播放、拖动条、缓存状态。
  • web/lib/h264.tsH.264 Annex B 解析、SPS/PPS、WebCodecs 配置。
  • web/lib/frame-store.ts:帧会话读写、校验、迁移。
  • web/lib/video-cache.ts:原始视频响应缓存。

生成图谱

graphify-out/ 是生成物,不建议提交到仓库。你在其他项目里想复用这套分析方式时,可以在目标项目根目录重新生成:

graphify .

增量更新:

graphify . --update

如果你在 Codex 里操作,直接对目标项目说这句就够了:

请对当前项目目录运行 graphify生成 graphify-out并重点输出 God Nodes、Surprising Connections 和 Suggested Questions。

生成后会得到这些文件:

  • graphify-out/graph.json
  • graphify-out/graph.html
  • graphify-out/GRAPH_REPORT.md
  • graphify-out/manifest.json

备注

前端依赖浏览器的 WebCodecs、Cache Storage 和 IndexedDB 能力,建议使用 Chromium / Edge。

Description
No description provided
Readme 60 KiB
Languages
TypeScript 84.5%
CSS 11.7%
Rust 3.6%
JavaScript 0.2%