| name | video-tagging |
| description | Tag, bucket, and search video clips in Video Review OS. Use when working with tags.json, content buckets, event/performer/venue tags, per-clip topics, the shared clip library, cross-project search, or when a user asks to find footage by what it shows or what was said. Also use when correcting a wrong tag or explaining how a bucket was chosen. |
| license | MIT |
Tagging and finding footage
tags.json (schema video_review_os.tags.v2) makes a raw library findable. v2 is
strictly additive over v1: the source-level tags record keeps every key it always had
and gains a visual summary, joined by a new per-clip clips list.
video-review-os tag <project>
video-review-os library speech-search "…"
Source level
event_type, performer, track, venue, energy, has_vocal, orientation,
usable_vertical, duration, quality_flags, and a first-class bucket. A clip never
leaves the tagger without a bucket — the default is broll_trending.
Bucket logic is deliberately simple and inspectable:
- identified performer + vocal + event type →
real_gfa (the high-craft lane)
- vocal + second-person address ("you", "here's how", "if you") →
direct_camera
- everything else →
config.tagging.default_bucket
Populate [tagging] roster and venues with the names you actually shoot; matching is
whole-word against filename plus transcript. An empty roster is why performer is null.
Clip level
Each entry in clips carries topics (frequent meaningful words from that clip's text),
has_speech, the visual attributes perception found, reframe_needed, and
quality_flags. With no perception.json the visual fields are all unknown and
everything else still works — perception is optional, not a prerequisite.
tags["visual"] rolls the per-clip readings into a source-level summary. unknown never
wins a vote there: a source with two known readings and eight unknowns describes itself by
the two.
When a tag is wrong
Correct it in the tag_overrides.json sidecar, keyed by approval_key — never by editing
tags.json, which is regenerated. Overrides keyed by content hash survive re-tagging;
overrides keyed by position do not, which is why the sidecar shape is what it is.
Using a model for tagging
Same contract as every other stage — a provider name in config, no vendor in the code:
[tagging]
provider = "generic-http"
hosted_endpoint_env = "VIDEO_REVIEW_TAG_ENDPOINT"
hosted_api_key_env = "VIDEO_REVIEW_TAG_API_KEY"
The response is sanitized: unknown buckets and orientations fall back to the deterministic
value, so a hostile or confused endpoint cannot introduce a bucket the rest of the system
does not understand. Verify this holds if you extend the schema — every new field needs a
sanitize rule and a test.