# Implementation Plan: VideoWall **Branch**: `001-video-wall` | **Date**: 2026-02-25 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/001-video-wall/spec.md` ## Summary Add a VideoWall feature spanning the Rust API backend and React Native mobile app. The backend generates 480p MP4 preview clips (up to 10 seconds, composed of 10 equally spaced 1-second segments) using ffmpeg, extending the existing `OverviewVideo` pattern in `src/video/ffmpeg.rs`. The mobile app adds a VideoWall view using `expo-video` and FlatList to display a responsive 2-3 column grid of simultaneously looping, muted preview clips with audio-on-long-press. Preview clips are cached on disk, served via new API endpoints, and generated proactively by the file watcher. ## Technical Context **Language/Version**: Rust (stable, Cargo) for backend API; TypeScript / React Native (Expo SDK 52) for mobile app **Primary Dependencies**: actix-web 4, Diesel 2.2 (SQLite), ffmpeg/ffprobe (CLI), expo-video 3.0, expo-router 6.0, react-native-reanimated 4.1 **Storage**: SQLite (preview clip status tracking), filesystem (MP4 preview clips in `PREVIEW_CLIPS_DIRECTORY`) **Testing**: `cargo test` for backend; manual testing for mobile app **Target Platform**: Linux server (API), iOS/Android (mobile app via Expo) **Project Type**: Mobile app + REST API (two separate repositories) **Performance Goals**: <3s VideoWall load for 50 pre-generated previews; <30s per clip generation; <5MB per clip; smooth simultaneous playback of 6-12 clips **Constraints**: Semaphore-limited concurrent ffmpeg processes (existing pattern); 480p resolution to keep bandwidth/CPU manageable; audio track preserved but muted by default **Scale/Scope**: Hundreds to low thousands of videos per library; single user at a time ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* Constitution is an unfilled template — no project-specific gates defined. **PASS** (no violations possible). Post-Phase 1 re-check: Still PASS — no gates to evaluate. ## Project Structure ### Documentation (this feature) ```text specs/001-video-wall/ ├── plan.md # This file ├── research.md # Phase 0 output ├── data-model.md # Phase 1 output ├── quickstart.md # Phase 1 output ├── contracts/ # Phase 1 output │ └── api-endpoints.md └── tasks.md # Phase 2 output (/speckit.tasks command) ``` ### Source Code (repository root) ```text # Backend (ImageApi - Rust) src/ ├── video/ │ ├── ffmpeg.rs # Add generate_preview_clip() using existing pattern │ ├── actors.rs # Add PreviewClipGenerator actor (semaphore-limited) │ └── mod.rs # Add generate_preview_clips() batch function ├── main.rs # Add GET /video/preview, POST /video/preview/status endpoints │ # Extend file watcher to trigger preview generation ├── database/ │ ├── schema.rs # Add video_preview_clips table │ └── models.rs # Add VideoPreviewClip model │ └── preview_dao.rs # New DAO for preview clip status tracking └── data/ └── mod.rs # Add PreviewClipRequest, PreviewStatusRequest types # Frontend (SynologyFileViewer - React Native) app/(app)/grid/ ├── video-wall.tsx # New VideoWall view (FlatList grid) └── _layout.tsx # Add video-wall route to stack components/ └── VideoWallItem.tsx # Single preview clip cell (expo-video player) hooks/ └── useVideoWall.ts # Preview clip fetching, status polling, audio state ``` **Structure Decision**: Mobile + API pattern. Backend changes extend existing `src/video/` module and `src/main.rs` handlers following established conventions. Frontend adds a new route under the existing grid stack navigator with a dedicated component and hook. ## Complexity Tracking No constitution violations to justify.