Zum Hauptinhalt springen




Erfahren Sie, wie Sie das verwenden requestVideoFrameCallback () um effizienter mit Videos im Browser zu arbeiten.


Aktualisiert

In dem Block befindet sich eine neue Web-API, die im definiert ist
HTMLVideoElement.requestVideoFrameCallback ()

Spezifikation. das requestVideoFrameCallback () Mit dieser Methode können Webautoren einen Rückruf aufzeichnen, der die Rendering-Schritte durchläuft, wenn ein neuer Videorahmen an den Komponisten gesendet wird. Dies soll Entwicklern ermöglichen, effiziente Vorgänge pro Bild von Video zu Video auszuführen, z. B. Videoverarbeitung und Malen auf einer Leinwand, Videoanalyse oder Synchronisierung mit externen Audioquellen.

Unterschied zu requestAnimationFrame ()

Vorgänge wie das Zeichnen eines Videorahmens auf einer Leinwand mit
drawImage ()

Über diese API erstellte Daten werden nach bestem Wissen und Gewissen mit der Bildrate des auf dem Bildschirm abgespielten Videos synchronisiert. Anders als
window.requestAnimationFrame (), die typischerweise etwa 60 Mal pro Sekunde feuert,
requestVideoFrameCallback () ist an die tatsächliche Videobildrate gebunden, mit einem wichtigen
Ausnahme:

Die effektive Rate, mit der Rückrufe ausgeführt werden, ist die niedrigere Rate der Videorate und der Browserrate. Dies bedeutet, dass ein 25-fps-Video, das in einem Browser abgespielt wird, der mit 60 Hz malt, Rückrufe mit 25 Hz auslöst. Ein 120-fps-Video in demselben 60-Hz-Browser würde 60-Hz-Rückrufe auslösen.

Was ist in einem Namen?

Aufgrund seiner Ähnlichkeit mit window.requestAnimationFrame ()war die Methode zunächst vorgeschlagen als video.requestAnimationFrame (), aber ich bin zufrieden mit dem neuen Namen,
requestVideoFrameCallback (), die nach a vereinbart wurde lange Diskussion. Hurra, Fahrräder für den Sieg!

Browserunterstützung und Funktionserkennung

Die Methode ist
in Chrom implementiert
schon und
Mozilla-Leute mögen. Für das, was es wert ist, habe ich auch eine eingereicht
WebKit-Fehler Danach fragen. Die API-Funktionserkennung funktioniert folgendermaßen:

if ( 'requestVideoFrameCallback' in HTMLVideoElement . Prototyp ) {
}}

Verwenden der requestVideoFrameCallback () -Methode

Wenn Sie jemals die verwendet haben requestAnimationFrame () Methode, werden Sie sich mit der sofort zu Hause fühlen requestVideoFrameCallback () Methode. Sie registrieren einen ersten Rückruf einmal und registrieren ihn dann jedes Mal neu, wenn der Rückruf ausgelöst wird.

const doSomethingWithTheFrame = (jetzt Metadaten) => {
Konsole . log (jetzt, Metadaten);
Video . requestVideoFrameCallback ( doSomethingWithTheFrame ) ;
} ;
Video . requestVideoFrameCallback ( doSomethingWithTheFrame ) ;

Im Rückruf jetzt ist ein DOMHighResTimeStamp

y Metadaten ist ein VideoFrameMetadata

Wörterbuch mit folgenden Eigenschaften:

  • Präsentationszeitvom Typ DOMHighResTimeStamp: Die Zeit, zu der der Benutzeragent den Frame zur Komposition gesendet hat.
  • expectedDisplayTimevom Typ DOMHighResTimeStamp: Die Zeit, zu der der Benutzeragent erwartet, dass der Frame sichtbar ist.
  • Breitevom Typ lange nicht signiert: Die Breite des Videorahmens in Medienpixeln.
  • Höhevom Typ lange nicht signiert: Die Höhe des Videorahmens in Multimedia-Pixeln.
  • mediaTimevom Typ doppelt: Der Zeitstempel für die Medienanzeige (PTS) in Sekunden des angezeigten Frames (z. B. Ihr Zeitstempel in der video.currentTime Zeitleiste).
  • präsentierte Framesvom Typ lange nicht signiert: Anzahl der Frames, die zur Komposition gesendet wurden. Ermöglicht Kunden zu bestimmen, ob Frames zwischen Instanzen von verloren gegangen sind VideoFrameRequestCallback.
  • VerarbeitungDauervom Typ doppelt: Die verstrichene Dauer in Sekunden seit dem Senden des Pakets, das mit demselben Präsentationszeitstempel (PTS) wie dieser Frame codiert wurde (z. B. derselbe wie der mediaTime) an den Decoder, bis der decodierte Rahmen zur Präsentation bereit ist.

Bei WebRTC-Anwendungen werden möglicherweise zusätzliche Eigenschaften angezeigt:

  • CaptureTimevom Typ DOMHighResTimeStamp: Bei Videobildern, die von einer lokalen oder Remote-Quelle stammen, ist dies der Moment, in dem die Kamera das Bild aufgenommen hat. Für eine Remote-Quelle wird die Erfassungszeit mithilfe der Synchronisierung und Berichterstellung der RTCP-Senderuhr geschätzt, um RTP-Zeitstempel in Erfassungszeit umzuwandeln.
  • receiveTimevom Typ DOMHighResTimeStamp: Bei Video-Frames, die von einer Remote-Quelle stammen, ist dies die Zeit, zu der die Plattform den codierten Frame empfangen hat, dh die Zeit, zu der das letzte zu diesem Frame gehörende Paket über das Netzwerk empfangen wurde.
  • rtpTimestampvom Typ lange nicht signiert: Der diesem Videorahmen zugeordnete RTP-Zeitstempel.

Beachten Sie, dass Breite y Höhe kann abweichen von videoWidth y videoHöhe In bestimmten Fällen (z. B. kann ein anamorphotisches Video rechteckige Pixel aufweisen).

Von besonderem Interesse in dieser Liste ist mediaTime. In der Chromium-Implementierung verwenden wir die Audiouhr als unterstützte Zeitquelle video.currentTimeInzwischen er mediaTime wird direkt von der bevölkert Präsentationszeitstempel des Rahmens. das mediaTime Dies ist zu verwenden, wenn Sie die Frames auf reproduzierbare Weise genau identifizieren möchten, auch um genau die Frames zu identifizieren, die verloren gegangen sind.

Leider garantiert das Videoelement keine Bildgenauigkeit suchen. Dies war eine kontinuierliche Diskussionsthema.
WebCodecs es wird schließlich rahmengenaue Anwendungen ermöglichen.

Wenn die Dinge wie eine Kiste entfernt scheinen ...

Vertikale Synchronisierung (oder einfach vsync) ist eine Grafiktechnologie, die die Bildrate eines Videos und die Bildwiederholfrequenz eines Monitors synchronisiert. Wie requestVideoFrameCallback () Es läuft im Haupt-Thread, aber unter der Haube findet Video-Compositing im Composer-Thread statt. Alles von dieser API ist eine Bestleistung und wir bieten keine strengen Garantien. Was möglicherweise passiert, ist, dass die API im Vergleich zum Rendern eines Videobilders möglicherweise hinter einem vsync zurückbleibt. Ein vsync ist erforderlich, damit Änderungen, die über die API an der Webseite vorgenommen werden, auf dem Bildschirm angezeigt werden (wie bei window.requestAnimationFrame ()). Also, wenn Sie weiter aktualisieren mediaTime oder die Bildnummer auf Ihrer Webseite und vergleichen Sie sie mit den nummerierten Videobildern. Schließlich sieht das Video so aus, als ob es ein Bild vor Ihnen liegt.

Was tatsächlich passiert, ist, dass der Frame in vsync x bereit ist, der Rückruf ausgelöst wird und der Frame in vsync x + 1 verarbeitet wird und die am Rückruf vorgenommenen Änderungen in vsync x + 2 verarbeitet werden. Sie können überprüfen, ob der Rückruf erfolgt ist eine späte vsync (und der Frame wird bereits auf dem Bildschirm gerendert), indem überprüft wird, ob die metadata.expectedDisplayTime ist circa jetzt oder ein vsync in der Zukunft. Wenn es innerhalb von fünf bis zehn Mikrosekunden von ist jetztist der Rahmen bereits gerendert; Wenn er expectedDisplayTime Es ist ungefähr 16 Millisekunden in der Zukunft (vorausgesetzt, Ihr Browser / Bildschirm wird auf 60 Hz aktualisiert), dann ist es mit dem Frame synchronisiert.

Manifestation

Ich habe eine kleine erstellt
Glitch-Demo
Hier wird gezeigt, wie Frames mit genau der Framerate des Videos auf einer Leinwand gezeichnet werden und wo Frame-Metadaten zu Debugging-Zwecken aufgezeichnet werden. Die Kernlogik besteht nur aus ein paar Zeilen JavaScript.

let paintCount = 0 ;
let startTime = 0.0 ;

const updateCanvas = (jetzt Metadaten) => {
if ( startTime === 0.0 ) {
startTime = now ;
}}

ctx . drawImage ( Video , 0 , 0 , Leinwand . Breite , Leinwand . Höhe ) ;

const elapsed = ( now - startTime ) / 1000.0 ;
const fps = ( ++ paintCount / elapsed) . toFixed ( 3 ) ;
fpsInfo . innerText = ` video fps: $ { fps } ` ;
metadataInfo . innerText = JSON . stringify ( Metadaten , null , 2 ) ;

Video . requestVideoFrameCallback ( updateCanvas ) ;
} ;

Video . requestVideoFrameCallback ( updateCanvas ) ;

Schlussfolgerungen

Ich habe lange Zeit eine Verarbeitung auf Frame-Ebene durchgeführt und keinen Zugriff auf die eigentlichen Frames gehabt, nur basierend auf video.currentTime. Ich habe die Segmentierung von Videoaufnahmen in JavaScript grob implementiert. Sie können den Anhang noch lesen
Forschungsarbeit. Hatte die requestVideoFrameCallback () existierte damals, mein Leben wäre viel einfacher gewesen ...

Vielen Dank

das requestVideoFrameCallback Die API wurde von spezifiziert und implementiert
Thomas Guilbert. Dieser Artikel wurde von überprüft Joe Medley
y Kayce Basques.
Heldenbild zum
Denise Jans auf Unsplash.

R Marketing Digital