Skip to content

Conversation

@codihuston
Copy link
Owner

@codihuston codihuston commented Jan 30, 2026

Summary

Add Global Jump Navigation GUI - a cross-video artifact search and navigation feature that allows users to search for objects, faces, transcript text, OCR text, scenes, places, and locations across their entire video library.

Changes

  • Product changes
  • Security changes
  • Test changes
  • Dependency changes
  • UX changes
  • Architecture changes
  • Feature/code changes
  • CI/CD changes
  • Breaking changes

Testing

  • Tests pass locally
  • New tests added (22 unit tests, 8 integration tests)
  • Manual testing completed

Related Issues

N/A

Screenshots (if applicable)

N/A


Detailed Changes

Frontend

New Components:

  • GlobalJumpControl - Cross-video artifact search and navigation component

    • Supports all 7 artifact types: object, face, transcript, ocr, scene, place, location
    • Dynamic input fields based on artifact type (label, query, face cluster ID)
    • Confidence threshold slider for object/face/place searches
    • Previous/Next navigation buttons
    • Cross-video navigation with video change callbacks
    • Form state preservation across page navigation
  • SearchPage - Dedicated search page for global artifact search

    • Renders GlobalJumpControl without video context
    • Navigates to player page with correct video and timestamp on result selection
    • Passes form state to player for preservation

Updated Components:

  • VideoPlayer - Integrated GlobalJumpControl (replaces JumpNavigationControl)

    • Added initial timestamp seeking for navigation from search page
    • Added cross-video navigation support via onVideoChange callback
    • Reset hasInitialSeeked when video changes for correct timestamp seeking
  • App - Added search page routing and navigation state management

    • Added "Jump Search" button to gallery header
    • Handles navigation between gallery, search page, and player
    • Preserves form state during cross-video navigation

Backend

API Changes:

  • GET /api/v1/jump/global - Made from_video_id optional
    • When omitted, search starts from beginning (next) or end (prev) of global timeline
    • Enables search page to work without video context

Service Changes:

  • GlobalJumpService.jump_next() / jump_prev() - Handle from_video_id=None
    • Automatically get earliest/latest video when no starting position provided

Tests

Unit Tests (22 new):

  • GlobalJumpControl rendering modes (search page vs player mode)
  • Artifact type dropdown with all 7 options
  • Input field visibility per artifact type
  • Confidence slider visibility and behavior

Integration Tests (8 new):

  • Search page to player page navigation flow
  • Cross-video navigation with video change
  • Form state preservation across navigation
  • Visual indicator for cross-video results

UX Improvements

  • Renamed "Global Search" to "Jump Search" throughout UI
  • Clear error messages when reaching end/beginning of results
  • Form state preserved when navigating from search to player
  • Correct timestamp seeking on backward navigation to different video

…o navigation

- Add GlobalJumpResult and JumpTo dataclasses for navigation results
- Add GlobalJumpError, VideoNotFoundError, InvalidParameterError exceptions
- Add spec documents (requirements, design, tasks)
- Create JumpToSchema with start_ms and end_ms fields (with ge=0 validation)
- Create GlobalJumpResultSchema with video_id, video_filename, file_created_at,
  jump_to, artifact_id, and preview fields
- Create GlobalJumpResponseSchema with results array and has_more boolean
- Add comprehensive docstrings and field descriptions
- Export new schemas from global_jump module

Requirements: 5.3, 7.1, 7.2, 7.3, 7.4, 7.5, 13.1
- Add GlobalJumpResult and JumpTo domain models
- Add GlobalJumpError, VideoNotFoundError, InvalidParameterError exceptions
- Add GlobalJumpResultSchema and GlobalJumpResponseSchema for API responses
- Implement GlobalJumpService with _get_video() and _to_global_result() helpers

Follows existing layer-based project structure rather than feature-module pattern.
- Add _search_objects_global() method to GlobalJumpService
- Query object_labels projection table joined with videos
- Support label and min_confidence filtering
- Order by global timeline (file_created_at, video_id, start_ms)
- Handle NULL file_created_at values (sorted after non-NULL)
- Add 11 unit tests covering cross-video navigation
- Fix unused imports in video_controller.py
- Extend _search_objects_global() to support direction="prev"
- Add WHERE clause for results chronologically before current position
- Order by file_created_at DESC, video_id DESC, start_ms DESC
- Handle NULL file_created_at values (non-NULL comes before NULLs)
- Add 10 unit tests for prev direction covering cross-video navigation,
  filtering, ordering, and edge cases
- Add _search_transcript_global() method for cross-video transcript search
- PostgreSQL: Use plainto_tsquery for FTS with ILIKE fallback
- SQLite: Use FTS5 MATCH with separate metadata table join
- Support both 'next' and 'prev' directions with global timeline ordering
- Handle NULL file_created_at values correctly
- Add 10 unit tests for transcript search covering single-video,
  cross-video, ordering, and edge cases
