Files
cube/apps/video2slides
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
..

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/冷门编码可能读不了——浏览器播不了就处理不了。

本地跑

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-video2slidesregistry-creds 已手工建好(不进 git)。