# 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_path` on `file_path` (unique, used for lookups and batch queries) - `idx_preview_clips_status` on `status` (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_path` must be a valid relative path within BASE_PATH - `status` must be one of: `pending`, `processing`, `complete`, `failed` - `duration_seconds` must be > 0 and ≤ 10.0 when status is `complete` - `file_size_bytes` must be > 0 when status is `complete` - `error_message` should only be non-null when status is `failed` ## 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.