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