feat: add comprehensive README documentation for Frame Analyzer project
This commit is contained in:
@@ -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.
|
||||||
Reference in New Issue
Block a user