PlayVideo

Self-Hosting PlayVideo

Deploy PlayVideo on your own infrastructure. Same API, your servers, zero vendor lock-in.

Why Self-Host?

  • Data sovereignty - Keep videos on your infrastructure
  • Cost control - Use your own storage (S3, R2, MinIO)
  • Customization - Modify the code to fit your needs
  • No vendor lock-in - Switch between self-hosted and cloud anytime

Requirements

  • Node.js 18+
  • PostgreSQL 14+
  • FFmpeg
  • Storage backend (local, S3, R2, or MinIO)
  • (Optional) Redis for async processing

Quick Start with Docker

# Clone the repository
git clone https://github.com/vascogaspar/blockbuster.git
cd playvideo

# Copy environment file
cp .env.example .env

# Start with Docker Compose
docker compose up -d

Access at http://localhost:8184

Environment Variables

# Required
DATABASE_URL=postgresql://user:pass@localhost:5432/playvideo
SESSION_SECRET=your-random-secret-at-least-32-chars

# Storage (choose one)
STORAGE_PROVIDER=local  # or 's3' or 'r2'

# For S3/R2
S3_BUCKET=your-bucket
S3_REGION=us-east-1
S3_ACCESS_KEY=xxx
S3_SECRET_KEY=xxx
S3_ENDPOINT=https://xxx.r2.cloudflarestorage.com  # For R2

# Optional - Async processing
REDIS_URL=redis://localhost:6379

# Optional - OAuth (for dashboard login)
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
GITHUB_CLIENT_ID=xxx
GITHUB_CLIENT_SECRET=xxx

# Optional - Billing
STRIPE_SECRET_KEY=xxx
STRIPE_WEBHOOK_SECRET=xxx

Storage Configuration

Local Storage (Development)

STORAGE_PROVIDER=local
LOCAL_STORAGE_PATH=./storage

Files stored in ./storage directory, served via /storage endpoint.

STORAGE_PROVIDER=r2
S3_BUCKET=your-bucket
S3_REGION=auto
S3_ACCESS_KEY=xxx
S3_SECRET_KEY=xxx
S3_ENDPOINT=https://xxx.r2.cloudflarestorage.com
PUBLIC_STORAGE_URL=https://your-bucket.yourdomain.com

R2 offers free egress, making it ideal for video delivery.

AWS S3

STORAGE_PROVIDER=s3
S3_BUCKET=your-bucket
S3_REGION=us-east-1
S3_ACCESS_KEY=xxx
S3_SECRET_KEY=xxx
PUBLIC_STORAGE_URL=https://your-bucket.s3.amazonaws.com

MinIO (Self-Hosted S3)

STORAGE_PROVIDER=s3
S3_BUCKET=videos
S3_REGION=us-east-1
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_ENDPOINT=http://localhost:9000
PUBLIC_STORAGE_URL=http://localhost:9000/videos

Deployment Options

Railway (One-Click)

Deploy on Railway

Render

  1. Fork the repository
  2. Connect to Render
  3. Create a new Web Service from your fork
  4. Add environment variables
  5. Deploy

Docker Compose (Production)

version: '3.8'

services:
  app:
    image: playvideo/playvideo:latest
    ports:
      - "8184:8184"
    environment:
      DATABASE_URL: postgresql://postgres:postgres@db:5432/playvideo
      REDIS_URL: redis://redis:6379
      STORAGE_PROVIDER: r2
      # ... other env vars
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: playvideo
      POSTGRES_PASSWORD: postgres

  redis:
    image: redis:7-alpine

volumes:
  pgdata:

Kubernetes

Helm chart coming soon. For now, use the Docker image with your own manifests.

Database Setup

# Run migrations
npx prisma migrate deploy

# (Optional) Seed with demo data
npx prisma db seed

FFmpeg Installation

FFmpeg is required for video transcoding.

Ubuntu/Debian

apt-get update && apt-get install -y ffmpeg

macOS

brew install ffmpeg

Docker

The official Docker image includes FFmpeg.

Scaling

Horizontal Scaling

Run multiple app instances behind a load balancer. Requires:

  • Shared storage (S3/R2, not local)
  • Redis for job queue coordination

Worker Separation

Run API and workers separately:

# API server
ENABLE_WORKERS=false node dist/index.js

# Worker process
node dist/worker.js

Monitoring

Health Check

curl http://localhost:8184/health

Returns:

{
  "status": "healthy",
  "timestamp": "2026-01-07T12:00:00.000Z",
  "version": "1.0.0"
}

Logs

Logs are written to stdout in JSON format. Use your preferred log aggregator.

Upgrading

# Pull latest
git pull origin main

# Install dependencies
npm install

# Run migrations
npx prisma migrate deploy

# Rebuild
npm run build

# Restart
pm2 restart playvideo

Using the SDK with Self-Hosted

Point the SDK to your instance:

import PlayVideo from '@playvideo/playvideo-sdk';

const bb = new PlayVideo({
  apiKey: 'your-api-key',
  baseUrl: 'https://video.yourdomain.com'
});

// Use exactly like the hosted version
const video = await bb.videos.upload({
  file: './video.mp4',
  collection: 'my-app'
});

Support