Skip to content

avidflyer17/VOD-Project

Repository files navigation

VOD-PROJET 🎬

Plateforme de vente de packs vidéos avec streaming sécurisé, optimisée pour un homelab avec Traefik.

📋 Table des matières

✨ Fonctionnalités

  • 🔐 Authentification : NextAuth avec vérification email obligatoire
  • 💳 Paiements : Intégration LemonSqueezy avec webhooks
  • 🎥 Streaming sécurisé : HLS + X-Accel-Redirect via Nginx
  • 🔒 Protection : Liens signés + watermarking côté client
  • 🌐 Reverse proxy : Traefik pour le routage et SSL
  • 📧 Emails : Nodemailer pour vérification et confirmations

🛠 Stack technique

Backend

  • Framework : Next.js 14+ (App Router, TypeScript)
  • Auth : NextAuth.js (Auth.js) avec Prisma
  • Database : PostgreSQL
  • Cache : Redis
  • ORM : Prisma

Frontend

  • React : Server & Client Components
  • Video Player : Video.js avec HLS
  • Styling : CSS moderne avec design system

Infrastructure

  • Reverse Proxy : Traefik (sur l'hôte)
  • Media Server : Nginx (X-Accel-Redirect)
  • Containerisation : Docker Compose
  • Streaming : HLS (HTTP Live Streaming)

🏗 Architecture

┌─────────────┐
│   Traefik   │ ← Port 80/443 (sur l'hôte)
└──────┬──────┘
       │
       ▼
┌─────────────────┐
│   Next.js App   │ ← Labels Traefik
│    (Port 3000)  │
└────────┬────────┘
         │
         ├─────→ PostgreSQL (DB)
         ├─────→ Redis (Cache)
         └─────→ Nginx (Media Server)
                      │
                      └─── /videos (volume partagé)

Protection des contenus

  1. Liens signés : Génération HMAC avec TTL configurable
  2. X-Accel-Redirect : Nginx sert les fichiers via location interne
  3. HLS Streaming : Empêche le téléchargement direct
  4. Watermarking client : Overlay dynamique avec email utilisateur

📦 Installation

Prérequis

  • Docker & Docker Compose
  • Traefik configuré sur l'hôte avec le réseau br-dams
  • Node.js 20+ (pour le développement local)
  • FFmpeg (pour la conversion HLS)

1. Cloner le projet

git clone <votre-repo>
cd dw-stream

2. Configuration

Copier le fichier d'environnement :

cp .env.example .env

Éditer .env avec vos valeurs :

# Database
DATABASE_URL="postgresql://voduser:vodpassword@db:5432/voddb"

# NextAuth
NEXTAUTH_URL="https://vod.yourdomain.com"
NEXTAUTH_SECRET="votre-secret-tres-long-min-32-caracteres"

# LemonSqueezy
LEMONSQUEEZY_API_KEY="votre-api-key"
LEMONSQUEEZY_STORE_ID="votre-store-id"
LEMONSQUEEZY_WEBHOOK_SECRET="votre-webhook-secret"

# SMTP (exemple avec Gmail)
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="[email protected]"
SMTP_PASSWORD="votre-app-password"
SMTP_FROM="VOD Platform <[email protected]>"

# Signed URLs
SIGNED_URL_SECRET="autre-secret-pour-videos"
SIGNED_URL_TTL="3600"

3. Configurer Traefik

Dans docker-compose.yml, ajustez le domaine :

labels:
  - "traefik.http.routers.vod-app.rule=Host(`vod.yourdomain.com`)"

4. Créer le dossier vidéos sur l'hôte

sudo mkdir -p /home/user/data/vod/videos
sudo chown -R $USER:$USER /home/user/data/vod

🚀 Déploiement

Développement local (sans Docker)

# Installer les dépendances
npm install

# Démarrer PostgreSQL et Redis (via Docker ou local)
# ...

# Générer Prisma Client
npx prisma generate

# Créer les migrations
npx prisma migrate dev

# Démarrer le serveur de dev
npm run dev

Accéder à : http://localhost:3000

Production (Docker Compose)

# Construire et démarrer les conteneurs
docker-compose up -d

# Vérifier les logs
docker-compose logs -f app

# Exécuter les migrations Prisma
docker-compose exec app npx prisma migrate deploy

Accéder à : https://vod.yourdomain.com (via Traefik)

Commandes utiles

# Arrêter les services
docker-compose down

# Reconstruire après modification
docker-compose up -d --build

# Voir les logs
docker-compose logs -f

# Accéder à la base de données
docker-compose exec db psql -U voduser -d voddb

# Prisma Studio (interface DB)
docker-compose exec app npx prisma studio

🎥 Gestion des vidéos

1. Convertir vos vidéos en HLS

Rendre le script exécutable :

chmod +x scripts/convert-to-hls.sh

Convertir une vidéo :

./scripts/convert-to-hls.sh ma-video.mp4 formation-1 intro

Cela crée :

/home/user/data/vod/videos/
└── formation-1/
    └── intro/
        ├── playlist.m3u8
        ├── segment_000.ts
        ├── segment_001.ts
        └── ...

2. Commande FFmpeg manuelle (alternative)

Pour plus de contrôle :

ffmpeg -i input.mp4 \
  -c:v libx264 -crf 23 -preset medium \
  -c:a aac -b:a 128k \
  -sc_threshold 0 \
  -g 48 -keyint_min 48 \
  -hls_time 10 \
  -hls_playlist_type vod \
  -hls_segment_filename "/home/user/data/vod/videos/bundle-1/video-1/segment_%03d.ts" \
  -f hls \
  "/home/user/data/vod/videos/bundle-1/video-1/playlist.m3u8"

Paramètres expliqués :

  • -crf 23 : Qualité (0-51, 23 = bonne qualité)
  • -hls_time 10 : Durée des segments (10 secondes)
  • -hls_playlist_type vod : Type de playlist VOD
  • -g 48 -keyint_min 48 : Keyframe tous les 2 secondes (pour seeking)

3. Ajouter la vidéo en base de données

Via Prisma Studio (npx prisma studio) ou SQL :

-- 1. Créer un bundle
INSERT INTO "Bundle" (id, title, description, price, currency, "variantId", active)
VALUES (
  'bundle-1',
  'Formation Complete',
  'Apprenez tout sur...',
  99.99,
  'EUR',
  'lemonsqueezy-variant-id',
  true
);

-- 2. Ajouter les vidéos
INSERT INTO "Video" (id, title, description, "hlsPath", "bundleId", "order")
VALUES (
  'video-1',
  'Introduction',
  'Présentation du cours',
  'formation-1/intro/playlist.m3u8',
  'bundle-1',
  1
);

🔔 Webhooks LemonSqueezy

Configuration

  1. Dans votre Dashboard LemonSqueezy, allez dans Settings > Webhooks
  2. Créez un nouveau webhook :
    • URL : https://vod.yourdomain.com/api/webhooks/lemonsqueezy
    • Events : Sélectionner order_created (et optionnellement subscription_created)
    • Secret : Générer et copier dans .envLEMONSQUEEZY_WEBHOOK_SECRET

Événements gérés

  • order_created : Création automatique de Purchase en DB
  • subscription_created : Support des abonnements (optionnel)

Test du webhook

Utiliser l'outil de test LemonSqueezy ou :

curl -X POST https://vod.yourdomain.com/api/webhooks/lemonsqueezy \
  -H "Content-Type: application/json" \
  -H "X-Signature: votre-signature-hmac" \
  -d '{ "meta": { "event_name": "order_created" }, ... }'

🔒 Sécurité

Watermarking

Le watermarking est côté client uniquement pour économiser le CPU :

  • Overlay React avec email de l'utilisateur
  • Position et rotation aléatoires toutes les 10s
  • Semi-transparent, non-interactif

Limites : Un utilisateur technique peut le contourner (CSS/DevTools).

Protection principale : HLS + Liens signés empêchent le partage direct des URLs.

Liens signés

  • Génération HMAC SHA-256 avec secret
  • TTL configurable (défaut: 1 heure)
  • Validation côté serveur avant streaming

X-Accel-Redirect

  • Nginx sert les fichiers via location internal
  • Accès direct aux fichiers bloqué
  • Next.js contrôle l'autorisation

Bonnes pratiques

  1. Secrets forts : Utilisez des secrets de 32+ caractères
  2. HTTPS obligatoire : Traefik avec Let's Encrypt
  3. Rate limiting : Ajoutez Traefik rate limiting si nécessaire
  4. Backups : Sauvegardez régulièrement PostgreSQL et /videos

📊 Structure du projet

dw-stream/
├── docker-compose.yml
├── Dockerfile
├── nginx.conf
├── package.json
├── tsconfig.json
├── next.config.js
├── prisma/
│   └── schema.prisma
├── scripts/
│   └── convert-to-hls.sh
├── src/
│   ├── app/
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   ├── globals.css
│   │   ├── auth/
│   │   │   ├── signin/page.tsx
│   │   │   └── signup/page.tsx
│   │   ├── bundles/page.tsx
│   │   ├── dashboard/page.tsx
│   │   └── api/
│   │       ├── auth/
│   │       │   ├── [...nextauth]/route.ts
│   │       │   ├── register/route.ts
│   │       │   └── verify-email/route.ts
│   │       ├── stream/[videoId]/route.ts
│   │       └── webhooks/lemonsqueezy/route.ts
│   ├── components/
│   │   ├── Navigation.tsx
│   │   ├── Providers.tsx
│   │   ├── VideoPlayer.tsx
│   │   └── WatermarkOverlay.tsx
│   ├── lib/
│   │   ├── auth.ts
│   │   ├── email.ts
│   │   ├── lemonsqueezy.ts
│   │   ├── prisma.ts
│   │   ├── redis.ts
│   │   └── signed-urls.ts
│   ├── middleware.ts
│   └── types/
│       └── next-auth.d.ts
└── README.md

🐛 Dépannage

Les vidéos ne se chargent pas

  1. Vérifier que le volume est monté : docker-compose exec app ls -la /videos
  2. Vérifier les permissions : ls -la /home/user/data/vod/videos
  3. Vérifier les logs Nginx : docker-compose logs media-server

Erreur 403 sur /api/stream

  • Vérifier l'authentification (session NextAuth)
  • Vérifier l'achat en DB (Purchase table)
  • Vérifier la signature du lien (pas expiré)

Emails non reçus

  • Vérifier les credentials SMTP dans .env
  • Pour Gmail, utiliser un "App Password"
  • Vérifier les logs : docker-compose logs app | grep "Email"

Webhook LemonSqueezy ne fonctionne pas

  • Vérifier que LEMONSQUEEZY_WEBHOOK_SECRET est correct
  • Tester la signature HMAC
  • Vérifier les logs : docker-compose logs app | grep "Webhook"

📝 License

MIT

👤 Auteur

Créé pour un homelab personnel avec amour ❤️


Note : Ce projet est optimisé pour un homelab. Pour une production à grande échelle, envisagez :

  • CDN pour le streaming
  • Watermarking serveur avec GPU
  • Load balancing
  • Monitoring (Prometheus/Grafana)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published