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>
3.1 KiB
3.1 KiB
Quickstart: VideoWall
Prerequisites
- Rust toolchain (stable) with
cargo diesel_cliinstalled (cargo install diesel_cli --no-default-features --features sqlite)- ffmpeg and ffprobe available on PATH
- Node.js 18+ and Expo CLI for mobile app
.envfile configured with existing variables plusPREVIEW_CLIPS_DIRECTORY
New Environment Variable
Add to .env:
PREVIEW_CLIPS_DIRECTORY=/path/to/preview-clips # Directory for generated preview MP4s
Backend Development
1. Create database migration
cd C:\Users\ccord\RustroverProjects\ImageApi
diesel migration generate create_video_preview_clips
Edit the generated up.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:
DROP TABLE IF EXISTS video_preview_clips;
Regenerate schema:
diesel migration run
diesel print-schema > src/database/schema.rs
2. Build and test backend
cargo build
cargo test
cargo run
Test preview endpoint:
# 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
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 |