Sign inSign up

ttlequals0/pixelprobe

By ttlequals0

•Updated 7 days ago

PixelProbe detects corrupted video, image, and audio files across media libraries

Image
Monitoring & observability
0

10K+

ttlequals0/pixelprobe repository overview

PixelProbe

⁠PixelProbe

Find corrupted media files before they ruin your day. PixelProbe scans video, image, and audio libraries using FFmpeg, ImageMagick, and PIL, then shows you exactly what's broken.

⁠What it does

  • Scans video files (MP4, MKV, AVI, MOV, ProRes, MXF, and more) with FFmpeg deep analysis
  • Validates images (JPEG, PNG, TIFF, WebP, HEIC, plus RAW formats from Canon, Nikon, Sony, Fujifilm, etc.)
  • Checks audio files (MP3, FLAC, WAV, AAC, DSD, Dolby/DTS)
  • 92 file formats total across video, image, and audio
  • Tested with libraries of 1M+ files and individual files over 50GB

⁠What you get

  • Web UI with dark/light themes, mobile support, and in-browser media preview
  • Scheduled scans via cron expressions or simple intervals
  • Parallel scanning with configurable worker threads (10-24 recommended)
  • Real-time progress tracking with ETA
  • REST API with OpenAPI/Swagger docs
  • Multi-user auth with role-based access and API tokens
  • Trend analytics, PDF/JSON exports, and audit logging
  • Healthcheck.io integration for monitoring

⁠Quick start

Create a .env file:

SECRET_KEY=generate-a-long-random-string-here
MEDIA_PATH=/path/to/your/media

Create a docker-compose.yml:

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: pixelprobe
      POSTGRES_USER: pixelprobe
      POSTGRES_PASSWORD: changeme
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine

  pixelprobe:
    image: ttlequals0/pixelprobe:latest
    environment:
      SECRET_KEY: ${SECRET_KEY}
      POSTGRES_HOST: postgres
      POSTGRES_PASSWORD: changeme
      CELERY_BROKER_URL: redis://redis:6379/0
      CELERY_RESULT_BACKEND: redis://redis:6379/0
      SCAN_PATHS: /media
      MAX_WORKERS: 10
    volumes:
      - ${MEDIA_PATH}:/media:ro
    ports:
      - "5000:5000"
    depends_on:
      - postgres
      - redis

  celery-worker:
    image: ttlequals0/pixelprobe:latest
    command: python celery_worker.py
    environment:
      SECRET_KEY: ${SECRET_KEY}
      POSTGRES_HOST: postgres
      POSTGRES_PASSWORD: changeme
      CELERY_BROKER_URL: redis://redis:6379/0
      CELERY_RESULT_BACKEND: redis://redis:6379/0
      SCAN_PATHS: /media
      MAX_WORKERS: 10
    volumes:
      - ${MEDIA_PATH}:/media:ro
    depends_on:
      - postgres
      - redis

volumes:
  postgres_data:

Then:

docker-compose up -d

Open http://localhost:5000⁠ and create your admin account through the first-run setup wizard.

⁠Architecture

Four containers, each with a single job:

ContainerImageRole
pixelprobettlequals0/pixelprobeWeb UI and REST API (Gunicorn)
celery-workerttlequals0/pixelprobeBackground scanning and scheduled tasks
postgrespostgres:15-alpineDatabase
redisredis:7-alpineTask queue broker for Celery

The app and worker share the same image. The worker runs python celery_worker.py instead of Gunicorn.

⁠Environment variables

Required:

VariableDescription
SECRET_KEYFlask session secret. Generate with python -c "import secrets; print(secrets.token_hex(32))"
MEDIA_PATHHost path to your media files (mounted read-only into the container)

Tuning:

VariableDefaultDescription
MAX_WORKERS10Parallel file scanning threads per task. 10-24 recommended.
CELERY_CONCURRENCY4Concurrent Celery tasks. Independent from MAX_WORKERS.
BATCH_SIZE100Files per batch during discovery phase
SCAN_PATHS/mediaComma-separated paths inside the container to scan

Scheduling:

VariableDefaultDescription
PERIODIC_SCAN_SCHEDULE(none)Cron expression for automated scans
CLEANUP_SCHEDULE(none)Cron expression for automated cleanup

Filtering:

VariableDefaultDescription
EXCLUDED_PATHS(none)Comma-separated paths to skip
EXCLUDED_EXTENSIONS.txt,.log,.mdFile extensions to ignore

Other:

VariableDefaultDescription
TZUTCContainer timezone
POSTGRES_PASSWORDchangemeDatabase password (change this)
FLASK_ENVproductionFlask environment

⁠Multiple media directories

Mount each directory separately and list them in SCAN_PATHS:

environment:
  SCAN_PATHS: /movies,/tv-shows,/music
volumes:
  - /mnt/movies:/movies:ro
  - /mnt/tv-shows:/tv-shows:ro
  - /mnt/music:/music:ro

⁠User permissions

The app and celery-worker containers must run as the same user, and that user needs read access to your media files. Add this to both services:

user: "1000:1000"  # Match your host user's UID:GID

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:6ba2d8aa9…

Size

760.5 MB

Last updated

7 days ago

docker pull ttlequals0/pixelprobe