Every frame of an anime, compressed into a single image — then analysed back into prose, palettes, and perceptual neighbours.
267 anime · 1996–2025 · 6 barcode variants each · k-means palettes, OKLab perceptual neighbours, brightness arcs, hue distributions. Long-form decade essays, hand-feeling per-show commentary, and a dedicated frame-by-frame deep-dive on Serial Experiments Lain.
The site's flagship is a single-show portfolio piece on Serial Experiments Lain (1998) — built ground-up in the show's own visual register (cathode-blue + warm-tan accents on a black void, scanline overlays, JetBrains Mono + Cormorant Garamond).
What's there:
- Walk the Season — interactive 13-Layer hover strip. Mouse over any Layer's slice barcode and a sticky panel updates with the closest of 24 extracted keyframes, the timestamp, the current act, the act-brightness, an act-palette, a hand-written plot beat, and the cast on screen.
- Frame Atlas, measured — 312 keyframes (24 × 13 Layers) extracted from the source video. Each one carries its measured brightness, saturation, and dominant hue. Sortable by Layer, brightness ascending/descending, saturation, hue (ROYGBIV). Extremes panel calls out the literal darkest, brightest, most-saturated, and most-desaturated frames in the run — found by the algorithm, not by me.
- Hue spectrogram — 13 Layers × 12 hue buckets stacked-bar.
- Per-Layer breakdown — palette, act-thirds bars, slice barcode, 24-frame keyframe strip per Layer, with a one-paragraph reading anchored to a measurable data point.
- Authorial-intent research — primary citations from cjas.org Otakon-2000 / AX-2001 / Anime Colony chat / ANN-2005, fact-checked against lain.wiki. Voice cast + Triangle Staff postscript. Honest non-attribution of the J.J. Burnel / Bôa fan claim.
- Cultural afterlife — the Milady/Remilia link's primary-source fragility, SystemSpace as the cleanest crypto-art continuity, Texhnolyze as the strongest creator-continuity chain, Lain's afterlife in draincore + schizoposting + cyberpunk-revival.
Every Layer beat was fact-checked against lain.wiki before shipping. The page is the part of the site that exists to be read, not browsed.
A barcode takes every sampled frame of an anime and compresses it into a single vertical strip. Stack them left-to-right and you get a visual fingerprint of the entire show — its colour mood, pacing, and aesthetic in one image.
Each entry gets 6 variants rendered from the actual video:
| Variant | What it shows |
|---|---|
| Pixel Slice | 1px center crop of each frame — raw, saturated, exact scene colour |
| Smooth Average | Mean colour of every pixel in each frame — the emotional tone |
| Rank Mosaic | Columns sorted by luminance — dark left, bright right — full palette as a gradient |
| Radial / Circle | Polar transform of the average barcode — the show as a clock face |
| Edit Pace | Frame-to-frame colour delta — bright columns = fast cuts, dark = slow scenes |
| Colour Temperature | Red-Blue channel ratio per frame — warm gold vs cool teal |
Every show gets a Color Twins panel listing its closest five palette neighbours from across the archive — computed in OKLab perceptual space (chromatic-weighted distance between palette colours, with greys / blacks / whites filtered out as universal). Land of the Lustrous finds Aria the Animation. Lain finds My Hero Academia (cool-palette match, surprising). The metric is symmetric mean-of-min OKLab distance, cached to a JSON index for instant lookup.
Four long-form essays (~1620–1900 words each), one per decade: 1990s — 2020s. Hand-written, anchored to specific show data. The 1997 rupture, FMA 2003 vs FMA Brotherhood 2009, KyoAni's painterly 2010s, MAPPA's industrial-grey 2020s.
40 shows have hand-curated editorial commentary; the remaining 227 have AI-generated paragraphs (DeepSeek-Reasoner / DeepSeek-Chat) anchored to the specific palette, brightness arc, and hue distribution of each show, with curated style anchors. Zero shows fall back to template-generated text — every detail page reads.
Cross-archive analytics: brightness vs. saturation scatter, edit-pace vs. MAL score, studio fingerprints (KyoAni vs MAPPA vs Trigger averaged palettes), warmth-over-time, hue distribution evolution from 1996 → 2025.
Top-bar YEAR ▾ select routes straight to any year's page. Hamburger drawer at <760px keeps the nav in a single row regardless of viewport. Image lightbox on every barcode + keyframe — click any image, fullscreen overlay with × / Esc / click-outside dismiss.
Warm-grays, cool-grays, one tan, one navy, zero primary colours
Gem-coloured CG — one of the most distinctive palettes in any anime
Jazz-era warmth — amber, rust, and space-black across the full run
High contrast — flame-lit fights against dark backgrounds, ufotable's industrial sublime
Pastel-to-black — the colour shift as the show turns dark is visible in the barcode
Deep reds, flesh tones, sudden bursts of white — MAPPA's kinetic colour language
Jikan MAL API Stream resolver ffmpeg
────────────── → ────────────────────── → ──────────────────────────
Top anime by year Resolve cached stream Sample 1 frame / 7.5s
score + members URL for episode or movie Crop / average → tile
Download to local tmp 6 variants rendered
↓
PIL + numpy + OKLab GitHub Pages analyze.py
────────────── → ────────────────────── ← ──────────────────────────
K-means palette Static site generated K-means palette (8 colours)
Brightness arc Committed + pushed Hue distribution (12 bins)
Color temperature ~340 MB total Brightness arc (3-act)
Edit pace delta Saturation average
OKLab perceptual Per-act palette
neighbour index
expand_lists.py— Hits the Jikan v4 API to pull top-rated anime per year (by MAL score + member count); merges intolists/YEAR.json.pipeline.py— For each entry: resolves a stream URL, downloads, renders 6 barcode variants with ffmpeg, analyses with numpy/PIL, writesstats.json+meta.json.derive_analysis.py— Post-processesbarcode_avg.pngto generate Edit Pace and Colour Temperature barcodes without re-downloading.scripts/generate_commentaries.py— DeepSeek-Reasoner / DeepSeek-Chat generates editorial paragraphs anchored to palette + brightness + hue-distribution, using curated shows as style anchors.scripts/extract_lain_frames.py— Re-resolves Lain episodes, extracts 24 keyframes per Layer at 480w (skipping OP/ED), deletes the .mkv. With per-episode timeout protection.lain_feature.py— Standalone module that reads existing analysis + extracted frames + research files and emits the dedicated/lain/deep-dive page with computed per-frame stats cached to.lain_frame_stats.json.generate_site.py— Reads allbarcodes/*/dirs, builds the full static site intosite/, copies barcode PNGs, writes HTML/CSS, generates the OKLab palette-neighbour index.
Each anime gets a stats.json with:
- K-means palette — 8 dominant colours from column means (the temporal colour data, not raw pixels)
- Per-act palette — opening / middle / closing third k-means dominants
- Brightness arc — Mean luminance per column split into thirds, classified as rising / falling / arc-up / dark-midpoint / flat
- Hue distribution — 12-bin HSV histogram of column mean colours
- Mean complexity — frame-to-frame colour delta as a proxy for edit pace
Per-show OKLab palette neighbours are precomputed in generate_site.py:build_similarity_index — symmetric mean-of-min OKLab distance with chromatic-weighted matching (greys/blacks/whites filtered out). Cached to .similarity_cache.json so subsequent rebuilds are free.
pip install pillow numpy
# ffmpeg must be on PATH
# Stream provider account + API token required for the download stage
# (the site / analysis / Lain feature don't need streaming once the .mkvs are
# processed — only the initial pipeline.py + extract_lain_frames.py do)git clone https://github.com/dknos/anime-barcodes.git
cd anime-barcodes-claudec
# Set your stream provider token
export STREAM_API_TOKEN=...
# Pull top-N anime per year
python3 expand_lists.py
# Process one year (or all)
python3 pipeline.py --year 2019
python3 pipeline.py --all
# Derive secondary barcodes (no video needed)
python3 derive_analysis.py
# Generate the AI commentary pass (DeepSeek)
export DEEPSEEK_API_KEY=...
python3 scripts/generate_commentaries.py --workers 6 --model deepseek-chat
# Extract Lain keyframes (only needed once)
python3 scripts/extract_lain_frames.py
# Build the site
python3 generate_site.pypython3 pipeline.py --year 2019 --gpu 0| Layer | Tool |
|---|---|
| Anime metadata | Jikan v4 (MyAnimeList API wrapper) |
| Stream resolution | Cached stream provider |
| Video processing | ffmpeg (fps, crop, scale, tile, slice) |
| Image processing | Pillow + numpy |
| Colour analysis | K-means clustering, HSV histograms, OKLab perceptual distance |
| Editorial prose | DeepSeek-Reasoner / DeepSeek-Chat (OpenAI-compatible API) |
| Charts | Chart.js v4 |
| Fonts | Inter, Cormorant Garamond, JetBrains Mono, Fraunces |
| Hosting | GitHub Pages |
- 267 anime processed
- 1996–2025 continuous coverage
- ~7.5 second frame sampling interval
- 6 barcode variants per anime · 1920 × 1080 PNG
- 312 extracted keyframes for Lain (24 × 13 Layers, 480w JPEG)
- OKLab palette index precomputed across all 267 entries
- 40 hand-curated + 237 AI-generated show commentaries
- 4 decade essays (~7,200 words total)
- ~340 MB total site weight
Edit lists/YEAR.json:
{
"mal_id": 1535,
"title": "Death Note",
"title_english": "Death Note",
"score": 8.62,
"episodes": 37,
"imdb_id": "tt0877057",
"media_type": "TV"
}Then python3 pipeline.py --year 2006.
Targets:
- Per-frame measurement scaled across the whole archive (currently Lain-only)
- Studio-fingerprint clustering (does Trigger have a measurable signature?)
- Scene-type detection (action / dialogue / establishing)
- Cross-year comparisons (is anime getting darker over time?)
Sometimes stream resolution picks a low-quality source:
rm -rf barcodes/YEAR/SLUG/
python3 pipeline.py --year YEAR --forceBuilt with Python, ffmpeg, OKLab, and the conviction that the colour data is already the analysis.











