~kris/hacks

sframe

0d0fb70a98aef8ae0b84af35faa63c34f8062524 — Kris Yotam 4 months ago 236dbd8 main
convert README.md to README.txt
2 files changed, 109 insertions(+), 116 deletions(-)

D README.md
A README.txt
D README.md => README.md +0 -116
@@ 1,116 0,0 @@
# 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

A README.txt => README.txt +109 -0
@@ 0,0 1,109 @@
sframe -- 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.

sframe 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.


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         8
             duplicates pass through. 0 removes only exact
             duplicates.
    -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:
      sframe lecture.mp4

    Use a stricter threshold with JPEG output:
      sframe -t 4 -f jpg documentary.mkv

    Process multiple videos into a custom directory:
      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:
    pacman -S ffmpeg libpng libjpeg-turbo

  Debian/Ubuntu:
    apt install libavformat-dev libavcodec-dev libavutil-dev \
                libswscale-dev libpng-dev libjpeg-dev


BUILDING

  make
  sudo make install

  Edit config.mk to change compile-time defaults (output format,
  default threshold).


LICENSE

  MIT