Add VideoWall feature: server-side preview clip generation and mobile grid view
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>
This commit is contained in:
115
specs/001-video-wall/quickstart.md
Normal file
115
specs/001-video-wall/quickstart.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Quickstart: VideoWall
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Rust toolchain (stable) with `cargo`
|
||||
- `diesel_cli` installed (`cargo install diesel_cli --no-default-features --features sqlite`)
|
||||
- ffmpeg and ffprobe available on PATH
|
||||
- Node.js 18+ and Expo CLI for mobile app
|
||||
- `.env` file configured with existing variables plus `PREVIEW_CLIPS_DIRECTORY`
|
||||
|
||||
## New Environment Variable
|
||||
|
||||
Add to `.env`:
|
||||
```bash
|
||||
PREVIEW_CLIPS_DIRECTORY=/path/to/preview-clips # Directory for generated preview MP4s
|
||||
```
|
||||
|
||||
## Backend Development
|
||||
|
||||
### 1. Create database migration
|
||||
|
||||
```bash
|
||||
cd C:\Users\ccord\RustroverProjects\ImageApi
|
||||
diesel migration generate create_video_preview_clips
|
||||
```
|
||||
|
||||
Edit the generated `up.sql`:
|
||||
```sql
|
||||
CREATE TABLE video_preview_clips (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
file_path TEXT NOT NULL UNIQUE,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
duration_seconds REAL,
|
||||
file_size_bytes INTEGER,
|
||||
error_message TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_preview_clips_file_path ON video_preview_clips(file_path);
|
||||
CREATE INDEX idx_preview_clips_status ON video_preview_clips(status);
|
||||
```
|
||||
|
||||
Edit `down.sql`:
|
||||
```sql
|
||||
DROP TABLE IF EXISTS video_preview_clips;
|
||||
```
|
||||
|
||||
Regenerate schema:
|
||||
```bash
|
||||
diesel migration run
|
||||
diesel print-schema > src/database/schema.rs
|
||||
```
|
||||
|
||||
### 2. Build and test backend
|
||||
|
||||
```bash
|
||||
cargo build
|
||||
cargo test
|
||||
cargo run
|
||||
```
|
||||
|
||||
Test preview endpoint:
|
||||
```bash
|
||||
# Check preview status
|
||||
curl -X POST http://localhost:8080/video/preview/status \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"paths": ["some/video.mp4"]}'
|
||||
|
||||
# Request preview clip
|
||||
curl http://localhost:8080/video/preview?path=some/video.mp4 \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-o preview.mp4
|
||||
```
|
||||
|
||||
### 3. Verify preview clip generation
|
||||
|
||||
Check that preview clips appear in `PREVIEW_CLIPS_DIRECTORY` with the expected directory structure mirroring `BASE_PATH`.
|
||||
|
||||
## Frontend Development
|
||||
|
||||
### 1. Start the mobile app
|
||||
|
||||
```bash
|
||||
cd C:\Users\ccord\development\SynologyFileViewer
|
||||
npx expo start
|
||||
```
|
||||
|
||||
### 2. Navigate to VideoWall
|
||||
|
||||
From the grid view of any folder containing videos, switch to VideoWall mode. The view should display a 2-3 column grid of looping preview clips.
|
||||
|
||||
## Key Files to Modify
|
||||
|
||||
### Backend (ImageApi)
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/video/ffmpeg.rs` | Add `generate_preview_clip()` function |
|
||||
| `src/video/actors.rs` | Add `PreviewClipGenerator` actor |
|
||||
| `src/video/mod.rs` | Add `generate_preview_clips()` batch function |
|
||||
| `src/main.rs` | Add endpoints, extend file watcher |
|
||||
| `src/database/schema.rs` | Regenerated by Diesel |
|
||||
| `src/database/models.rs` | Add `VideoPreviewClip` struct |
|
||||
| `src/database/preview_dao.rs` | New DAO file |
|
||||
| `src/data/mod.rs` | Add request/response types |
|
||||
| `src/state.rs` | Add PreviewClipGenerator to AppState |
|
||||
|
||||
### Frontend (SynologyFileViewer)
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `app/(app)/grid/video-wall.tsx` | New VideoWall view |
|
||||
| `app/(app)/grid/_layout.tsx` | Add route |
|
||||
| `components/VideoWallItem.tsx` | New preview clip cell component |
|
||||
| `hooks/useVideoWall.ts` | New hook for preview state management |
|
||||
Reference in New Issue
Block a user