Was ist Just-in-Time-Encoding?
Just-in-Time-Encoding erzeugt eine angefragte Medienvariante bei Bedarf, statt jede Auflösungs-, Codec- oder Qualitätsvariante vorab zu berechnen. Das Ergebnis kann anschließend für spätere Anfragen zwischengespeichert werden.
So funktioniert Just-in-Time-Encoding
Ein Just-in-Time-System schaltet den Encoder hinter die Auslieferungs-URL. Eine Anfrage benennt eine Quelle und eine Verarbeitungsvorgabe. Ein Cache wird auf ein gespeichertes Ergebnis geprüft, und das Encoding läuft nur bei einem Cache-Miss. Anschließend wird die Ausgabe zurückgegeben und für spätere Anfragen gespeichert. Dieser Cache ist ein CDN vor dem Encoder, ein vom Dienst selbst verwalteter Speicher oder beides. Ohne beides wiederholt ein Encoder die Arbeit bei jeder Anfrage. Ein gespeichertes Ergebnis wird nur so lange wiederverwendet, bis es abläuft oder aus dem Cache entfernt wird. Bei Bildern ist die Arbeitseinheit eine URL. Bei Videos ist die praktische Einheit ein Segment eines adaptiven Streams statt der gesamten Datei: Ein HLS-Player fragt zunächst Playlists an, die der Dienst unmittelbar erzeugt, und danach kurze Segmente, die jeweils bei der ersten Anfrage codiert werden. Nur angefragte Varianten und Zeitbereiche werden codiert. Player laden Segmente über die aktuelle Wiedergabeposition hinaus vor, sodass dazu auch Segmente gehören können, die letztlich niemand ansieht. Mux bezeichnet dies als Just-in-Time-Transkodierung und beschreibt, dass Frames bereits aus dem Transcoder gestreamt werden, bevor die Verarbeitung der restlichen Datei abgeschlossen ist.
Wichtige Fakten
- Ist Just-in-Time-Packaging dasselbe? Nein. Just-in-Time-Packaging verpackt bereits vorhandene Varianten neu in das Streaming-Format, das ein Player anfragt. AWS Elemental MediaPackage beschreibt dies als Erstellen eines Manifests in einem Format, das mit dem anfragenden Gerät kompatibel ist. Die Quellinhalte stammen bei Live-Video von einem vorgeschalteten Encoder und bei Video-on-Demand aus HLS- oder MP4-Dateien in Amazon S3. Das nginx-vod-module beschreibt das unmittelbare Neuverpacken von MP4-Dateien in DASH, HDS, HLS und MSS. Keiner der beiden Dienste beschreibt das Encoding in eine neue Auflösung oder Bitrate. Die Encoding-Leiter muss daher weiterhin im Voraus erzeugt werden. Just-in-Time-Encoding verschiebt auch diesen Schritt auf später.
- Was kostet die erste Anfrage, und was passiert, wenn viele gleichzeitig eintreffen? Die erste Anfrage für eine Ausgabe wartet auf das Abrufen der Quelle und das Encoding. Spätere Anfragen sind Cache-Treffer, solange das Ergebnis zwischengespeichert bleibt. Die Dokumentation von imgproxy weist darauf hin, dass CDNs selten abgerufene Inhalte üblicherweise löschen. Eine selten angefragte Ausgabe kann daher mehrfach codiert werden. Gleichzeitige Erstanfragen für dieselbe Ausgabe können jeweils ein Encoding starten, sofern der vorgeschaltete Cache sie nicht zu einer Anfrage zusammenfasst oder der Encoder selbst die laufende Verarbeitung gemeinsam nutzt, wie es der Bildserver imagor tut. Für das Zusammenfassen gelten Bedingungen: Cloudflare fasst Anfragen pro Rechenzentrum zusammen, bei NGINX ist
proxy_cache_lockstandardmäßig ausgeschaltet, und bei Fastly führt eine nicht zwischenspeicherbare Antwort dazu, dass wartende Anfragen nacheinander zum Origin-Server gelangen. - Was passiert mit zwischengespeicherten Ausgaben, wenn sich die Encoding-Einstellungen ändern? Zunächst nichts, sofern die Änderung nicht den Cache-Schlüssel verändert. Ein gespeichertes Ergebnis wird anhand seines Schlüssels gefunden, der üblicherweise aus Quelle, Verarbeitungsoptionen und Ausgabeformat besteht. Eine Änderung an einer serverseitigen Voreinstellung, einem Qualitätsstandardwert oder einem Wasserzeichen, die sich nicht in der Anfrage widerspiegelt, lässt daher die alte Ausgabe bestehen, bis sie abläuft oder für ungültig erklärt wird. imgproxy dokumentiert für genau diesen Fall die URL-Option
cachebusterund weist darauf hin, dass sein interner Cache keine manuelle Invalidierung bietet. Es gibt nur die Ablaufzeit, die im dahinterliegenden Speicher festgelegt wird. Wird bei einer Änderung der Verarbeitungsvorgabe eine Version in die URL aufgenommen, erhält die neue Ausgabe sofort einen neuen Schlüssel. - Was sollte passieren, wenn ein Encoding fehlschlägt? Die Fehlerantwort benötigt eine eigene Cache-Richtlinie. Hat sie dieselbe Gültigkeitsdauer wie ein erfolgreiches Ergebnis, bleibt ein vorübergehender Fehler bestehen: Eine Person, die imgproxy nutzt, meldete eine Antwort mit dem Statuscode 504, die mit einem Header namens
Cache-Controlund einer Gültigkeitsdauer von einem Jahr gesendet und von einem nachgeschalteten NGINX-Cache gespeichert wurde. Werden Fehler nie zwischengespeichert, wiederholt jede Anfrage für eine defekte Quelle den ressourcenintensiven Fehlschlag. Ohne explizite Caching-Header erlaubt HTTP einem Cache, eine Antwort mit dem Statuscode 404 zu speichern und wiederzuverwenden, da sie heuristisch zwischenspeicherbar ist. Für Antworten mit den Statuscodes 500, 503 oder 504 gilt das nicht. Direktiven fürCache-Controländern dies in beide Richtungen: Mitmax-ageoderpubliclässt sich ein solcher Fehler speichern, währendno-storedas Speichern jeglicher Antworten verbietet.
Wann Just-in-Time-Encoding wichtig ist
Just-in-Time-Encoding lohnt sich, wenn Sie nicht vorhersagen können, welche Varianten oder Teile einer Datei angefordert werden: bei großen Archiven und Nutzer-Uploads, deren Inhalte größtenteils selten angesehen werden, oder bei Bildgrößen, die von noch nicht erstellten Layouts abhängen. Encoding-Vorgänge, die niemand anfordert, werden nie ausgeführt. Bei selten angeforderten Inhalten entscheidet die Verweildauer eines Ergebnisses im Cache darüber, wie oft bei wiederholten Anfragen erneut Kosten für das Encoding anfallen. Codieren Sie stattdessen vorab, wenn jede Ausgabe vor der Veröffentlichung bereitstehen muss, jemand sie zuerst prüfen muss oder die erste Anfrage genauso schnell sein muss wie alle späteren. Eine feste Abstufung von Varianten allein ist kein Grund, vorab zu codieren: Ein Just-in-Time-Encoder kann vordefinierte Varianten ausliefern und dennoch Segmente überspringen, die niemand anfordert.
So hilft Transloadit bei Just-in-Time-Encoding
Transloadit bietet Just-in-Time-Encoding über sein Smart CDN an. Für Videos erzeugt der Robot /video/ondemand HLS-Playlists und Segmente bei Bedarf: Ein Player fragt die Multivarianten-Playlist über eine URL für tlcdn.com an, jedes Segment wird bei seiner ersten Anfrage codiert, und das Smart CDN speichert Playlists und Segmente für spätere Zuschauer zwischen. Bei Bildern und anderen Dateien führt eine URL für das Smart CDN bei einem Cache-Miss ein Template aus und liefert das zwischengespeicherte Ergebnis bis zu dessen Ablauf aus.
Die Dokumentation zu /video/ondemand beschreibt die HLS-Ausgabe. Der Robot /file/serve legt fest, wie lange Ergebnisse zwischengespeichert werden: Standardmäßig weist er CDNs an, ein Ergebnis für 24 Stunden aufzubewahren, und Browser für 72 Stunden. Mit cache_duration werden beide Zeiträume geändert. Werden Playlist-URLs mit sign_urls_for signiert, verringern kürzere Gültigkeitsdauern die Wiederverwendung des Caches und können dazu führen, dass Segmente häufiger neu erzeugt werden. Die verlinkten Seiten geben nicht an, was mit bereits zwischengespeicherten Ergebnissen passiert, wenn ein Template bearbeitet wird, oder was ein Player erhält, wenn das Encoding eines Segments fehlschlägt. Testen Sie daher beides, bevor Sie sich darauf verlassen.
Quellen
- Engineering-Blog von Mux: Just-in-Time-Transkodierung und welches Encoding sie vermeidet
- AWS Elemental MediaPackage: Konzepte und Terminologie (Just-in-Time-Packaging)
- README von kaltura/nginx-vod-module: unmittelbares Neuverpacken und Caching-Empfehlungen
- RFC 8216: HTTP Live Streaming, Abschnitt 6.3.3 (Clients laden Segmente im Voraus)
- RFC 9110: HTTP-Semantik, Abschnitt 15.1 (heuristisch zwischenspeicherbare Statuscodes)
- RFC 9111: HTTP-Caching (Speichern und Wiederverwenden von Antworten, zusammengefasste Anfragen, Cache-Control-Direktiven)
- Cloudflare: standardmäßiges Cache-Verhalten einschließlich des Zusammenfassens von Anfragen
- NGINX: ngx_http_proxy_module, proxy_cache_lock und proxy_cache_valid
- Fastly: Zusammenfassen von Anfragen
- Quellcode von cshum/imagor: Gleichzeitige Anfragen für dasselbe Ergebnis nutzen eine gemeinsame laufende Verarbeitung
- imgproxy: interner Cache-Schlüssel, Ablauf und Einschränkungen
- imgproxy: Verarbeitungsoptionen einschließlich cachebuster
- imgproxy-Issue 686: Stellungnahme aus dem Maintainer-Team zum Überlassen des Cachings an CDNs und Caching-Server
- imgproxy-Issue 1677: Cache-Control bei einer fehlgeschlagenen Anfrage gesendet