Skip to content

Angablade/JellyPreviews

Repository files navigation

JellyPreviews

JellyPreviews Logo

A powerful video preview generation service for Jellyfin

JellyPreviews automatically generates video preview clips for your Jellyfin media library, providing Netflix-style hover previews for an enhanced browsing experience.

.NET Docker


About This Tool

JellyPreviews automatically generates video preview clips for your Jellyfin media library, providing Netflix-style hover previews for an enhanced browsing experience.

Key Features

  • Automatic preview generation with smart scene detection
  • Hardware-accelerated encoding support (Intel QSV, NVIDIA NVENC, VA-API)
  • Intelligent caching system for instant playback
  • Webhook notifications for Discord and other services
  • Customizable encoding presets for different quality/performance needs
  • Multi-server support to manage multiple Jellyfin instances

Acknowledgments

This project was inspired by and uses partial code from BobHasNoSoul's jellyfin-video-previews. Special thanks to BobHasNoSoul for the original JavaScript implementation and the inspiration that made this project possible.


Features

Core Functionality

  • Automatic Preview Generation: Create 3-5 second preview clips from movies and TV episodes
  • On-Hover Playback: Previews play automatically when hovering over items in Jellyfin
  • Smart Container Detection: Automatically handles TV Series and Seasons by fetching the first episode
  • Multiple Format Support: WebM, MP4, and MKV output formats
  • Hardware Acceleration: Optional GPU encoding (NVIDIA NVENC, Intel QuickSync, AMD VA-API)
  • Intelligent Caching: Efficient storage with LRU cache management and automatic cleanup

Advanced Features

  • Library Management: Scan and batch-generate previews for entire libraries
  • Webhook Integration: Auto-generate previews when new content is added to Jellyfin
  • Discord Notifications: Send preview notifications to Discord with embedded video files
  • Multi-Server Support: Connect to multiple Jellyfin servers simultaneously
  • Real-time Monitoring: Web-based admin panel with job tracking and system metrics
  • Customizable Settings: Configure duration, format, codec, bitrate, and more

Quick Start

Prerequisites

  • Docker or .NET 8.0 Runtime
  • Jellyfin Server (10.8.0+)
  • FFmpeg (included in Docker images)

Docker Deployment

Basic Setup:

docker run -d \
  --name jellypreviews \
  -p 8080:8080 \
  -v ./cache:/data/cache \
  -v ./config:/config \
  -e JELLYFIN_SERVER_URL=http://jellyfin:8096 \
  -e JELLYFIN_API_KEY=your-api-key-here \
  jellypreviews:latest

Docker Compose:

version: '3.8'

services:
  jellypreviews:
    image: jellypreviews:latest
    container_name: jellypreviews
    ports:
      - "8080:8080"
    volumes:
      - ./data/cache:/data/cache
      - ./data/config:/config
    environment:
      - JELLYFIN_SERVER_URL=http://jellyfin:8096
      - JELLYFIN_API_KEY=your-api-key
      - PREVIEW_DURATION_SECONDS=4
      - PREVIEW_FORMAT=webm
      - CONCURRENCY=2
    restart: unless-stopped

With GPU Support (NVIDIA):

services:
  jellypreviews:
    image: jellypreviews:latest
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - FFMPEG_CODEC=h264_nvenc

Jellyfin Integration

JS Injector

Add this script with JS Injector:

// set the global variable first
window.PREVIEW_SERVICE_URL = "http://your-server:8080";

// create the script element
const script = document.createElement("script");
script.src = window.PREVIEW_SERVICE_URL + "/config/vidprev.js?version=multi";
script.async = true;

// append to page
document.head.appendChild(script);

With custom settings:

// Set PREVIEW_CONFIG
window.PREVIEW_CONFIG = {
    playbackSpeed: 1.0,
    hoverDelay: 1000,
    maxPollAttempts: 30,
    pollInterval: 2000,
    maxCacheSize: 30
};

// Set PREVIEW_SERVICE_URL
window.PREVIEW_SERVICE_URL = "http://your-server:8080";

// Dynamically load the script
const script = document.createElement("script");
script.src = "http://your-server:8080/config/vidprev.js?version=multi";   // <-- your JS URL
script.async = true;

document.head.appendChild(script);

Direct Injection Directly in your Jellyfin index.html:

<script>
  window.PREVIEW_SERVICE_URL = 'http://your-server:8080';
</script>
<script src="http://your-server:8080/config/vidprev.js?version=multi"></script>

With Custom Settings

<script>
window.PREVIEW_CONFIG = {
    playbackSpeed: 1.0,
    hoverDelay: 1000,
    maxPollAttempts: 30,
    pollInterval: 2000,
    maxCacheSize: 30
};
window.PREVIEW_SERVICE_URL="https://your-server:8080";
</script>
<script src="http://your-server:8080/config/vidprev.js?version=multi"></script>

Access Admin Panel

Navigate to: http://your-server:8080/


Configuration

Environment Variables

Variable Default Description
JELLYFIN_SERVER_URL - Jellyfin server URL (required)
JELLYFIN_API_KEY - Jellyfin API key (required)
PREVIEW_DURATION_SECONDS 4 Preview clip duration (1-30)
PREVIEW_FORMAT webm Output format (webm, mp4, mkv)
FFMPEG_CODEC libx264 Video codec (see below)
PREVIEW_BITRATE 300k Target bitrate
INCLUDE_AUDIO true Include audio in previews
CONCURRENCY 2 Concurrent generation jobs (1-16)
CACHE_DIR /data/cache Cache directory path
MAX_CACHE_SIZE 10737418240 Max cache size (10GB)

Video Codecs

Software (CPU):

  • libx264 - H.264 (most compatible)
  • libx265 - H.265 (better compression)
  • libvpx-vp9 - VP9 (best for WebM)

Hardware (GPU):

  • h264_nvenc - NVIDIA NVENC
  • h264_qsv - Intel QuickSync
  • h264_vaapi - AMD VA-API

Settings File

Configuration is stored in /config/settings.json:

{
  "previewDurationSeconds": 4,
  "previewStartSeconds": 300,
  "previewFormat": "webm",
  "ffmpegCodec": "libx264",
  "previewBitrate": "300k",
  "includeAudio": true,
  "concurrency": 2,
  "jellyfinServers": [
    {
    "name": "My Server",
      "url": "http://jellyfin:8096",
    "apiKey": "your-api-key",
      "enabled": true
    }
  ],
  "webhookEnabled": false,
  "autoGenerateEnabled": false
}

Usage

On-Hover Generation (Automatic)

  1. Hover over any movie or TV show in Jellyfin
  2. Preview generates automatically on first hover (takes 20-30 seconds)
  3. Subsequent hovers play instantly from cache

Library Management (Batch)

  1. Open Admin Panel: http://your-server:8080/
  2. Navigate to Library Management tab
  3. Select your Jellyfin server and library
  4. Click Generate All Previews
  5. Monitor progress in Jobs tab

Webhook Automation (Recommended)

  1. Install Jellyfin Webhook plugin
  2. Configure webhook to POST to: http://jellypreviews:8080/api/webhook/jellyfin
  3. Enable auto-generation in JellyPreviews settings
  4. Previews generate automatically when content is added

Hardware Acceleration

NVIDIA GPU

Docker Compose:

services:
  jellypreviews:
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - FFMPEG_CODEC=h264_nvenc
      - HARDWARE_ACCELERATION=cuda

Requirements:

  • NVIDIA GPU (GTX 600+ or newer)
  • NVIDIA Container Toolkit installed
  • CUDA support

Intel QuickSync

Docker Compose:

services:
  jellypreviews:
    devices:
      - /dev/dri:/dev/dri
    environment:
      - FFMPEG_CODEC=h264_qsv
      - HARDWARE_ACCELERATION=qsv

Requirements:

  • Intel CPU with QuickSync (6th gen+)
  • iGPU enabled in BIOS
  • /dev/dri device access

AMD VA-API

Docker Compose:

services:
  jellypreviews:
    devices:
      - /dev/dri:/dev/dri
    environment:
      - FFMPEG_CODEC=h264_vaapi
      - HARDWARE_ACCELERATION=vaapi

Requirements:

  • AMD GPU with VA-API support
  • VA-API drivers installed
  • /dev/dri device access

Architecture

Components

  • ASP.NET Core Web API: REST API for preview generation and status
  • Background Worker: Processes preview generation jobs
  • Cache Service: Manages preview storage and retrieval
  • Jellyfin Integration: Authenticates and fetches media metadata
  • FFmpeg Service: Handles video encoding
  • Admin Dashboard: Web-based management interface
  • Client Script: JavaScript injection for Jellyfin hover functionality

How It Works

┌──────────┐
│  User    │
│  Hovers  │
└────┬─────┘
     │
     ▼
┌─────────────┐
│ vidprev.js  │
└─────┬───────┘
      │
      ├─► Check browser cache
      │   ├─► HIT: Play immediately
      │   └─► MISS: Continue
      │
      ▼
