From 207fa6f1bcb0ea0718118313b1df67e15ec87366 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 14 May 2026 11:25:46 -0700 Subject: [PATCH] feat: add comprehensive README documentation for Frame Analyzer project --- README.md | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..7d6541f --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# Frame Analyzer + +Frame Analyzer is a local-first browser app for pulling a small set of representative stills out of a video. You load a video file in the browser, scan it for scene changes, review the candidate frames, and then copy or download the stills you want. + +No backend is required for the app itself. Video processing happens in the browser against a local blob URL. + +## What It Does + +- Loads a local video file without uploading it to a server +- Samples the video at a configurable interval +- Scores sampled moments using a hybrid of histogram shift and pixel change +- Picks candidate frames across the full duration of the video instead of clustering around one active section +- Shows thumbnail candidates with timestamps +- Lets you copy a frame as PNG to the clipboard +- Falls back to PNG download if clipboard image write is blocked +- Lets you manually add the current scrubbed frame from the video preview + +## How Selection Works + +The current frame picker is a two-stage pipeline: + +1. The scanner samples the video over time and computes a visual-change score for each sampled moment. +2. The selector first tries to fill the timeline with one strong candidate per time bucket, then backfills additional high-quality frames while preserving temporal spread. + +This is intentionally different from a simple threshold-crossing approach. One-pass threshold gating tends to miss gradual transitions and often returns only one or two frames in videos with slow visual evolution. + +## Stack + +- React 19 +- TypeScript +- Vite +- Native browser video decoding through `HTMLVideoElement` +- Canvas for analysis and frame extraction +- Clipboard API for image copy +- `nginx` for static serving in the containerized deployment + +## Running Locally + +Requirements: + +- Node.js 22 or newer is recommended +- A Chromium-based browser is the safest target for clipboard image support + +Install dependencies: + +```bash +npm install +``` + +Start the dev server: + +```bash +npm run dev +``` + +Build for production: + +```bash +npm run build +``` + +Preview the production build locally: + +```bash +npm run preview +``` + +## Usage + +1. Open the app and select a local video file. +2. Adjust scan settings if needed: + - sample interval + - change threshold + - pixel delta + - minimum gap between captures + - target image count + - candidate pool size + - analysis size +3. Run the scan. +4. Review the candidate gallery. +5. Copy or download the frames you want. +6. Use the video scrubber and `Add current` if you want to add a frame manually. + +## Deployment + +This repo includes CapRover deployment files: + +- [captain-definition](./captain-definition) +- [Dockerfile](./Dockerfile) + +CapRover will build the app with Node, generate the Vite production output, and serve the built files from `nginx`. + +## Project Structure + +```text +src/ + analysis/ + candidateRanking.ts + frameDifference.ts + scanVideo.ts + media/ + canvas.ts + clipboard.ts + video.ts + types/ + scan.ts + App.tsx + main.tsx + styles.css +``` + +## Important Browser Notes + +- Clipboard image writing requires a secure context such as `localhost` or HTTPS. +- Browser codec support varies. MP4/H.264 is the safest general input format. +- Exact frame extraction is limited by browser video seeking behavior. +- The app waits for a rendered post-seek frame before capturing thumbnails or exports, but browser decoding behavior can still vary across engines. + +## Known Limits + +- This is still a heuristic frame picker, not a frame-accurate editor. +- Very long videos can take time because the browser must seek and decode many timestamps. +- Videos with subtle lighting changes, heavy motion, or repeated near-identical scenes may still need manual adjustment or manual frame additions. +- Safari and Firefox may behave differently from Chromium for clipboard support and media decoding.