Skip to main content
Annie

Local-first browser UI to explore, inspect, and validate a video annotation dataset

GitHub Release PyPI CI codecov Docs
Python Code style: ruff License


Annie visualizes a video dataset alongside its frame-wise annotations and lets you curate and (soon) author them — all in one local, browser-based UI that runs on a single machine. The motivating datasets are CMU-MOSEI and First Impression V2 (face detections + derived face tracks), but Annie is dataset-agnostic.

Screenshots

Annie – Home tab

Home tab — landing page with a summary card for each tab.

Annie – Browse tab

Browse tab — per-video rows with original clip, annotated frame strip, label tags, and review controls.

Features

Tab What it does
Home A landing page (the default) summarising each tab; click a card to jump there.
Convert Re-encode an audio/video dataset to a consistent, torchcodec-validated form: uniform audio (format/rate/channels) and constant-frame-rate H.264 video, with explicit audio muxing (or black-frame videos for audio-only). A background batch shows live X/Y progress, %, elapsed, and ETA.
Dataset Build the dataset from a list of data sources (videos folder, vdet/track folders, and any number of label/protagonist CSVs). Add a source and it scans in place — no Scan button — with live counts and an Available/Unavailable chip per source.
Browse Scrollable, per-video visualizer with an always-visible filter bar (name, video/audio/vdet/track presence, review, labels): an ORIGINAL placeholder, five-frame strip, on-the-fly annotated render, media/annotation/label tags, and per-video review (liked by default, dislike, note, "Add to Annotator"). Row height is configurable.
Annotator Greys out until videos are queued from Browse; then shows only those, in taller rows, to fix the protagonist track — pick a track, see it re-render green, Save, and export the corrected datasource as CSV.
Settings Browse/Annotator row height, render-cache TTL, and review-status export/import (CSV/JSON).

Highlights

  • Extensible data sources — a dataset is an ordered set of sources; a CSV joins to videos by a chosen key column, exposing its value columns as Browse tags and filter facets (e.g. Sentiment: negative, Angry: 0.33). Dataset-agnostic by construction.
  • Stem matching — videos pair with vdet/track files by filename stem (exact + prefix, longest-stem-first), aggregated into one row per video.
  • Composable filtering — filter by vdet/track coverage, review verdict, notes, annotator selection, and label values; facets combine with AND, label values OR.
  • Frame-accurate decodetorchcodec with exact mode for the annotator and approximate for fast scrubbing.
  • Render-on-demand — a background job burns annotations into a browser-playable clip (libx264 via FFmpeg, audio muxed back); temp clips auto-purge on a TTL.
  • Protagonist correction — pick the true protagonist; the fix is written to a separate _manual file (resolution manual ▸ source ▸ -1) so human judgement never overwrites the pristine heuristic record, and the resolved datasource exports to a standalone CSV.

Installation

Prerequisites

Required for the source and PyPI install paths. Docker bundles everything automatically.

Tool Purpose Install
uv Python package manager curl -LsSf https://astral.sh/uv/install.sh | sh
FFmpeg (4–8) Frame decode, render pipeline, audio probe brew install ffmpeg
ffprobe Audio-stream detection (ships with FFmpeg) included with FFmpeg

From PyPI

uv pip install "annie[all]"     # core + torch / torchcodec for frame decode & render
annie                           # starts the UI at http://127.0.0.1:8080

From source (development)

git clone https://github.com/fodorad/Annie
cd Annie
make dev      # installs annie[all,dev] in editable mode (torch + torchcodec included)
make run      # starts the UI at http://127.0.0.1:8080

Docker

No Python, uv, or FFmpeg required on the host — Docker bundles everything.

git clone https://github.com/fodorad/Annie
cd Annie
cp .env.example .env   # fill in your HDD paths
make docker-build      # ~5–10 min first time (downloads CPU torch)
make docker-run        # starts the UI at http://localhost:8080

Or pull the pre-built image without cloning:

curl -O https://raw.githubusercontent.com/fodorad/Annie/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/fodorad/Annie/main/.env.example
cp .env.example .env   # fill in your HDD paths
docker compose up      # pulls fodorad/annie:latest automatically

Annie state (logs, session DBs, render cache, saved configs) is stored in ./annie-home/ next to docker-compose.yml by default, so all files are directly accessible from Finder / Explorer. Exported review CSVs land in annie-home/tmp/. Override the path with ANNIE_HOME_HOST in .env.

macOS + external HDDs: If /Volumes is already in Docker Desktop → Settings → Resources → File Sharing, individual drives under /Volumes work without any additional configuration.

Extras