- Add _search_ocr_global() method for cross-video OCR text search
- PostgreSQL: Use plainto_tsquery for FTS with ILIKE fallback
- SQLite: Use FTS5 MATCH with separate metadata table join
- Support both 'next' and 'prev' directions with global timeline ordering
- Handle NULL file_created_at values correctly
- Add 10 unit tests for OCR search covering single-video,
  cross-video, ordering, and edge cases
- Add VALID_KINDS class attribute with valid artifact types
- Implement jump_next() method that routes to appropriate search method
- Handle object, transcript, ocr kinds with proper routing
- Add placeholder errors for face, scene, place, location (not yet implemented)
- Validate kind parameter and raise InvalidParameterError for invalid values
- Default from_ms to 0 for next direction
- Require query parameter for transcript and ocr searches
- Add 8 unit tests for jump_next() method

Requirements: 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 12.3
- Implement jump_prev() method that routes to appropriate search method
- Handle object, transcript, ocr kinds with direction='prev'
- Add placeholder errors for face, scene, place, location (not yet implemented)
- Validate kind parameter and raise InvalidParameterError for invalid values
- Default from_ms to max int value for prev direction (end of video)
- Require query parameter for transcript and ocr searches
- Add 8 unit tests for jump_prev() method

Requirements: 1.2, 2.1, 3.3, 4.2, 5.1, 6.5, 12.3
- Add SceneRange import from database models
- Implement _search_scenes_global() for scene boundary navigation
- Implement _search_places_global() using object_labels table
- Update jump_next() to route scene and place kinds
- Update jump_prev() to route scene and place kinds
- Add 16 unit tests for scene and place search functionality

Scene search queries scene_ranges projection table for scene boundaries.
Place search reuses object_labels table since place classifications
are stored as object labels from Places365 model.

Requirements: 5.1, 7.5
- Implement _search_locations_global() for GPS location navigation
- Query video_locations projection table for videos with GPS data
- Support optional geo_bounds filtering (min_lat, max_lat, min_lon, max_lon)
- Handle SQLite datetime comparison by converting to string format
- Update jump_next() and jump_prev() to route location kind
- Add 10 unit tests for location search functionality

Location search returns videos with GPS coordinates ordered by global
timeline. Unlike other artifact searches, location is per-video so
results point to start_ms=0.

Requirements: 5.1
- Follow existing project patterns for API controllers
- Delete orphaned test_face_detection.py (ML service moved)
- Add test_global_jump_router.py for error handling tests
- Update ErrorResponseSchema in schemas.py
- All 339 tests passing
- Add global_jump_controller with parameter validation and error handling
- Register global jump router in main_api.py at /v1/jump/global
- Add composite database indexes for query optimization
- Add comprehensive tests for:
  - Arbitrary position navigation (14 tests)
  - Filter change independence (9 tests)
  - Result chaining capability (7 tests)
  - Cross-video navigation correctness (8 tests)
  - Backward compatibility with single-video jump (9 tests)
- All 391 tests passing

Tasks completed: 13-25 (excluding optional property tests)
- Add detailed endpoint description with global timeline concept
- Add OpenAPI examples for all response types
- Document all query parameters with examples
- Add error response examples for all error codes
- Enhance schema docstrings with field descriptions
- GlobalJumpControl component replacing JumpNavigationControl
- Cross-video navigation with onVideoChange callback
- Search page at /search route
- Location text search backend enhancement
- Video clip export (nice-to-have)
- 25 implementation tasks
- Thumbnail extraction task (idempotent, deduplicated)
- Thumbnail serving API at /api/v1/thumbnails/{video_id}/{timestamp_ms}
- Artifact search API at /api/v1/artifacts/search
- ArtifactGallery component with thumbnail grid
- Filename filter for scoping searches
- 35 implementation tasks
- Add GlobalJumpControl component for cross-video artifact search
- Create SearchPage for dedicated global search interface
- Add location text search to backend global jump service
- Integrate GlobalJumpControl into VideoPlayer replacing JumpNavigationControl
- Add form state preservation across page navigation
- Add 22 unit tests and 8 integration tests
- Make from_video_id optional in API (fixes 422 error from search page)
- Pass form state through onNavigate callback to preserve search params
- Show clear error message when reaching end/beginning of results
- Reset hasInitialSeeked when video changes for correct timestamp seeking
- Rename 'Global Search' to 'Jump Search' in UI
- Fix MetadataViewer tests for dual fetch calls and GPS format
- Update integration tests for renamed button
@codihuston codihuston merged commit f3956e1 into main Jan 30, 2026
0 of 2 checks passed
@codihuston codihuston deleted the global-jump-ui branch January 31, 2026 06:45
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