WebCodecs API
Hinweis: Dieses Feature ist verfügbar in Dedicated Web Workers.
Die WebCodecs API bietet Webentwicklern Low-Level-Zugriff auf die einzelnen Frames eines Videostreams und Audio-Chunks. Sie ist nützlich für Webanwendungen, die volle Kontrolle darüber benötigen, wie Medien verarbeitet werden. Zum Beispiel Video- oder Audio-Editoren und Videokonferenzen.
Konzepte und Anwendung
Viele Web-APIs verwenden intern Mediencodecs. Zum Beispiel die Web Audio API und die WebRTC API. Diese APIs erlauben es Entwicklern jedoch nicht, mit einzelnen Frames eines Videostreams und ungemischten, kodierten Audio- oder Videodaten zu arbeiten.
Webentwickler haben typischerweise WebAssembly verwendet, um diese Einschränkung zu umgehen und mit Mediencodecs im Browser zu arbeiten. Dies erfordert jedoch zusätzlichen Bandbreitenverbrauch, um bereits im Browser vorhandene Codecs herunterzuladen, was die Leistung und Energieeffizienz reduziert und zusätzlichen Entwicklungsaufwand verursacht.
Die WebCodecs API bietet Zugriff auf Codecs, die bereits im Browser vorhanden sind. Sie ermöglicht den Zugriff auf rohe Video-Frames, Audio-Daten-Chunks, Bild-Dekoder, Audio- und Video-Encoder und -Dekoder.
Verarbeitungsmodell
Die WebCodecs API verwendet ein asynchrones Verarbeitungsmodell. Jede Instanz eines Encoders oder Decoders pflegt eine interne, unabhängige Verarbeitungsschlange. Bei der Warteschlange einer erheblichen Menge an Arbeit ist es wichtig, dieses Modell im Hinterkopf zu behalten.
Methoden mit den Namen configure()
, encode()
, decode()
und flush()
arbeiten asynchron, indem sie Steuerungsnachrichten
ans Ende der Warteschlange anhängen, während Methoden mit den Namen reset()
und close()
synchron alle wartenden Aufgaben abbrechen und die
Verarbeitungsschlange leeren. Nach reset()
kann mehr Arbeit nach einem Aufruf von configure()
in die Warteschlange gestellt werden, aber close()
ist eine endgültige Operation.
Methoden mit dem Namen flush()
können verwendet werden, um auf die Fertigstellung aller Arbeiten zu warten, die zum Zeitpunkt des Aufrufs von flush()
anstanden. Es sollte jedoch im Allgemeinen nur aufgerufen werden, wenn alle gewünschten Arbeiten in der Warteschlange sind. Es ist nicht dazu gedacht, Fortschritte in regelmäßigen Abständen zu erzwingen. Ein übermäßiger Aufruf beeinträchtigt die Encoder-Qualität und führt dazu, dass Decoder das nächste Eingabesignal als Keyframe erwarten.
Demuxing
Derzeit gibt es keine API für das Demuxing von Mediencontainern. Entwickler, die mit containerisierten Medien arbeiten, müssen entweder ihre eigenen Implementierungen entwickeln oder Drittanbieter-Bibliotheken verwenden. Zum Beispiel können MP4Box.js oder jswebm verwendet werden, um Audio- und Videodaten in EncodedAudioChunk
und EncodedVideoChunk
Objekte zu demuxen.
Schnittstellen
AudioDecoder
-
Dekodiert
EncodedAudioChunk
Objekte. VideoDecoder
-
Dekodiert
EncodedVideoChunk
Objekte. AudioEncoder
-
Kodiert
AudioData
Objekte. VideoEncoder
-
Kodiert
VideoFrame
Objekte. EncodedAudioChunk
-
Repräsentiert codec-spezifische kodierte Audio-Bytes.
EncodedVideoChunk
-
Repräsentiert codec-spezifische kodierte Video-Bytes.
AudioData
-
Repräsentiert unkodierte Audio-Daten.
VideoFrame
-
Repräsentiert einen Frame unkodierter Video-Daten.
VideoColorSpace
-
Repräsentiert den Farbraum eines Video-Frames.
ImageDecoder
-
Entpackt und dekodiert Bilddaten und ermöglicht den Zugriff auf die Sequenz von Frames in einem animierten Bild.
ImageTrackList
-
Repräsentiert die Liste der im Bild verfügbaren Tracks.
ImageTrack
-
Repräsentiert einen individuellen Bild-Track.
Beispiele
Im folgenden Beispiel werden Frames von einem MediaStreamTrackProcessor
zurückgegeben und dann kodiert.
Sehen Sie sich das vollständige Beispiel an und lesen Sie mehr darüber im Artikel Videoverarbeitung mit WebCodecs.
let frame_counter = 0;
const track = stream.getVideoTracks()[0];
const media_processor = new MediaStreamTrackProcessor(track);
const reader = media_processor.readable.getReader();
while (true) {
const result = await reader.read();
if (result.done) break;
let frame = result.value;
if (encoder.encodeQueueSize > 2) {
// Too many frames in flight, encoder is overwhelmed
// let's drop this frame.
frame.close();
} else {
frame_counter++;
const insert_keyframe = frame_counter % 150 === 0;
encoder.encode(frame, { keyFrame: insert_keyframe });
frame.close();
}
}