# video2slides

把一段长视频（演讲 / 课程录屏）按固定间隔抽帧，逐帧比差异，拖动阈值就能把重复画面变灰、留下关键变化（≈ 幻灯片翻页点）。

线上：<https://video2slides.famzheng.me>

## 架构

跟 cube 其它 app 同款：Rust + axum + `cube-core`，前端纯静态单页（零构建）。唯一特殊处——依赖 `ffmpeg`/`ffprobe`，所以镜像不是 `FROM scratch` 而是 `debian-slim` 装 ffmpeg + 拷静态 musl binary。

- 后端 `src/`：`core.rs`（存储 / 后台任务 / ffmpeg 抽帧 / image crate 逐帧灰度 MAE 差异）、`handlers.rs`（REST）、`main.rs`（路由）。
- 前端 `frontend/index.html`：上传(进度) → 分析(进度) → 结果网格；顶部常驻 toolbar（阈值滑块 + 仅显示保留帧 + 保留/总数 + 分页），悬停缩略图浮出彩色大图。

## 流程

1. **上传** —— 拖拽或选文件，multipart 流式落盘，进度条到 100% 后 ffprobe 校验。
2. **分析** —— 设「每隔 N 秒抽一帧」（默认 8），`ffmpeg fps=1/N` 抽帧（限宽 1280），逐帧生成缩略图并算相邻帧灰度逐像素 MAE（0–100）。后台线程跑，前端轮询进度。
3. **挑帧** —— `diff ≥ 阈值` = 关键变化高亮保留；`< 阈值` = 跟上一帧太像变灰。纯前端实时切换，不回后端。

## 隔离与存储

- 前端在 `localStorage` 存随机 `v2s_client`，所有请求带 `X-Client-Id`，后端按 client 分目录。换浏览器 = 换身份，互相看不到。
- 每个视频一个目录：`source.*` 原片、`frames/` 抽出的彩色帧（大图预览）、`thumbs/` 缩略图、`meta.json`（含每帧时间戳与 diff）。
- 线上数据落 hostPath `/var/lib/cube/video2slides`（单节点 k3s，pod 重启不丢）。

## 本地跑

```bash
# 后端（数据 / 前端目录用 env 指过去，端口 8080）
VIDEO2SLIDES_DATA_DIR=/tmp/v2sdata VIDEO2SLIDES_DIST_DIR=apps/video2slides/frontend \
  cargo run -p video2slides
```

打开 <http://localhost:8080>。需要本机有 `ffmpeg` / `ffprobe`。

## 部署

push 到 master 且改了 `apps/video2slides/**` → `.gitea/workflows/deploy-video2slides.yml` 自动 build musl → 打 debian+ffmpeg 镜像（`--no-cache`）→ push registry → `kubectl apply` + rollout。

namespace `cube-video2slides`，已手工建好 `registry-creds`（从别的 ns 拷的，不进 git）。换 ns 重建命令：

```bash
kubectl -n cube-webgl get secret registry-creds -o yaml \
  | sed 's/namespace: cube-webgl/namespace: cube-video2slides/' \
  | kubectl apply -f -
```