Extra What it adds
media torch, torchcodec — frame decoding & rendering
dev ruff, ty, coverage, pre-commit
docs sphinx, furo, sphinx-autoapi, myst-parser
all media

Architecture

Annie is a single process with a strict layered architecture; each layer calls only the layer directly beneath it, enforced by import direction:

UI layer          annie/app.py, annie/pages/*          (NiceGUI tabs)
   │  calls down only
Service layer     annie/dataset/*, annie/media/*        (scanning, rendering, filtering, …)
   │
Domain layer      annie/core/models.py, annie/parsers/* (pure data, no I/O frameworks)
   │
Infrastructure    annie/core/config.py, annie/core/theme.py,
                  annie/dataset/storage.py (SQLite), annie/media/decode.py (torchcodec)

The UI never imports sqlite3 or torchcodec directly — it calls a service function. The core layers install without a heavyweight torch dependency; only the frame decode and render pipeline need the media extra.

Annotation formats

Both .vdet and .track files share one 17-column CSV schema (CRLF, with header):

frame_id, source, score, x, y, w, h,
left_eye_x, left_eye_y, right_eye_x, right_eye_y,
nose_x, nose_y, left_mouth_x, left_mouth_y, right_mouth_x, right_mouth_y
  • .vdet — all raw detections for a video; may have several rows per frame.
  • {video_id}__track{N}.csv — one tracked face across frames (one row/frame).
  • protagonist CSV — e.g. protagonist_track_heuristic.csv with uuid,track_id, the active protagonist per video (-1 = none). The key and track-id columns are chosen when the source is added; manual corrections go to the _manual sibling.
  • label CSV — any CSV; pick a key column (joined to the video id) and value columns to surface as Browse tags and filter facets.

Development

git clone https://github.com/fodorad/Annie
cd Annie
make dev      # install in editable mode with all extras
make check    # lint + type-check + test + docs (mirrors CI)
make run      # start the app at http://127.0.0.1:8080

Tip — skip re-clicking paths on every restart: set ANNIE_* environment variables and Annie will seed those sources automatically at launch. This is equivalent to manually adding sources on the Dataset tab, but saves time during development when you always work with the same dataset.

export ANNIE_VIDEO_DIR=/path/to/video
export ANNIE_VDET_DIR=/path/to/vdet
export ANNIE_TRACK_DIR=/path/to/track
export ANNIE_PROTAGONIST_CSV=/path/to/protagonist_track_heuristic.csv
export ANNIE_LABEL_CSV=/path/to/label.csv
make run

Sources seeded via env vars are session-only; curation and corrections always persist. Save your source configuration from the Dataset tab to a named config file to reload it in one click without relying on env vars. Every setting has a corresponding ANNIE_* variable (see annie/core/config.py).

See CONTRIBUTING.md for the commit convention and release flow.

Documentation

Related Projects

  • exordium — multimodal feature extraction (the detectors/trackers that produce Annie's .vdet/.track inputs).

Contact

Ádám Fodoradamfodor.com · fodorad201@gmail.com

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

annie-1.3.0.tar.gz (45.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

annie-1.3.0-py3-none-any.whl (133.7 kB view details)

Uploaded Python 3

File details

Details for the file annie-1.3.0.tar.gz.

File metadata

  • Download URL: annie-1.3.0.tar.gz
  • Upload date:
  • Size: 45.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for annie-1.3.0.tar.gz
Algorithm Hash digest
SHA256 6d2d3e86e201673c3d3e8a8895c1f423a8511b0d5134f25ed7376bdf74aec537
MD5 48295055bb77751212ad0866a93cf1f0
BLAKE2b-256 2c053011661348598c388b66c26e665f18c512cbb3c6283ecb1bfb20f0d6a050

See more details on using hashes here.

Provenance

The following attestation bundles were made for annie-1.3.0.tar.gz:

Publisher: cd.yml on fodorad/Annie

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file annie-1.3.0-py3-none-any.whl.

File metadata

  • Download URL: annie-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 133.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for annie-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 022e35655ea2a7374586b9a3ba13d5ebab516cb299e840bb2538d1b25561bb65
MD5 a806646b51338f367a77d4a9955271e2
BLAKE2b-256 64b3e4539a1bd7d55ccec51a72a67ee90c2cbfc73e247eabcde767b85d68acef

See more details on using hashes here.

Provenance

The following attestation bundles were made for annie-1.3.0-py3-none-any.whl:

Publisher: cd.yml on fodorad/Annie

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.4.0

2 files

This release

1.3.0 This release

2 files

1.2.0

2 files

1.1.0

2 files

1.0.2

2 files

1.0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page