sframe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 02a1b32f6354d21c58f4d2bd92c608b2ec120336
parent 155c468d6c81a5f1a7d352f27ffd8f354dcad6c2
Author: Kris Yotam <krisyotam@protonmail.com>
Date:   Fri, 20 Feb 2026 09:35:16 -0600

Add README

Diffstat:
AREADME.md | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 116 insertions(+), 0 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,116 @@ +# Simple Frame + +A lightweight command-line tool for extracting unique frames from video +files. Built for research workflows where you need to dissect video +content into distinct, non-duplicate images with timestamps. + +Simple Frame uses perceptual hashing to compare consecutive frames and +only saves those that are visually distinct, drastically reducing the +manual sorting required when working with extracted video stills. + +Written in C following the [suckless philosophy](https://suckless.org/philosophy/). + +## Usage + +``` +sframe [-v] [-t threshold] [-f png|jpg] [-o outdir] video [video...] +``` + +### Options + +| Flag | Description | Default | +|------|-------------|---------| +| `-t N` | Hash threshold (0–64). Lower = stricter, fewer duplicates pass through. 0 removes only exact duplicates. | `8` | +| `-f fmt` | Output image format: `png` or `jpg` | `png` | +| `-o dir` | Output directory | `~/frames` | +| `-v` | Print version and exit | | + +### Examples + +Extract unique frames from a video: + +```sh +sframe lecture.mp4 +``` + +Use a stricter threshold with JPEG output: + +```sh +sframe -t 4 -f jpg documentary.mkv +``` + +Process multiple videos into a custom directory: + +```sh +sframe -o /tmp/research clip1.mp4 clip2.webm +``` + +## Output Structure + +``` +~/frames/ +└── lecture/ + ├── lecture-00-00-01.234.png + ├── lecture-00-00-15.678.png + ├── lecture-00-01-02.345.png + └── ... +``` + +Each video gets its own subdirectory. Frames are named as +`<video-name>-HH-MM-SS.mmm.<ext>` where the timestamp corresponds to +the frame's position in the video. + +## How It Works + +1. Decodes every frame of the video using FFmpeg +2. Scales each frame to 8x8 grayscale +3. Computes a 64-bit average perceptual hash +4. Compares the hamming distance against the previously saved frame's hash +5. Saves the frame only if the distance exceeds the threshold + +This approach is fast and effective at eliminating duplicate and +near-duplicate frames (static shots, slow pans, talking heads with +minimal movement) while preserving genuine scene changes and visually +distinct content. + +### Threshold Guide + +| Value | Behavior | +|-------|----------| +| `0` | Only removes pixel-identical frames | +| `4` | Very strict — catches near-identical frames | +| `8` | Balanced — good default for most content | +| `16` | Loose — aggressive duplicate removal | +| `32+` | Very aggressive — only major scene changes | + +## Dependencies + +- FFmpeg libraries: `libavformat`, `libavcodec`, `libavutil`, `libswscale` +- `libpng` +- `libjpeg` + +### Arch Linux + +```sh +pacman -S ffmpeg libpng libjpeg-turbo +``` + +### Debian/Ubuntu + +```sh +apt install libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libpng-dev libjpeg-dev +``` + +## Building + +```sh +make +sudo make install +``` + +Edit `config.mk` to change compile-time defaults (output format, +default threshold). + +## License + +MIT