Video-Pipeline
Inhalt
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].jpggespeichert - 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:
- DB-Status des Videos wird auf
readygesetzt - WebSocket-Event
video.processingProgressmitstatus: "ready"wird gesendet - Signierte URLs werden für private und
logged_in-Videos generiert (Ablauf: 1 Stunde) - 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:
- Nutzer gibt URL im Studio ein
- Worker führt
yt-dlpaus und lädt die Originaldatei herunter - Metadaten (Titel, Beschreibung, Thumbnail) füllen das Studio-Formular automatisch vor
- Standard-Sichtbarkeit ist
privat— Nutzer muss aktiv veröffentlichen - 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
privateundlogged_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