┌──────────────┐
│ POST /preview│
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│ API Controller   │
└──────┬───────────┘
       │
       ├─► Check server cache
       │   ├─► HIT: Return preview
       │   └─► MISS: Continue
       │
       ├─► Check job queue
       │   ├─► EXISTS: Return job ID
       │   └─► NONE: Create job
       │
       ▼
┌──────────────┐
│  Job Queue   │
└──────┬───────┘
       │
       ▼
┌──────────────┐
│   Worker     │
└──────┬───────┘
       │
       ├─► Download from Jellyfin
       ├─► Run FFmpeg
       ├─► Save to cache
       └─► Update job status
       │
       ▼
┌──────────────┐
│   Cache      │
└──────┬───────┘
       │
       ▼
┌──────────────────┐
│ vidprev.js       │
│ (polling status) │
└──────┬───────────┘
       │
       ▼
┌──────────────┐
│ Play Preview │
└──────────────┘

API Endpoints

Preview Endpoints

  • GET /preview?id={itemId} - Get or generate preview
  • GET /preview/status/{hash} - Check generation status
  • GET /preview/download/{hash} - Download preview file

Admin Endpoints

  • GET /admin/api/status - Get system status
  • GET /admin/api/jobs - List all jobs
  • POST /admin/api/jobs/{jobId}/cancel - Cancel job
  • GET /admin/api/cache - List cached previews
  • DELETE /admin/api/cache/{hash} - Delete cached preview
  • GET /admin/api/settings - Get configuration
  • PUT /admin/api/settings - Update configuration

Webhook Endpoints

  • POST /api/webhook/jellyfin - Receive Jellyfin webhook
  • GET /api/webhook/jellyfin/test - Test webhook endpoint

See API_Endpoints.md for complete API documentation.


Performance

Typical Generation Times

Scenario Time per Preview Throughput
Software Encoding (CPU) 20-30s ~120/hour
Hardware Encoding (GPU) 3-5s ~720/hour
4K Content (CPU) 60-90s ~40/hour
4K Content (GPU) 10-15s ~240/hour

Cache Efficiency

  • Storage: ~150KB per preview (4s @ 300k bitrate)
  • 1000 movies: ~150MB total cache
  • 10000 movies: ~1.5GB total cache
  • Hit Rate: 90%+ after initial generation

Resource Usage

  • CPU: 50-100% per job (software encoding)
  • RAM: ~512MB base + ~100MB per concurrent job
  • Storage: Variable (depends on cache size)
  • Network: Minimal (only for Jellyfin API calls)

Troubleshooting

Previews Don't Appear

Check:

  1. Service is running: docker ps | grep jellypreviews
  2. Client script is loaded: Open browser console (F12), look for [VidPrev] messages
  3. Test endpoint: curl http://localhost:8080/health
  4. Check logs: docker logs jellypreviews -f

Generation Fails

Check:

  1. FFmpeg is available: docker exec jellypreviews ffmpeg -version
  2. Storage space: df -h /data/cache
  3. File permissions: Cache directory must be writable
  4. Video codec compatibility: Try different codec

Slow Performance

Solutions:

  1. Enable hardware acceleration
  2. Lower preview quality: PREVIEW_BITRATE=200k
  3. Shorter duration: PREVIEW_DURATION_SECONDS=3
  4. Increase concurrency: CONCURRENCY=4

See Troubleshooting.md for detailed solutions.


Documentation


Development

Building from Source

# Clone repository
git clone https://github.com/Angablade/JellyPreviews.git
cd JellyPreviews

# Build with .NET
dotnet build

# Run locally
dotnet run --project JellyPreviews

# Build Docker image
docker build -t jellypreviews:latest .

Requirements

  • .NET 8.0 SDK
  • FFmpeg (for local development)
  • Jellyfin server for testing

Project Structure

JellyPreviews/
├── Controllers/         # API endpoints
├── Services/    # Business logic
├── Models/      # Data models
├── Workers/            # Background workers
├── wwwroot/        # Static files (admin panel)
│   ├── js/   # JavaScript modules
│   ├── css/    # Stylesheets
│   └── img/    # Images
├── Docs/              # Documentation
└── Dockerfile       # Docker build configuration

Acknowledgments

  • Jellyfin - Open source media server
  • FFmpeg - Video processing framework
  • ASP.NET Core - Web framework
  • Docker - Containerization platform
  • BobHasNoSoul - Original inspiration and codebase

Support

Made with ❤️ for the Jellyfin community

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors