Auch verfügbar in: 🇬🇧 English

Video-Pipeline

Inhalt

🇬🇧 English Version


Videos durchlaufen eine 5-stufige Pipeline vom Upload bis zur Wiedergabe. Jede Stufe wird von einem dedizierten BullMQ-Job-Worker ausgeführt, sodass einzelne Schritte unabhängig skaliert und bei Fehlern erneut versucht werden können.


Überblick: Pipeline-Stufen

[1] Eingang → [2] Analyse → [3] Thumbnails → [4] Transcodierung → [5] Abschluss
Stufe Name Zuständigkeit
1 Eingang Datei empfangen, in MinIO ablegen
2 Analyse Metadaten mit ffprobe extrahieren
3 Thumbnails Kandidaten-Frames generieren
4 Transcodierung HLS-Varianten mit FFmpeg erzeugen
5 Abschluss Status setzen, Clients benachrichtigen

Stufe 1: Eingang

Uploads verwenden das tus.io-Protokoll für resumierbare Dateiübertragungen. Große Dateien werden automatisch in Chunks aufgeteilt und können nach Verbindungsabbruch nahtlos fortgesetzt werden.

  • Fortschritt wird in Echtzeit per WebSocket an das Studio übermittelt
  • Rohdatei landet in MinIO unter play-raw/[videoId]/original.[ext]
  • Nach erfolgreichem Upload wird automatisch ein BullMQ-Job für Stufe 2 eingereiht

Stufe 2: Analyse

ffprobe extrahiert die technischen Metadaten der Rohdatei:

Metadatum Beschreibung
Dauer Länge des Videos in Sekunden
Auflösung Breite x Höhe in Pixeln
Codec Video-Codec (z. B. h264, av1)
Bitrate Durchschnittliche Bitrate in kbit/s
Framerate Bilder pro Sekunde
Audio Audioformat, Kanäle, Sample-Rate

Die extrahierten Werte werden in der Datenbank gespeichert und bestimmen, welche HLS-Qualitätsstufen in Stufe 4 erzeugt werden.


Stufe 3: Thumbnails

FFmpeg extrahiert 5 Thumbnail-Kandidaten aus gleichmäßig verteilten Zeitpunkten im Video. Der Nutzer kann anschließend im Studio einen davon als Titelbild auswählen oder ein eigenes Bild hochladen.

  • Thumbnails werden unter play-thumbs/[videoId]/thumb-[0-4].jpg gespeichert
  • Ausgabegröße: 1280 x 720 px (bei niedrigerer Quellauflösung entsprechend kleiner)
  • Die Auswahl des Nutzers wird in der Datenbank vermerkt

Stufe 4: Transcodierung

FFmpeg erzeugt einen HLS-Stream mit mehreren Qualitätsvarianten (Adaptive Bitrate Streaming).

Qualitätsvarianten

Auflösung Bitrate Bedingung
1080p 5 Mbit/s Nur wenn Quelle >= 1080p
720p 2,8 Mbit/s Immer
480p 1,2 Mbit/s Immer
360p 0,6 Mbit/s Immer

HLS-Konfiguration

  • Segmentformat: fmp4 (fragmentiertes MP4)
  • Segmentlänge: 4 Sekunden
  • Playlist: master.m3u8 + je eine Playlist pro Qualitätsstufe
  • Ausgabe: MinIO play-videos/[videoId]/

Transcodierungsjobs unterstützen Fortschritts-Reporting: Das Frontend zeigt einen Prozentzähler basierend auf den verarbeiteten Frames.


Stufe 5: Abschluss

Nach erfolgreicher Transcodierung:

  1. DB-Status des Videos wird auf ready gesetzt
  2. WebSocket-Event video.processingProgress mit status: "ready" wird gesendet
  3. Signierte URLs werden für private und logged_in-Videos generiert (Ablauf: 1 Stunde)
  4. Studio und Kanalseite werden automatisch aktualisiert

Externer Import (yt-dlp)

Nutzer können externe Video-URLs importieren (YouTube, Vimeo und andere yt-dlp-kompatible Plattformen).

Ablauf:

  1. Nutzer gibt URL im Studio ein
  2. Worker führt yt-dlp aus und lädt die Originaldatei herunter
  3. Metadaten (Titel, Beschreibung, Thumbnail) füllen das Studio-Formular automatisch vor
  4. Standard-Sichtbarkeit ist privat — Nutzer muss aktiv veröffentlichen
  5. Danach durchläuft das Video die normale 5-stufige Pipeline

Auto-Untertitel (Whisper) — v0.3-Feature

Die Integration von whisper.cpp ermöglicht automatische Untertitelgenerierung nach der Transcodierung.

  • Spracherkennung: Automatische Erkennung oder manuelle Sprachauswahl
  • Ausgabe: SRT-Datei, gespeichert als Untertitelspur am Video
  • Im Player umschaltbar, Standard ist deaktiviert
  • Ressourcenintensiv: Läuft in einem separaten, drosselten Worker-Prozess

Wiedergabe

Der HLS.js-Player übernimmt die Videowiedergabe im Browser.

  • Adaptive Bitraten-Umschaltung (ABR) basierend auf Bandbreite und Puffer
  • Manuelle Qualitätsauswahl im Player-Menü
  • Signierte URLs für private und logged_in-Videos: Server-seitig generiert, 1 Stunde gültig
  • Öffentliche Videos: Unsignierte, dauerhaft gültige URLs für CDN-Caching

Speicher-Layout (MinIO)

play-raw/
  [videoId]/
    original.[ext]          ← Rohe Upload-Datei (nach Processing löschbar)

play-videos/
  [videoId]/
    master.m3u8             ← HLS-Master-Playlist
    1080p/
      playlist.m3u8
      seg-000.m4s
      seg-001.m4s
      ...
    720p/
      playlist.m3u8
      seg-000.m4s
      ...
    480p/  ...
    360p/  ...

play-thumbs/
  [videoId]/
    thumb-0.jpg             ← Automatisch generierte Kandidaten
    thumb-1.jpg
    thumb-2.jpg
    thumb-3.jpg
    thumb-4.jpg

play-assets/
  logo.png                  ← Instanz-Logo

© Benjamin Weber · ITSWEBER — play.itsweber.net · GitHub