Files
Fam Zheng a0253e118f
deploy articulate / build-and-deploy (push) Successful in 1m1s
deploy cube / build-and-deploy (push) Successful in 1m22s
deploy karaoke / build-and-deploy (push) Successful in 55s
deploy llm-proxy / build-and-deploy (push) Successful in 1m44s
deploy music / build-and-deploy (push) Successful in 2m14s
deploy notes / build-and-deploy (push) Successful in 1m40s
deploy simpleasm / build-and-deploy (push) Successful in 1m17s
deploy video2slides / build-and-deploy (push) Successful in 39s
deploy werewolf / build-and-deploy (push) Successful in 1m7s
deploy webgl / build-and-deploy (push) Successful in 1m17s
deploy write / build-and-deploy (push) Successful in 1m13s
video2slides: 重构为纯客户端 app(浏览器抽帧 + IndexedDB),后端归零
- 不再上传视频:<video>+canvas 原生解码按时间戳 seek 抽帧,逐帧 256px 灰度
  MAE 算差异,缩略图(320)+大图(1280) 随抽随写 IndexedDB,带进度条+ETA
- 阈值/手动 保留弃用/缩放偏好 持久化到 IndexedDB,刷新仍在
- PDF 导出回到客户端 jsPDF,保留帧逐张 base64 嵌入、单帧处理防 OOM
- 后端删光业务逻辑(core.rs/handlers.rs),main.rs 缩成 cube_core::base 静态服务
- 不再需要 ffmpeg → Dockerfile 回归 FROM scratch;k8s 去掉 hostPath 卷、降资源
- 真浏览器(Playwright)验证:抽帧/差异/阈值/持久化/导出 全通过
2026-06-14 22:25:20 +01:00

37 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# video2slides
把一段长视频(演讲 / 课程录屏)按固定间隔抽帧,逐帧比差异,拖动阈值就能把重复画面变灰、留下关键变化(≈ 幻灯片翻页点)。
线上:<https://video2slides.famzheng.me>
## 纯客户端,无后端
视频**不上传**——浏览器用 `<video>` + canvas 原生解码、按时间戳 seek 抽帧,逐帧差异、缩略图、PDF 导出全在前端。结果(缩略图 + 大图 + 元数据)存 **IndexedDB**,每个浏览器各自持久化、刷新还在,换设备/清缓存即清空。
因此后端没有任何业务逻辑/存储,这个 Rust 进程只是个**静态文件服务器**(`cube_core::base`),把前端发出去而已。也因此镜像回归 cube 惯例:`FROM scratch` + 静态 musl binary,不再需要 ffmpeg / hostPath。
为什么不上传 + 不用服务端 ffmpeg:大视频(1~5GB)上传慢且易失败,服务端还得存。纯客户端零上传、无限扩展,且内存安全——抽帧逐帧即弃、只在内存留一张 256px 灰度算 diff;缩略图/大图随抽随写 IndexedDB。
## 流程
1. **选视频** —— 拖拽或选本地文件(不上传)。
2. **处理** —— 设「每隔 N 秒抽一帧」(默认 8)→ `<video>` 逐点 seek、canvas 抓帧 → 生成缩略图(320px)+大图(1280px) 写 IndexedDB,相邻帧 256px 灰度逐像素 MAE(0–100) 算差异。带进度条 + 预计剩余(ETA)。
3. **挑帧** —— toolbar 常驻:差异阈值滑块(`diff ≥ 阈值`=关键变化高亮保留,`<`=变灰)、缩略图缩放、仅显示保留、保留/总数、分页;**点击卡片手动切换 保留/弃用**(覆盖阈值,带角标 + 重置);悬停缩略图浮彩色大图。阈值/手动选择都存回 IndexedDB。
4. **导出 PDF** —— 客户端 jsPDF,把保留帧逐张(大图 JPEG 以 base64 直接嵌入、单帧处理避免 OOM)打成 PDF 下载。
## 格式支持
走浏览器原生解码,支持浏览器能播的格式(mp4/H.264、webm/VP9/AV1 等,演讲视频基本都是 mp4)。mkv/avi/冷门编码可能读不了——浏览器播不了就处理不了。
## 本地跑
```bash
VIDEO2SLIDES_DIST_DIR=apps/video2slides/frontend cargo run -p video2slides
```
打开 <http://localhost:8080>。后端纯静态,不需要 ffmpeg。
## 部署
push 到 master 改 `apps/video2slides/**` → CI build musl → `FROM scratch` 镜像 → push registry → `kubectl apply` + rollout。namespace `cube-video2slides``registry-creds` 已手工建好(不进 git)。