Backend (Rust/Actix-web): - Add video_preview_clips table and PreviewDao for tracking preview generation - Add ffmpeg preview clip generator: 10 equally-spaced 1s segments at 480p with CUDA NVENC auto-detection - Add PreviewClipGenerator actor with semaphore-limited concurrent processing - Add GET /video/preview and POST /video/preview/status endpoints - Extend file watcher to detect and queue previews for new videos - Use relative paths consistently for DB storage (matching EXIF convention) Frontend (React Native/Expo): - Add VideoWall grid view with 2-3 column layout of looping preview clips - Add VideoWallItem component with ActiveVideoPlayer sub-component for lifecycle management - Add useVideoWall hook for batch status polling with 5s refresh - Add navigation button in grid header (visible when videos exist) - Use TextureView surface type to fix Android z-ordering issues - Optimize memory: players only mount while visible via FlatList windowSize - Configure ExoPlayer buffer options and caching for short clips - Tap to toggle audio focus, long press to open in full viewer Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.6 KiB
2.6 KiB
Data Model: VideoWall
Entities
VideoPreviewClip
Tracks the generation status and metadata of preview clips derived from source videos.
Table: video_preview_clips
| Field | Type | Constraints | Description |
|---|---|---|---|
| id | INTEGER | PRIMARY KEY, AUTOINCREMENT | Unique identifier |
| file_path | TEXT | NOT NULL, UNIQUE | Relative path of the source video from BASE_PATH |
| status | TEXT | NOT NULL, DEFAULT 'pending' | Generation status: pending, processing, complete, failed |
| duration_seconds | REAL | NULLABLE | Duration of the generated preview clip (≤10s) |
| file_size_bytes | INTEGER | NULLABLE | Size of the generated MP4 file |
| error_message | TEXT | NULLABLE | Error details if status is failed |
| created_at | TEXT | NOT NULL | ISO 8601 timestamp when record was created |
| updated_at | TEXT | NOT NULL | ISO 8601 timestamp when record was last updated |
Indexes:
idx_preview_clips_file_pathonfile_path(unique, used for lookups and batch queries)idx_preview_clips_statusonstatus(used by file watcher to find pending/failed clips)
Relationships
- VideoPreviewClip → Source Video: One-to-one via
file_path. The preview clip file on disk is located at{PREVIEW_CLIPS_DIRECTORY}/{file_path}.mp4. - VideoPreviewClip → image_exif: Implicit relationship via shared
file_path. No foreign key needed — the EXIF table may not have an entry for every video.
State Transitions
[new video detected] → pending
pending → processing (when generation starts)
processing → complete (when ffmpeg succeeds)
processing → failed (when ffmpeg fails or times out)
failed → pending (on retry / re-scan)
Validation Rules
file_pathmust be a valid relative path within BASE_PATHstatusmust be one of:pending,processing,complete,failedduration_secondsmust be > 0 and ≤ 10.0 when status iscompletefile_size_bytesmust be > 0 when status iscompleteerror_messageshould only be non-null when status isfailed
Storage Layout (Filesystem)
{PREVIEW_CLIPS_DIRECTORY}/
├── 2024/
│ ├── vacation/
│ │ ├── beach.mp4 # Preview for BASE_PATH/2024/vacation/beach.mov
│ │ └── sunset.mp4 # Preview for BASE_PATH/2024/vacation/sunset.mp4
│ └── birthday.mp4 # Preview for BASE_PATH/2024/birthday.avi
└── 2025/
└── trip.mp4 # Preview for BASE_PATH/2025/trip.mkv
All preview clips use .mp4 extension regardless of source format.