Apprenez à utiliser le requestVideoFrameCallback ()
para trabajar de manera más eficiente con videos en el le navigateur.
Mise à jour
Hay una nueva API la toile en el bloque, definida en el
HTMLVideoElement.requestVideoFrameCallback ()
spécification. Les requestVideoFrameCallback ()
La méthode permet aux auteurs Web d'enregistrer un rappel qui exécute les étapes de rendu lorsqu'une nouvelle image vidéo est envoyée au compositeur. Ceci est destiné à permettre aux développeurs d'effectuer des opérations efficaces par image de vidéo à vidéo, telles que le traitement vidéo et la peinture sur une toile, l'analyse vidéo ou la synchronisation avec des sources audio externes.
Différence avec requestAnimationFrame ()
Opérations telles que dessiner une image vidéo sur un canevas à l'aide
drawImage ()
fait via cette API sera synchronisé au mieux avec la fréquence d'images de la vidéo qui est lue à l'écran. Différent de
window.requestAnimationFrame ()
, qui se déclenche généralement environ 60 fois par seconde,
requestVideoFrameCallback ()
est lié à la fréquence d'images réelle de la vidéo, avec un
exception:
Le taux effectif auquel les rappels sont exécutés est le taux le plus bas du taux vidéo et du taux du navigateur. Cela signifie qu'une vidéo à 25 ips lue dans un navigateur qui peint à 60 Hz déclencherait des rappels à 25 Hz. Une vidéo à 120 ips sur ce même navigateur à 60 Hz déclencherait des rappels à 60 Hz.
Qu'est-ce qu'il y a dans un nom?
En raison de sa similitude avec window.requestAnimationFrame ()
, la méthode était initialement proposé comme video.requestAnimationFrame ()
, mais je suis content du nouveau nom,
requestVideoFrameCallback ()
, ce qui a été convenu après un longue discussion. Hourra, vélos pour la victoire!
Prise en charge du navigateur et détection des fonctionnalités
La méthode est
implémenté dans Chromium
déjà, et
Les gens de Mozilla aiment. Pour ce que ça vaut, j'ai également soumis un
Erreur WebKit le demander. La détection des fonctionnalités de l'API fonctionne comme ceci:
si ('requestVideoFrameCallback' dans HTMLVideoElement.prototype) {
}
Utilisation de la méthode requestVideoFrameCallback ()
Si vous avez déjà utilisé le requestAnimationFrame ()
méthode, vous vous sentirez immédiatement chez vous avec la requestVideoFrameCallback ()
méthode. Vous enregistrez un rappel initial une fois, puis vous vous réinscrivez chaque fois que le rappel est déclenché.
const doSomethingWithTheFrame = (à présent, métadonnées) => {
console.Journal(à présent, métadonnées);
vidéo.requestVideoFrameCallback(doSomethingWithTheFrame);
};
vidéo.requestVideoFrameCallback(doSomethingWithTheFrame);
Dans le rappel, à présent
c'est un DOMHighResTimeStamp
y métadonnées
c'est un VideoFrameMetadata
dictionnaire avec les propriétés suivantes:
presentationTime
, de typeDOMHighResTimeStamp
: El momento en el que el agent utilisateur envió el marco para su composición.attenduDisplayTime
, de typeDOMHighResTimeStamp
: El momento en el que el agente de Nom d'utilisateur espera que el marco être visible.largeur
, de typenon signé longtemps
: La largeur de l'image vidéo, en pixels multimédias.la taille
, de typenon signé longtemps
: La hauteur de l'image vidéo, en pixels multimédia.mediaTime
, de typedouble
: L'horodatage d'affichage du média (PTS) en secondes de l'image affichée (par exemple, votre horodatage dans levideo.currentTime
ligne de temps).Cadres présentés
, de typenon signé longtemps
: Compte du nombre d'images envoyées pour la composition. Permet aux clients de déterminer si des trames ont été perdues entre les instances deVideoFrameRequestCallback
.traitementDurée
, de typedouble
: La durée écoulée en secondes depuis l'envoi du paquet codé avec le même horodatage de présentation (PTS) que cette trame (par exemple, le même que lemediaTime
) au décodeur jusqu'à ce que la trame décodée soit prête à être présentée.
Pour les applications WebRTC, des propriétés supplémentaires peuvent apparaître:
captureTime
, de typeDOMHighResTimeStamp
: Pour les images vidéo provenant d'une source locale ou distante, c'est le moment où la caméra a capturé l'image. Pour une source distante, l'heure de capture est estimée à l'aide de la synchronisation d'horloge de l'émetteur RTCP et de la génération de rapports pour convertir les horodatages RTP en heure de capture.recevoirTime
, de typeDOMHighResTimeStamp
: Pour les trames vidéo provenant d'une source distante, il s'agit de l'heure à laquelle la plate-forme a reçu la trame codée, c'est-à-dire l'heure à laquelle le dernier paquet appartenant à cette trame a été reçu via le réseau.rtpTimestamp
, de typenon signé longtemps
: Horodatage RTP associé à cette image vidéo.
Notez que largeur
y la taille
peut différer de videoWidth
y vidéoHeight
dans certains cas (par exemple, une vidéo anamorphique peut avoir des pixels rectangulaires).
Un intérêt particulier dans cette liste est mediaTime
. Dans l'implémentation Chromium, nous utilisons l'horloge audio comme source de temps qui prend en charge video.currentTime
, Pendant ce temps, il mediaTime
est peuplé directement par le PrésentationTimestamp
du cadre. Les mediaTime
est ce qu'il faut utiliser si vous souhaitez identifier avec précision les images de manière reproductible, même pour identifier exactement les images qui ont été perdues.
Malheureusement, l'élément vidéo ne garantit pas la précision des images recherche. Cela a été un sujet de discussion.
WebCodecs cela permettra éventuellement des applications précises.
Si les choses semblent être une boîte loin ...
La synchronisation verticale (ou simplement vsync) est une technologie graphique qui synchronise la fréquence d'images d'une vidéo et la fréquence de rafraîchissement d'un moniteur. Car requestVideoFrameCallback ()
il s'exécute dans le fil principal, mais sous le capot, la composition vidéo se produit dans le fil du compositeur, tout ce qui provient de cette API est un meilleur effort et nous n'offrons aucune garantie stricte. Ce qui peut se produire, c'est que l'API peut retarder un vsync par rapport au moment où une image vidéo est rendue. Un vsync est requis pour que les modifications apportées à la page Web via l'API apparaissent à l'écran (comme window.requestAnimationFrame ()
). Donc, si vous continuez à mettre à jour mediaTime
ou le numéro d'image sur votre page Web et comparez-le aux images vidéo numérotées, la vidéo aura finalement l'air d'avoir une image d'avance.
Ce qui se passe réellement, c'est que la trame est prête dans vsync x, le rappel se déclenche et la trame est traitée dans vsync x + 1, et les modifications apportées au rappel sont traitées dans vsync x + 2. Vous pouvez vérifier si le rappel est un vsync tardif (et le cadre est déjà rendu à l'écran) en vérifiant si le metadata.expectedDisplayTime
est d'environ à présent
ou un vsync dans le futur. Si c'est dans les cinq à dix microsecondes de à présent
, l'image est déjà rendue; Si il attenduDisplayTime
il reste environ seize millisecondes dans le futur (en supposant que votre navigateur / écran se mette à jour à 60 Hz), alors il est synchronisé avec le cadre.
Manifestation
J'ai créé un petit
Démo Glitch
que muestra cómo se dibujan los fotogramas en un lienzo exactamente a la velocidad de fotogramas del video y dónde se registran los métadonnées del fotograma para fines de depuración. La lógica central es solo un par de líneas de JavaScript.
laisser paintCount = 0;
laisser startTime = 0.0;const updateCanvas = (à présent, métadonnées) => {
si (startTime === 0.0) {
startTime = à présent;
}
ctx.drawImage(vidéo, 0, 0, canvas.largeur, canvas.la taille);
const elapsed = (à présent - startTime) / 1000.0;
const fps = (++paintCount / elapsed).toFixed(3);
fpsInfo.innerText = `video fps: ${fps}`;
metadataInfo.innerText = JSON.stringify(métadonnées, nul, 2);
vidéo.requestVideoFrameCallback(updateCanvas);
};
vidéo.requestVideoFrameCallback(updateCanvas);
Conclusions
J'ai fait du traitement au niveau de la trame pendant longtemps, sans avoir accès aux trames réelles, juste en fonction de video.currentTime
. Implementé la segmentation de tomas de video en JavaScript de una manera aproximada; todavía puedes leer el adjunto
travail de recherche. Avait le requestVideoFrameCallback ()
existait à l'époque, ma vie aurait été beaucoup plus simple ...
Merci
Les requestVideoFrameCallback
L'API a été spécifiée et mise en œuvre par
Thomas Guilbert. Cet article a été révisé par Joe medley
y Kayce Basques.
Image de héros pour
Denise Jans sur Unsplash.