Skip to content

Video search on top of the Review grid (rebase of #1743) - #1898

Draft
mattdawkins wants to merge 7 commits into
dev/review-gridfrom
dev/video-search-review
Draft

Video search on top of the Review grid (rebase of #1743)#1898
mattdawkins wants to merge 7 commits into
dev/review-gridfrom
dev/video-search-review

Conversation

@mattdawkins

Copy link
Copy Markdown
Member

Stacked on #1897 (base branch dev/review-grid). Rebases the video search / IQR work from #1743 onto it and shows search results in the new Review chip grid.

Rebase

The five commits of #1743 apply on top of the review branch with these adaptations to changes that landed on main in the meantime (one follow-up commit):

  • desktop project store type is JsonConfig, read with loadJsonConfig from datasetFileAbsPath
  • the frontend metadata loader is loadConfig
  • the GPU job queue uses the typed IPC invoke<DesktopJob>
  • a spawn without a pid now fails the index build instead of storing undefined

Results in the Review grid

  • VideoSearchResultsGrid is rebuilt on the shared review components: results map to ReviewItems (dive-common/review/searchResultItems.ts), and the grid uses ReviewGrid / ReviewCell / ReviewGridControls and useReviewGrid, so grid shape, zoom, context margin, paging and keyboard behaviour are the same as the Review tab and share its persisted settings.
  • Chips are cropped client-side through the review frame sources via a lazy per-dataset registry (createFrameSourceRegistry), so cross-dataset results load their own media (image sequence or hidden <video> seek) with no backend frame extraction for display. Results without a box show the whole frame.
  • Cells keep accept / reject through ReviewCell's actions slot, get a green / red highlight border, show the relevancy score as the badge, and clicking a chip from the open dataset seeks the viewer to it.
  • useSearchChips.ts replaces useResultChips.ts and AdjudicationChip.vue; it also feeds the side panel's row thumbnails from the same chip store.
  • docs/Review.md gains a short "Search results" section.

Testing

  • Unit tests for the result → item mapping, whole-frame crop regions and the grid settings; npm run lint, npm run typecheck and npm test pass.
  • Desktop dev build: the results grid was opened on a real image-sequence dataset with synthetic results injected into the search session (this machine's dev build was not restarted with the new IPC handlers, so the backend query path itself was not exercised here). Chips, track cycling, whole-frame results, paging and zoom rendered correctly.
  • The index build / query / refine backend is unchanged from Add optional video search capabilities to DIVE [DRAFT] #1743 apart from the renames above and remains untested here.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W1C4QY6hxjHaUPJfWPfQuu

mattdawkins and others added 7 commits September 9, 2026 01:40
Per-dataset search index lifecycle (build via a process_video.py job,
status from an index_meta.json sidecar + ITQ file check, delete) and a
persistent QueryServiceManager wrapping viame.core.query_service over
NDJSON stdio (open index, formulate from image chip + boxes, query with
optional warm-start model, refine with +/- feedback, export the SVM as a
runnable trained pipeline in DIVE_Pipelines). One index open at a time;
the embedded postgres is stopped gracefully on app cleanup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New in-viewer context panel (desktop only) for index-backed video search
and rapid model generation: build/rebuild/delete the dataset's search
index (via the GPU job queue), query from the selected annotation, an
external image file, or a saved .svm model warm-start, adjudicate ranked
results +/- with cropped chip thumbnails and click-to-seek, refine
iteratively, and save good models as runnable trained pipelines. Shared
request/response types live in apispec so web can implement later.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace per-dataset index directories with a single shared search
database (DIVE_SearchIndex): every table keys rows on a per-video
stream identifier, so datasets are added, updated, and removed
independently while one IQR session searches everything at once.

- Add/Update ingests a dataset into the shared database as a job
  (initializing it on first use), re-using stream identifiers derived
  from the dataset id (image sequences) or video filename stem.
- Remove deletes the dataset's rows through the query service and drops
  it from the membership metadata; deleting a dataset from DIVE also
  removes it from the index automatically.
- Query results attribute back to their source dataset via stream_id;
  the panel labels cross-dataset results, seeks within the current
  dataset, crops thumbnails from each result's own media, and can
  filter the display to the current dataset.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New fullscreen 5x4 grid page, opened from the Video Search panel, showing
the ranked results across every indexed video as cropped chips with
accept/reject buttons; marks share the panel's session state and feed the
same IQR refine loop. Chip rendering moves to a shared, concurrency-limited
loader (useResultChips) with context padding and the result box outlined,
and the cell (AdjudicationChip) is presentation-only so future annotation
cluster rows can reuse it.

Also: extracted video frames are now cached per source video (hash-keyed)
instead of colliding across videos on frame number, and cross-dataset chip
media resolves the file the media server actually serves, so transcoded
copies work when originals have moved.
Track results load their first-state chip immediately, then the grid
queues up to 8 frames evenly sampled along the track (visible page only,
at lower priority than primary chips) and each cell cycles through
whichever frames have loaded, with a filmstrip badge marking animated
cells. Static detection results are unchanged.
Follow renames that landed on main since the branch was cut: the desktop
project store type is JsonConfig and is read with loadJsonConfig from the
project's datasetFileAbsPath, the frontend metadata loader is loadConfig,
the typed IPC invoke is used in the GPU job queue, and a spawn without a
pid now fails the index build instead of storing an undefined pid.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1C4QY6hxjHaUPJfWPfQuu
The full-window results grid is now the review chip grid: results map to
ReviewItems (searchResultItems.ts), chips are cropped client-side through
the review frame sources (a lazy per-dataset registry, so cross-dataset
results need no backend frame extraction), and the grid shape, zoom,
context and paging come from useReviewGrid / ReviewGridControls with the
same persisted settings as the Review page. Cells keep the accept/reject
actions through ReviewCell's slots and a highlight border; results without
a box show the whole frame.

useResultChips.ts and AdjudicationChip.vue are replaced by
useSearchChips.ts, which also feeds the side panel's row thumbnails.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1C4QY6hxjHaUPJfWPfQuu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant