Files
velour/docs/architecture.md
Dan Milne 88a906064f
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled
Much base work started
2025-10-31 14:36:14 +11:00

7.9 KiB

Velour - Video Library Application Architecture

Velour is a self-hosted video library application built with Rails 8 and Hotwire, designed for personal video collections with optional multi-user support and federation capabilities.

Quick Start

Phase 1 (MVP) - Local Filesystem

  • Goal: Complete local video library with grouping and transcoding
  • Timeline: 5 weeks
  • Documentation: Phase 1 Details

Phase 2 - Authentication & Multi-User

  • Goal: User management and per-user playback history
  • Documentation: Phase 2 Details

Phase 3 - Remote Sources & Import

  • Goal: S3, JellyFin, and web directory integration
  • Documentation: Phase 3 Details

Phase 4 - Federation

  • Goal: Share libraries between Velour instances
  • Documentation: Phase 4 Details

Phase 5 - Audio Support

  • Goal: Add music and audiobook support using extensible MediaFile architecture
  • Documentation: Phase 5 Details

Technology Stack

Core Technologies

  • Ruby on Rails 8.x - Modern Rails with Solid Queue and Solid Cache
  • SQLite3 - Single-user database (PostgreSQL path available)
  • Hotwire - Turbo + Stimulus for reactive frontend
  • Video.js - HTML5 video player with plugins
  • FFmpeg - Video transcoding and metadata extraction
  • Active Storage - File management for thumbnails/assets
  • TailwindCSS - Utility-first CSS framework

Key Rails 8 Features

  • Solid Queue - Background job processing
  • ActiveJob 8.1 Continuations - Progress tracking
  • Structured Event Reporting - Real-time job updates
  • TurboFrame Permanent Attributes - Uninterrupted video playback

Architecture Overview

Video Processing Pipeline

  1. File Discovery - Automatic scanning of mounted directories
  2. Metadata Extraction - FFmpeg analysis with xxhash64 deduplication
  3. Thumbnail Generation - Preview images at 10% mark
  4. Transcoding - Web-compatible MP4 creation for incompatible formats
  5. Storage - Files remain in original locations with managed assets

Storage Flexibility

  • Local Files - Primary storage, original files untouched
  • Heuristic Discovery - Automatic categorization of mounted directories
  • Remote Sources (Phase 3) - S3, JellyFin, web directories
  • Federation (Phase 4) - Cross-instance sharing

Data Model

Work (canonical content) - has_many -> Videos (different files/qualities)
Video (inherits from MediaFile) - belongs_to -> StorageLocation (where file lives)
Video - has_many -> VideoAssets (thumbnails, previews)
Video - has_many -> PlaybackSessions (user viewing history)
Work - has_many -> ExternalIds (IMDb, TMDb references)

**Extensible Architecture**: MediaFile base class supports future Audio model
MediaFile - common functionality (streaming, processing, metadata)
Video - video-specific functionality (resolution, codecs)
Audio (Phase 5) - audio-specific functionality (bitrate, sample rate, album art)

Key Features

Phase 1 (MVP)

  • Local video library scanning and organization
  • Video streaming with seeking support
  • Automatic transcoding to web-compatible formats
  • Duplicate detection and grouping into "works"
  • Uninterrupted playback with TurboFrame
  • Real-time processing progress with Turbo Streams

Phase 2 (Multi-User)

  • Rails authentication with OIDC extension
  • Admin user bootstrap flow
  • Per-user playback history and preferences
  • Storage location management (admin only)

Phase 3 (Remote Sources)

  • S3 storage location support
  • JellyFin server integration
  • Web directory browsing
  • Video import system with progress tracking

Phase 4 (Federation)

  • Cross-instance API with authentication
  • Remote video streaming
  • Federated library discovery
  • Security and rate limiting

Phase 5 (Audio Support)

  • Audio model inheriting from MediaFile
  • Music library with album/artist organization
  • Audiobook support with chapter tracking
  • Audio processing and transcoding pipeline

Development Phases

Phase 1A: Core Foundation (Week 1-2)

  • Models and migrations
  • Storage adapter pattern
  • File scanning service
  • Basic UI

Phase 1B: Video Playback (Week 3)

  • Video streaming with byte-range support
  • Video.js integration
  • Playback session tracking

Phase 1C: Processing Pipeline (Week 4)

  • FFmpeg integration
  • Background job processing
  • Thumbnail generation

Phase 1D: Works & Grouping (Week 5)

  • Duplicate detection
  • Manual grouping interface
  • Search and filtering

Quick Setup

Docker Compose

version: '3.8'
services:
  velour:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - /path/to/movies:/videos/movies:ro
      - /path/to/tv:/videos/tv:ro
      - ./velour_data:/app/velour_data
    environment:
      - RAILS_ENV=production
      - ADMIN_EMAIL=admin@yourdomain.com

Environment Variables

# Required
RAILS_MASTER_KEY=your_master_key
ADMIN_EMAIL=admin@yourdomain.com

# Video Processing
FFMPEG_PATH=/usr/bin/ffmpeg
VIDEOS_PATH=./velour_data/videos
MAX_TRANSCODE_SIZE_GB=50

# Background jobs (SolidQueue)
SOLID_QUEUE_PROCESSES="*:2"  # 2 workers for all queues

# Optional (Phase 2+)
OIDC_ISSUER=https://your-provider.com
OIDC_CLIENT_ID=your_client_id

# Optional (Phase 3+)
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret

File Structure

/app
├── app/
│   ├── models/           # ActiveRecord models
│   ├── services/         # Business logic objects
│   ├── jobs/            # Background jobs
│   └── controllers/     # Web controllers
├── lib/
│   └── osmoviehash.rb   # Video fingerprinting
├── config/
│   └── routes.rb        # Application routes
└── docs/
    ├── architecture.md  # This file
    └── phases/          # Detailed phase documentation
        ├── phase_1.md
        ├── phase_2.md
        ├── phase_3.md
        └── phase_4.md

Design Decisions

Why Rails + Hotwire?

  • Convention over Configuration - Faster development
  • Integrated System - Single framework for frontend and backend
  • Real-time Capabilities - Turbo Streams for job progress
  • Video Focus - Uninterrupted playback with TurboFrame

Why SQLite First?

  • Single User Focus - Simpler deployment and maintenance
  • Migration Path - Easy upgrade to PostgreSQL if needed
  • Performance - Excellent for personal video libraries

Why Separate Transcoding?

  • Original Preservation - Never modify source files
  • Quality Choice - Users keep original quality when available
  • Storage Efficiency - Transcode only when needed
  • Browser Compatibility - Web-friendly formats for streaming

Getting Started

  1. Clone and setup:

    git clone <repository>
    cd velour
    bundle install
    rails db:setup
    
  2. Configure storage:

    # Edit docker-compose.yml
    volumes:
      - /path/to/your/movies:/videos/movies:ro
      - /path/to/your/tv:/videos/tv:ro
    
  3. Start the application:

    docker-compose up
    # or
    rails server
    
  4. Visit http://localhost:3000 and follow the first-user setup

Contributing

When adding features:

  1. Follow Rails Conventions - Use generators and standard patterns
  2. Maintain Phase Structure - Add features to appropriate phase
  3. Test Thoroughly - Include model, service, and system tests
  4. Update Documentation - Keep architecture docs current

Resources


Next Steps: Start with Phase 1 (MVP) for complete implementation details.