spec: fold in operator approval + pano-projector design change
Operator approved the spec and confirmed first-ship archives (LibriVox + NASA + IA). Folds in the 2026-06-04 design change (single panoramic projector across all three walls, nature-video content): demotes dominant_color to optional/opt-in (its only consumer was the procedural side walls), ffmpeg-only when computed, never an image lib. Flags the design-spec/ROADMAP follow-up as out of scope here. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,7 +22,8 @@ calls for (§5), under `tools/`:
|
||||
pool and write a catalog record.
|
||||
2. **Mechanical tagging** — tooling auto-fills the non-curatorial fields: `mode`
|
||||
(via `ffprobe`), `license`/`attribution`/`source_*` (from origin),
|
||||
`duration_s`, `resolution`, and `dominant_color` (computed from the video).
|
||||
`duration_s`, `resolution`, and — optionally, opt-in only — `dominant_color`
|
||||
(computed from the video; see §5.2 design-change note).
|
||||
3. **Coordinate drafting** — a proposer suggests `left/right/dark/light` with a
|
||||
one-line `rationale`, written as `review_status: proposed`.
|
||||
4. **Review CLI** — walks `proposed` records one at a time (proposed coords +
|
||||
@@ -193,29 +194,35 @@ derives:
|
||||
`tools/probe.py` takes the subprocess runner as an injectable dependency
|
||||
(default: `subprocess.run`); tests feed canned `ffprobe` JSON and never shell out.
|
||||
|
||||
### 5.2 `dominant_color` — computed from the video (`tools/mediatools.py`)
|
||||
### 5.2 `dominant_color` — optional, deferred (computed from the video only on demand)
|
||||
|
||||
For `video`/`av` records, extract a representative frame mid-segment and reduce it
|
||||
to one hex color. **Primary approach is `ffmpeg`-only** (keeps the dependency
|
||||
surface to just `ffmpeg`/`ffprobe` — no image library):
|
||||
> **Design-change note (2026-06-04):** `dominant_color`'s only consumer was the
|
||||
> **procedural side walls** (design §7): hue for the three non-primary walls. The
|
||||
> installation is moving to a **single panoramic projector that spans all three
|
||||
> walls showing the real (nature-video) content**, which removes the procedural
|
||||
> side-wall renderer — and with it the need to *compute* a dominant color. So this
|
||||
> spec **demotes `dominant_color` from a core mechanical-tagging requirement to an
|
||||
> optional, opt-in computation.** This is a knock-on of a larger design shift that
|
||||
> primarily affects sub-projects 3 and 5 and the design spec (see §11 follow-up).
|
||||
|
||||
```
|
||||
# representative frame near the middle, reduced to a single-entry palette
|
||||
ffmpeg -v quiet -ss <mid> -i <file> -vf "thumbnail,palettegen=max_colors=1" -frames:v 1 -f rawvideo -pix_fmt rgb24 -
|
||||
```
|
||||
Concretely:
|
||||
|
||||
The 3 output bytes are the dominant palette color → `"#rrggbb"`. (A simpler
|
||||
`scale=1:1` average-color path is the fallback if `palettegen` is unavailable.)
|
||||
Audio-only records keep `dominant_color=""`.
|
||||
- The `dominant_color` **field stays** in the schema (it is already there; default
|
||||
`""`) — no schema change either way.
|
||||
- Ingest does **not** compute it by default. An opt-in flag
|
||||
(`--dominant-color`) enables computation for `video`/`av` records, for the case
|
||||
the operator still wants it (e.g. a later ambient/lighting use).
|
||||
- **When enabled, it is `ffmpeg`-only — never an image library.** Extract a
|
||||
representative mid-segment frame and reduce it to one hex color:
|
||||
```
|
||||
ffmpeg -v quiet -ss <mid> -i <file> -vf "thumbnail,palettegen=max_colors=1" -frames:v 1 -f rawvideo -pix_fmt rgb24 -
|
||||
```
|
||||
The 3 output bytes are the dominant palette color → `"#rrggbb"` (a `scale=1:1`
|
||||
average-color path is the fallback if `palettegen` is unavailable). This honors
|
||||
the operator's "no video manipulation needed" steer: no Pillow, no new dep, and
|
||||
the work isn't done at all unless explicitly requested.
|
||||
|
||||
> **Open decision (logged):** the roadmap assumed "an image lib for dominant
|
||||
> color." This spec instead recommends the **ffmpeg-only** path so the whole
|
||||
> sub-project depends on nothing beyond `ffmpeg`/`ffprobe`. **Pillow** (k-means /
|
||||
> `quantize` over a sampled frame) is the documented fallback if ffmpeg-derived
|
||||
> color quality proves insufficient in review. Chosen for the lean dependency
|
||||
> story; reversible.
|
||||
|
||||
`dominant_color` feeds the side walls (sub-project 5, design §7).
|
||||
Audio-only records always keep `dominant_color=""`.
|
||||
|
||||
### 5.3 `license` / `attribution` / `source_*` — from origin (`tools/licensing.py`)
|
||||
|
||||
@@ -469,8 +476,9 @@ Mirrors sub-project 1's TDD discipline (test-first, stdlib, hermetic).
|
||||
2. **Mechanical tagging** — canned `ffprobe` JSON → expected `mode`/`duration_s`/
|
||||
`resolution`; the **cover-art `attached_pic` guard** keeps an art-bearing MP3 at
|
||||
`mode="audio"`.
|
||||
3. **Dominant color** — canned ffmpeg `rgb24` bytes → expected `"#rrggbb"`;
|
||||
audio-only → `""`.
|
||||
3. **Dominant color (opt-in path)** — with the flag on, canned ffmpeg `rgb24`
|
||||
bytes → expected `"#rrggbb"`; with the flag off (default), `dominant_color`
|
||||
stays `""`; audio-only → `""`.
|
||||
4. **License normalization** — sample per-archive metadata → correct `license`;
|
||||
`cc_by`/`cc_by_nc` produce non-empty `attribution`; unmappable license is
|
||||
rejected.
|
||||
@@ -504,13 +512,17 @@ fixture clip → `mode`/`duration`/`resolution`; real dominant-color extraction.
|
||||
None block writing the implementation plan; each has a recommended default the
|
||||
plan will assume unless the operator overrides.
|
||||
|
||||
1. **Dominant-color dependency** — *Recommend:* ffmpeg-only (`palettegen`), no
|
||||
image lib; Pillow as fallback. (Roadmap had assumed an image lib.)
|
||||
1. **Dominant-color dependency** — *Decided (operator, 2026-06-04):* `dominant_color`
|
||||
is **optional / opt-in** and, when computed, **ffmpeg-only — no image lib**,
|
||||
because the move to a single panoramic projector showing real nature video
|
||||
removes the procedural side walls that were its only consumer (§5.2).
|
||||
2. **`file_path` style** — *Recommend:* relative-to-`media-root` for portability;
|
||||
reconcile the USER_GUIDE's absolute examples with a doc note; player spec
|
||||
defines mount resolution.
|
||||
3. **Which archives ship first** — *Recommend:* LibriVox, NASA, Internet
|
||||
Archive/Prelinger first; defer Freesound, Musopen, FMA (auth / API-stability tax).
|
||||
3. **Which archives ship first** — *Decided (operator, 2026-06-04):* **LibriVox,
|
||||
NASA, Internet Archive/Prelinger** first; defer Freesound, Musopen, FMA (auth /
|
||||
API-stability tax). (Nature-video content focus weights NASA/IA; the audio
|
||||
pools still serve the catalog's audio modes.)
|
||||
4. **CLI surface** — *Recommend:* two `python -m` entry points (`tools.ingest_cli`,
|
||||
`tools.review_cli`), matching the no-install repo convention; console-script
|
||||
aliases optional.
|
||||
@@ -522,14 +534,27 @@ archive-identifier field, `media_sha256` integrity, an `ingested_at` timestamp,
|
||||
any LLM-backed proposer in the core. All are future, additive extensions; none are
|
||||
needed for the done-criteria.
|
||||
|
||||
**Design-spec follow-up (beyond this sub-project):** the operator's 2026-06-04
|
||||
decision to use a **single panoramic projector spanning all three walls, showing
|
||||
real nature video**, supersedes the design spec's §6 (four projectors) / §7
|
||||
(procedural side-wall renderer) and reshapes sub-projects **3** (player drives one
|
||||
pano output, not primary + side feed) and **5** (procedural side walls likely
|
||||
dropped). The design spec
|
||||
(`2026-06-04-human-experience-filter-design.md`) and ROADMAP should be updated to
|
||||
reflect this in a separate pass; it is **out of scope for the sub-project-2 spec**,
|
||||
whose only affected element is the now-optional `dominant_color` (§5.2).
|
||||
|
||||
---
|
||||
|
||||
## 12. Relationship to the other sub-projects
|
||||
|
||||
- **Consumes** sub-project 1 (`hef.catalog`, `hef.selection`) — the only required
|
||||
change is the additive `validate_catalog` (+ optional `index_by_id`), §3.
|
||||
- **Feeds** sub-project 3 (the Pi player): a populated, `approved` catalog with
|
||||
`dominant_color` ready for sub-project 5's side walls. The player resolving
|
||||
- **Feeds** sub-project 3 (the Pi player): a populated, `approved` catalog the
|
||||
player drives to the (now single, panoramic) projector. The player resolving
|
||||
`file_path` against its drive mount (§6.3) is a player-spec concern.
|
||||
- **Side walls (sub-project 5)** are likely **dropped** under the pano-projector
|
||||
design change (§11 follow-up); `dominant_color`, their only input, is
|
||||
correspondingly optional here (§5.2).
|
||||
- **Settles** two roadmap open decisions (download/caching layout §6.3; ingest
|
||||
language = Python under `tools/`, §4).
|
||||
|
||||
Reference in New Issue
Block a user