Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.
Dieser Leitfaden behandelt die grundlegenden Nutzungsmuster der WebCodecs API, einschließlich der Codierung und Dekodierung von Video und Audio sowie der Verwendung von VideoFrame und AudioData.
Das grundlegende Nutzungsmuster für VideoEncoder beginnt mit der Instanziierung, bei der Sie die output- und error-Callback-Funktionen definieren. Das output-Callback erhält ein EncodedVideoChunk und einen metadata-Parameter — ein EncodedVideoChunkMetadata-Wörterbuch, das eine optionale decoderConfig-Eigenschaft enthält. Diese Metadaten werden von Multiplexing-Bibliotheken benötigt, wenn sie in eine Videodatei gemuxt werden sollen.
Anschließend müssen Sie den Encoder mit dem Codec-Parameter und verschiedenen anderen Kodierungsparametern wie Breite, Höhe, Bitrate und Bildrate konfigurieren. Siehe den Leitfaden zur Codec-Auswahl für Hinweise zur Auswahl eines Codecs.
Dann würden Sie damit beginnen, VideoFrame-Objekte zu kodieren, wobei Sie nicht nur das zu kodierende VideoFrame angeben, sondern auch den keyFrame-Parameter, der angibt, ob das Frame als Keyframe kodiert werden soll oder nicht.
Das erste kodierte Frame sollte ein Keyframe sein — während VideoEncoder das erste Frame automatisch als Keyframe erzwingen wird, selbst wenn es nicht explizit gekennzeichnet ist, ist es eine gute Praxis, es explizit festzulegen. Typische Keyframe-Intervalle liegen bei ein Mal alle 30 oder 60 Frames. Die Verwendung von mehr Keyframes erhöht die Dateigröße des Videos, während die Verwendung von weniger Keyframes zu instabiler Videowiedergabe bei einigen Videoplayern führen kann.
Es ist wichtig, VideoFrame-Objekte sofort nach dem Senden zur Kodierung zu schließen, um Speicherlecks zu vermeiden. VideoFrame-Objekte sind groß genug, dass Anwendungen abstürzen können, wenn weniger als 100 aktive Frames im Speicher sind.
Beachten Sie, dass VideoEncoder auch eine Warteschlange für zu kodierende Frames hat, die encodeQueue genannt wird. Wenn Sie eine Animation mit 30 fps rendern, führen Sie encoder.encode(frame) bei jedem Rendern aus, aber der Encoder kann nur mit 10 fps kodieren, dann wird die Encoder-Warteschlange schließlich so lange wachsen, bis sie keinen Videospeicher mehr hat und der Prozess abstürzt.
Sie müssen daher verwalten, wie und wann Sie Frames an den Encoder senden, indem Sie innerhalb Ihrer Render-Schleife die VideoEncoder.encodeQueueSize überprüfen und sicherstellen, dass sie nicht ungebunden wächst.
Es ist möglich, das dequeue-Ereignis zu verwenden, um zu erkennen, wann die Encode-Warteschlange reduziert wird, um das Abfragen der encodeQueueSize zu vermeiden.
Sobald Sie alle Frames zur Kodierung gesendet haben, sollten Sie die flush()-Methode aufrufen.
Je nach Gerät/Browser gibt der Encoder möglicherweise die letzten EncodedVideoChunk-Objekte nicht zurück, bis flush() aufgerufen wird. Sobald Sie die VideoEncoder-Nutzung vollständig abgeschlossen haben, sollten Sie die close()-Methode aufrufen, um Systemressourcen freizugeben.
Ein VideoEncoder kann während der Kodierung aus verschiedenen Gründen einen Fehler auslösen, wie etwa wenn der Benutzer den Tab wechselt und der Browser die Ressourcen wiedererlangt. Wenn ein Fehler auftritt, wechselt der Encoder dauerhaft in den Zustand "closed". Es ist nicht möglich, einen geschlossenen Encoder neu zu konfigurieren — eine neue VideoEncoder-Instanz muss erstellt werden. Das erste von dem neuen Encoder kodierte Frame muss ein Keyframe sein.
Ebenso beginnen Sie bei der Dekodierung von Videos mit der Instanziierung des VideoDecoder mit den output- und error-Callback-Funktionen, wobei das output-Callback VideoFrame-Objekte erhält, die vom Decoder zurückgegeben werden.
Anschließend müssen Sie den Decoder konfigurieren. Wenn Sie eine Videodatei dekodieren, kann eine Demultiplex-Bibliothek die richtige Decoder-Konfiguration bereitstellen (siehe Muxing und Demuxing). Beim Streaming von Video zwischen einem WebCodecs-Sender und -Empfänger würde die Decoder-Konfiguration identisch mit den Metadaten sein, die von dem VideoEncoder zurückgegeben werden, der die kodierten Chunks erzeugt hat.
Wenn Sie eine Videodatei dekodieren, benötigen Sie eine Demultiplex-Bibliothek, um Video-Chunks zu extrahieren. Sie können dann die Chunks zur Dekodierung einreichen. Denken Sie daran, dass Sie nicht nur einen Chunk zur Dekodierung senden und darauf warten sollten, dass das Frame ausgegeben wird, bevor Sie den nächsten Chunk senden. Abhängig vom Browser/Gerät und dem Video selbst müssen Sie möglicherweise mehrere Chunks senden, bevor der Decoder beginnt, Frames zurückzugeben, und die Mindestanzahl von Chunks hängt vom jeweiligen Gerät ab.
Ähnlich wie VideoEncoder unterhält VideoDecoder eine Dekodier-Warteschlange, die verwaltet werden muss. Wenn Sie Tausende von Chunks auf einmal an den VideoDecoder senden, könnte der Decoder schließen oder fehlschlagen, sodass Ihre Anwendung sicherstellen muss, dass die VideoDecoder.decodeQueueSize nicht ungebunden wächst. Wie beim Encoder können Sie auch das dequeue-Ereignis verwenden, um bei der Verwaltung der Dekodier-Warteschlange zu helfen.
Sobald Sie alle Frames zur Dekodierung gesendet haben, können Sie flush ausführen.
Je nach Gerät/Browser gibt der Decoder die letzten VideoFrame-Objekte möglicherweise nicht zurück, bis flush() aufgerufen wird. Sobald Sie die VideoDecoder-Nutzung vollständig abgeschlossen haben, sollten Sie die close()-Methode aufrufen, um Systemressourcen freizugeben.
Ein VideoDecoder kann aus verschiedenen Gründen einen Fehler beim Dekodieren auslösen, wie z.B. beschädigte oder fehlende Daten in einem Quell-EncodedVideoChunk. Wenn ein Decoder fehlschlägt, wechselt er dauerhaft in den Zustand "closed", und es muss eine neue VideoDecoder-Instanz erstellt werden. Der erste von dem neuen Decoder dekodierte Chunk muss ein Keyframe sein, daher muss von der aktuellen Position bis zum nächsten Keyframe gesucht werden, bevor fortgefahren wird.
Ein VideoFrame repräsentiert ein einzelnes unkomprimiertes Video-Frame, einschließlich seiner Pixeldaten und Metadaten wie seinem Zeitstempel. Es wird sowohl vom VideoDecoder beim Dekodieren codierter Videos zurückgegeben als auch aus einer Vielzahl von Bildquellen erzeugt.
Ein VideoFrame kann aus jeder Bildquelle konstruiert werden. Beachten Sie, dass Zeitstempel in Mikrosekunden angegeben werden.
Das Erstellen eines VideoFrame aus einem Canvas ist typischerweise der Weg, wie Sie Video in einer Videobearbeitungsanwendung kodieren würden, wobei Quellvideos und Bilder im Rahmen eines Canvas-Kontextes verwendet werden, um Effekte und Transformationen anzuwenden, und das Canvas kann sowohl vom Benutzer vorab betrachtet als auch als Bildquelle für ein zu kodierendes VideoFrame verwendet werden.
Sie können auch direkt ein VideoFrame aus Binärdaten erstellen, wie z. B. einem ArrayBuffer; Sie müssen jedoch das format und die Metadaten angeben und sicherstellen, dass die zum Erstellen des Frames verwendeten Daten dem angegebenen format entsprechen.
VideoFrame-Objekte sind an Daten im Grafikspeicher gebunden. Beim Erstellen eines VideoFrame aus einem Canvas, Bitmap, Video oder Image werden Daten vom Grafikspeicher zum Grafikspeicher kopiert, was relativ effizienter ist.
Ein aus Binärdaten (z.B. ArrayBuffer oder Uint8ClampedArray) konstruiertes VideoFrame wird eine CPU→Grafikspeicher-Kopieroperation erfordern, was, wenn es wiederholt durchgeführt wird, zu Leistungseinbußen führen kann.
Schließlich können VideoFrame-Objekte auch durch das Dekodieren von EncodedVideoChunk-Objekten über einen VideoDecoder erzeugt werden, wie im Abschnitt Videodekodierung oben gezeigt.
Dekodiertes Video kann auch im Browser abgespielt werden, indem VideoFrame-Objekte über eine der Canvas-Rendering-Methoden in ein Canvas gerendert werden. Verschiedene Rendering-Methoden haben unterschiedliche Leistungsmerkmale, die relevant sein könnten, wenn rechenintensive Videoverarbeitungsoperationen ausgeführt werden.
Frames können mit der drawImage-Methode auf ein CanvasRenderingContext2D gezeichnet werden:
Während der 2D-Canvas-Kontext eine einfache, aber flexible API hat, verwenden Browser unter der Haube unterschiedliche Implementierungen, was zu inkonsistenter und im Allgemeinen schlechterer Leistung über verschiedene Browser hinweg führt.
Frames können auch über den ImageBitmapRenderingContext auf ein Canvas gerendert werden, indem ein ImageBitmap aus dem Frame erstellt und es über die Methode transferFromImageBitmap auf das Canvas gerendert wird.
Diese Methode beinhaltet das Erstellen einer einzigen Kopie des Frames im Grafikspeicher, was zu konsistenterer und im Allgemeinen besserer Leistung über Browser hinweg als die Canvas2D-API führt und gleichzeitig relativ einfach ist.
Der effizienteste Weg, ein VideoFrame auf ein Canvas zu rendern, ist über die Methode importExternalTexture in WebGPU.
importExternalTexture ist effizient, da es einen null kopierenden Vorgang verursacht und genau dasselbe VideoFrame-Objekt im Speicher innerhalb einer WebGPU-Pipeline verwendet. Es ist die leistungsstärkste Methode zum Rendern eines VideoFrame, aber auch die komplexeste beim Einrichten.
Da VideoFrame-Objekte signifikanten GPU-Speicher konsumieren können und die Videobearbeitung das Manipulieren vieler Frames pro Sekunde beinhaltet, sollte besonderer Wert darauf gelegt werden, Speicher zu verwalten und Speicherlecks zu vermeiden, um Abstürze der Anwendung zu vermeiden.
In erster Linie müssen Frames explizit freigegeben werden, wenn sie nicht mehr benötigt werden.
Beim Kodieren können Sie das Frame schließen, sobald Sie es zur Kodierung senden.
Sie sollten die Frames auch unmittelbar nach dem Rendern schließen.
Beim Übertragen eines VideoFrame zwischen Threads (z.B. einem Worker) sollte es als Transferable Object übertragen werden.
WebCodecs unterstützt die Kodierung und Dekodierung von Audio über AudioEncoder und AudioDecoder, unter Verwendung der Codecs Opus und AAC. Bevor Sie mit Audio arbeiten, gibt es einige wichtige Hinweise:
Es gibt keine direkte Verbindung zwischen WebCodecs und der Web Audio API. AudioData-Objekte können nicht direkt an die Web Audio API übergeben werden, die AudioBuffer zur Darstellung roher Audiodaten verwendet.
Der empfohlene Ansatz zur Wiedergabe ist, EncodedAudioChunk-Objekte mit einer Muxing-Bibliothek in einen Speicherpuffer zu muxen und dann diesen Puffer über AudioContext.decodeAudioData() zu dekodieren:
Alternativ können Sie rohe Samples aus AudioData über copyTo() extrahieren und manuell einen AudioBuffer konstruieren, aber dies erfordert eine CPU-seitige Datenkopie für jeden Chunk und ist langsamer.
Die Audiokodierung ist einfacher als die Videokodierung — es gibt keine Keyframes, keine Hardware-Beschleunigungsprobleme, und jedes AudioData erzeugt genau einen EncodedAudioChunk. Der Encoder kann als einfacher asynchroner Pipeline behandelt werden.
Siehe den Leitfaden zur Codec-Auswahl für Hinweise zur Auswahl zwischen Opus und AAC.
Die Audiodekodierung folgt demselben Muster wie die Kodierung. Die Decoder-Konfiguration wird typischerweise von der Demuxing-Bibliothek bereitgestellt und nicht vom Entwickler ausgewählt.
Ein AudioData-Objekt repräsentiert ein Segment von Rohaudio, typischerweise über einen Zeitraum von 0,2–0,5 Sekunden. Rohe Samples werden als Float32Array-Daten mithilfe der Methode AudioData.copyTo() extrahiert. Das Extraktionsmuster hängt von der format-Eigenschaft des AudioData-Objekts ab.
Das häufigste Format ist f32-planar, bei dem jeder Kanal in einer separaten Ebene gespeichert wird. Verwenden Sie planeIndex, um jeden Kanal unabhängig zu kopieren:
Das weniger häufige f32-Format speichert alle Kanäle ineinander gestaffelt in einem einzigen Array ([L, R, L, R, ...]). In diesem Fall kopieren Sie den gesamten ineinander verschachtelten Puffer und de-multiplexieren ihn manuell:
Um beide Formate zu verarbeiten:
Um ein AudioData aus rohen Samples zu konstruieren, müssen die Daten für alle Kanäle in einem einzelnen Float32Array verkettet werden, wobei die Samples jedes Kanals sequentiell angeordnet werden (entspricht dem f32-planar-Layout), und die numberOfFrames muss auf die Anzahl der Samples pro Kanal eingestellt werden:
Beachten Sie, dass bestimmte AAC-Codec-Zeichenfolgen (mp4a.40.5, mp4a.40.05 und mp4a.40.29) Konfigurationen entsprechen, die eine Technik namens Spectral Band Replication (SBR) verwenden, die dazu führt, dass der Decoder Audio mit der doppelten Samplerate ausgibt, die in der Decoder-Konfiguration angegeben ist. Lesen Sie immer audioData.sampleRate direkt ab, anstatt anzunehmen, dass es mit dem konfigurierten Wert übereinstimmt.
Wie VideoFrame-Objekte müssen AudioData-Objekte explizit geschlossen werden, um Speicher freizugeben:
Während AudioData viel weniger Speicher als ein VideoFrame benötigt, hat rohes Audio immer noch einen erheblichen Speicherbedarf — eine Stunde Stereo-Audio bei 48 kHz liegt bei ungefähr 1,4 GB. Für große Dateien sollte Audio in Chargen dekodiert und verarbeitet werden, anstatt alles auf einmal.
Der Bauplan für ein besseres Internet.
Besuche die gemeinnützige Muttergesellschaft der Mozilla Corporation, die Mozilla Foundation.
Teile dieses Inhalts sind ©1998–2026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfügbar unter einer Creative-Commons-Lizenz.