feat(ingest): store extracted video frames at a chosen scale - #814
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Ingest-time downscale for video sources: registration takes an optional
scale_percent(1–100, default 100), and every extracted frame is stored at that percent of the clip's
native size per side.
beside the rate and the clip ranges: the same clip at another scale is a second source.
Migration 18 reshapes the origin index to
uq_source_project_kind_path_fps_ranges_scale; an unscaled clip omits the JSON key, sorows written in any generation share one spelling and nothing forks retroactively.
Migration 16 became drop-only in the same change — only the head reshape may execute the
shared index declaration, because that declaration is always the current spelling.
_filtergraphgains a finalscale=W:Hstage with dimensions computedin Python from the probe (
max(1, (native·pct+50)//100), integer half-up — mirroredexactly by the screen so preview and stored size cannot drift). The whole-clip 100%
command stays byte-identical, pinned by test.
scale_percentform field, CLI--scale, MCPscale— allvideo-only, refused on a directory of stills the way
--fpsis.VideoProvenanceOutpublishes the value;
openapi.json, the generated client, and the MCP tool referenceare regenerated.
(
1280×720 · native, or1280×720 → 640×360 · 50%), a native range slider withendpoint labels, and a purpose line stating the pixel cost. The step-2 fact grid shows
the same arrow. The ingest preview player is now always muted, with the volume control
hidden — a vision dataset has no use for the audio track.
Per-image scaling for image batches was implemented and then withdrawn during review; the
history carries both halves, and the final tree scales video only. Image directories store
stills at their decoded size — a uniform size remains the export recipes' job.
Found, not fixed
Nothing — the one defect found along the way (an object URL revoked under StrictMode's
double-mount, breaking dev-server thumbnails) was in this branch's own code and is gone
with it.
Test plan
uv run pytest tests/kernel tests/server tests/cli tests/mcp— green.uv run lint-imports,uv run mypy src/visionset/kernel,uv run ruff check .— green.openapi.json/ generated client /docs/content/mcp-tools.mddrift — clean.pnpm -r build && pnpm -r test && pnpm -r lint— green; real-server cycle suite green.dimensions on disk (640×360 from a 1280×720 clip at 50%), identity forking, the muted
player, and the images panel unchanged.