← Back to results

HTTP/1

.1 200 OK Connection: keep-alive Content-Length: 169228 etag: "ba73b5fb65e12a8047d1e932f3254a2f" content-type: text/html server: Google Frontend x-goog-stored-content-encoding: identity referrer-policy: strict-origin-when-cross-origin x-goog-metageneration: 1 x-goog-storage-class: STANDARD x-cloud-trace-context: f764fca079764ef45e44dd1c72ef95b9;o=1 x-goog-hash: crc32c=9RgO4A==, md5=unO1+2XhKoBH0eky8yVKLw== content-security-policy: default-src 'self'; script-src 'report-sample' 'self' 'wasm-unsafe-eval' assets.codepen.io production-assets.codepen.io https://js.stripe.com transcend-cdn.com 'sha256-XNBp89FG76amD8BqrJzyflxOF9PaWPqPqvJfKZPCv7M=' 'sha256-YCNoU9DNiinACbd8n6UPyB/8vj0kXvhkOni9/06SuYw=' 'sha256-PZjP7OR6mBEtnvXIZfCZ5PuOlxoDF1LDZL8aj8c42rw='; script-src-elem 'report-sample' 'self' 'wasm-unsafe-eval' assets.codepen.io production-assets.codepen.io https://js.stripe.com transcend-cdn.com 'sha256-XNBp89FG76amD8BqrJzyflxOF9PaWPqPqvJfKZPCv7M=' 'sha256-YCNoU9DNiinACbd8n6UPyB/8vj0kXvhkOni9/06SuYw=' 'sha256-PZjP7OR6mBEtnvXIZfCZ5PuOlxoDF1LDZL8aj8c42rw='; style-src 'report-sample' 'self' 'unsafe-inline' transcend-cdn.com; object-src 'none'; base-uri 'self'; connect-src 'self' developer.allizom.org bcd.developer.allizom.org bcd.developer.mozilla.org updates.developer.allizom.org updates.developer.mozilla.org https://incoming.telemetry.mozilla.org https://observatory-api.mdn.allizom.net https://observatory-api.mdn.mozilla.net telemetry.transcend.io telemetry.us.transcend.io transcend-cdn.com https://api.github.com/search/issues https://api.stripe.com; font-src 'self'; frame-src 'self' mdn.github.io *.mdnplay.dev *.mdnyalp.dev *.play.test.mdn.allizom.net https://v2.scrimba.com https://scrimba.com jsfiddle.net www.youtube-nocookie.com codepen.io survey.alchemer.com https://js.stripe.com; img-src 'self' data: *.githubusercontent.com *.gravatar.com mozillausercontent.com firefoxusercontent.com profile.stage.mozaws.net profile.accounts.firefox.com developer.mozilla.org mdn.dev wikipedia.org upload.wikimedia.org https://mdn.github.io/shared-assets/ https://mdn.dev/; manifest-src 'self'; media-src 'self' archive.org videos.cdn.mozilla.net https://mdn.github.io/shared-assets/; child-src 'self'; worker-src 'self'; x-guploader-uploadid: AJ5rDhFGc66F0sPxqpD536DcEGjGkcmxvMw_m6oUi5-ox_bDJmt3T5W9ced-dIiqIIXAnpctUnGqnFA x-frame-options: DENY x-goog-stored-content-length: 169228 x-content-type-options: nosniff x-goog-meta-goog-reserved-file-mtime: 1782954895 strict-transport-security: max-age=63072000 via: 1.1 google, 1.1 varnish, 1.1 varnish, 1.1 varnish x-goog-generation: 1782955805163085 expires: Thu, 02 Jul 2026 21:19:15 GMT last-modified: Thu, 02 Jul 2026 01:30:05 GMT cache-control: public, max-age=3600 Accept-Ranges: bytes Age: 0 Date: Thu, 02 Jul 2026 20:19:16 GMT X-Served-By: cache-bfi-kbfi7400076-BFI, cache-bfi-kbfi7400076-BFI, cache-bfi-kbfi7400074-BFI, cache-dfw-ktki8620074-DFW X-Cache: MISS, MISS, MISS X-Cache-Hits: 0, 0, 0 X-Timer: S1783023555.418546,VS0,VE1095 Vary: Accept-Encoding HTMLVideoElement: requestVideoFrameCallback() method - Web APIs | MDN Skip to main content Skip to search MDN HTML HTML: Markup language HTML reference Elements Global attributes Attributes See all… HTML guides Responsive images HTML cheatsheet Date & time formats See all… Markup languages SVG MathML XML CSS CSS: Styling language CSS reference Properties Selectors At-rules Values See all… CSS guides Box model Animations Flexbox Colors See all… Layout cookbook Column layouts Centering an element Card component See all… JavaScript JS JavaScript: Scripting language JS reference Standard built-in objects Expressions & operators Statements & declarations Functions See all… JS guides Control flow & error handing Loops and iteration Working with objects Using classes See all… Web APIs Web APIs: Programming interfaces Web API reference File system API Fetch API Geolocation API HTML DOM API Push API Service worker API See all… Web API guides Using the Web animation API Using the Fetch API Working with the History API Using the Web speech API Using web workers All All web technology Technologies Accessibility HTTP URI Web extensions WebAssembly WebDriver See all… Topics Media Performance Privacy Security Progressive web apps Learn Learn web development Frontend developer course Getting started modules Core modules MDN Curriculum Check out the video course from Scrimba, our partner Learn HTML Structuring content with HTML module Learn CSS CSS styling basics module CSS layout module Learn JavaScript Dynamic scripting with JavaScript module Tools Discover our tools Playground HTTP Observatory Border-image generator Border-radius generator Box-shadow generator Color format converter Color mixer Shape generator About Get to know MDN better About MDN Advertise with us Community MDN on GitHub Blog Toggle sidebar Web Web APIs HTMLVideoElement requestVideoFrameCallback() Theme OS default Light Dark English (US) Remember language Learn more Deutsch English (US) Français 日本語 HTMLVideoElement: requestVideoFrameCallback() method Baseline 2024 Newly available Since October 2024, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers. Learn more See full compatibility The requestVideoFrameCallback() method of the HTMLVideoElement interface registers a callback function that runs when a new video frame is sent to the compositor. This enables developers to perform efficient operations on each video frame. In this article Syntax Description Examples Specifications Browser compatibility See also Syntax js requestVideoFrameCallback(callback) Parameters callback The callback function that runs when a new video frame is sent to the compositor. This contains two parameters: now A DOMHighResTimeStamp representing the time when the callback was called. metadata An object containing the following properties: expectedDisplayTime A DOMHighResTimeStamp representing the time when the browser expects the frame to be visible. height A number, in media pixels, representing the height of the video frame (the visible decoded pixels, without aspect ratio adjustments). mediaTime A number, in seconds, representing the media presentation timestamp of the presented frame. This is equal to the frame's timestamp on the HTMLMediaElement.currentTime timeline. presentationTime A DOMHighResTimeStamp representing the time when the browser submitted the frame for composition. presentedFrames A number representing the number of frames submitted for composition so far alongside the current callback. This can be used to detect whether frames were missed between callback instances. processingDuration A number, in seconds, representing the duration between the submission of the encoded packet with the same presentation timestamp as this frame to the decoder (i.e., the mediaTime ) and the decoded frame being ready for presentation. width A number, in media pixels, representing the width of the video frame (the visible decoded pixels, without aspect ratio adjustments). Additional metadata properties may be available within requestVideoFrameCallback() callbacks used in WebRTC applications: captureTime A DOMHighResTimeStamp representing the time when the frame was captured. This applies to video frames coming from a local or remote source. For a remote source, the capture time is estimated using clock synchronization and RTCP sender reports to convert RTP timestamps to capture time. receiveTime A DOMHighResTimeStamp representing the time when the encoded frame was received by the platform. This applies to video frames coming from a remote source. Specifically, this corresponds to the time when the last packet belonging to this frame was received over the network. rtpTimestamp A number representing the RTP timestamp associated with this video frame. Note: width and height may differ from HTMLVideoElement.videoWidth and HTMLVideoElement.videoHeight in certain cases (for example, an anamorphic video may have rectangular pixels). Return value A number representing a unique callback ID. This can be passed to HTMLVideoElement.cancelVideoFrameCallback() to cancel the callback registration. Description Typical use cases for requestVideoFrameCallback() include video processing and painting to a canvas, video analysis, and synchronization with external audio sources. Per-frame processing used to be done in a less efficient or accurate fashion by running operations on the current video display whenever the timeupdate event fired. This technique did not provide access to the actual video frames. requestVideoFrameCallback() is used in the same way as Window.requestAnimationFrame() . You use it to run a callback function that performs some operation when the next video frame is sent to the compositor. The callback finishes by calling requestVideoFrameCallback() again to run the callback when the next video frame is composited, and so on. However, requestVideoFrameCallback() is tailored for video operations in several ways: requestVideoFrameCallback() provides reliable access to each individual video frame. requestAnimationFrame() tries to match the display refresh rate, which is typically 60Hz. requestVideoFrameCallback() , on the other hand, tries to match the video frame rate. More specifically, the callback will run at the lower of the video frame rate and the browser paint refresh rate. For example, a video with a frame rate of 25fps playing in a browser that paints at 60Hz would fire callbacks at a rate of 25Hz. A video with a frame rate of 120fps running in the same 60Hz browser would fire callbacks at 60Hz. requestVideoFrameCallback() makes useful video metadata available in the callback function. One thing to bear in mind is that requestVideoFrameCallback() does not offer any strict guarantees that the output from your callback will remain in sync with the video frame rate. It may end up being fired one vertical synchronization (v-sync) later than when the new video frame was presented. (V-sync is a graphics technology that synchronizes the frame rate of a video with the refresh rate of a monitor.) The API runs on the main thread, while video compositing likely happens on a separate compositing thread. You've got to factor in the time taken for these operations to complete, as well as the time it takes for the video itself and the result of your requestVideoFrameCallback() operation to display on the screen. You can compare the now callback parameter and the expectedDisplayTime metadata property to determine whether your callback is a v-sync late. If expectedDisplayTime is within about five to ten microseconds of now , the frame is already rendered. If the expectedDisplayTime is approximately sixteen milliseconds in the future (assuming your browser/screen is refreshing at 60Hz), then the callback is a v-sync out. Examples Drawing video frames on a canvas This example shows how to use requestVideoFrameCallback() to draw the frames of a video onto a <canvas> element at exactly the same frame rate as the video. It also logs the frame metadata to the screen for debugging purposes. js const button = document.querySelector("button"); const video = document.querySelector("video"); const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); const fpsInfo = document.querySelector("#fps-info"); const metadataInfo = document.querySelector("#metadata-info"); button.addEventListener("click", () => video.paused ? video.play() : video.pause(), ); video.addEventListener("play", () => { if (!("requestVideoFrameCallback" in HTMLVideoElement.prototype)) { console.error( "Your browser does not support the `Video.requestVideoFrameCallback()` API.", ); } }); let width = canvas.width; let height = canvas.height; let paintCount = 0; let startTime = 0.0; const updateCanvas = (now, metadata) => { if (startTime === 0.0) { startTime = now; } ctx.drawImage(video, 0, 0, width, height); const elapsed = (now - startTime) / 1000.0; const fps = (++paintCount / elapsed).toFixed(3); fpsInfo.innerText = !isFinite(fps) ? 0 : fps; metadataInfo.innerText = JSON.stringify(metadata, null, 2); video.requestVideoFrameCallback(updateCanvas); }; video.src = "https://mdn.github.io/shared-assets/videos/flower.mp4"; video.requestVideoFrameCallback(updateCanvas); css video, canvas { max-width: 49%; } html <p> Start <button type="button">⏯</button> playing the video. Pause the video to read the metadata. Drawing video frames on the canvas is synced with the actual video framerate. </p> <video controls playsinline></video> <canvas width="960" height="540"></canvas> <p><span id="fps-info">0</span>fps</p> <pre id="metadata-info"></pre> Specifications Specification HTMLVideoElement.requestVideoFrameCallback() # dom-htmlvideoelement-requestvideoframecallback Browser compatibility Enable JavaScript to view this browser compatibility table. See also The <video> element HTMLVideoElement.cancelVideoFrameCallback() Perform efficient per-video-frame operations on video with requestVideoFrameCallback() on developer.chrome.com (2023) Help improve MDN Was this page helpful to you? Yes No Learn how to contribute This page was last modified on Sep 11, 2025 by MDN contributors . View this page on GitHub • Report a problem with this content Filter sidebar Clear filter input HTML DOM API HTMLVideoElement Instance properties disablePictureInPicture height poster videoHeight videoWidth width Instance methods cancelVideoFrameCallback() getVideoPlaybackQuality() requestPictureInPicture() requestVideoFrameCallback() Events enterpictureinpicture leavepictureinpicture resize Inheritance HTMLMediaElement HTMLElement Element Node EventTarget Related pages for HTML DOM BeforeUnloadEvent DOMStringMap ErrorEvent HTMLAnchorElement HTMLAreaElement HTMLAudioElement HTMLBRElement HTMLBaseElement HTMLBodyElement HTMLButtonElement HTMLCanvasElement HTMLDListElement HTMLDataElement HTMLDataListElement HTMLDialogElement HTMLDivElement HTMLDocument HTMLElement HTMLEmbedElement HTMLFieldSetElement HTMLFormControlsCollection HTMLFormElement HTMLFrameSetElement HTMLGeolocationElement HTMLHRElement HTMLHeadElement HTMLHeadingElement HTMLHtmlElement HTMLIFrameElement HTMLImageElement HTMLInputElement HTMLLIElement HTMLLabelElement HTMLLegendElement HTMLLinkElement HTMLMapElement HTMLMediaElement HTMLMenuElement HTMLMetaElement HTMLMeterElement HTMLModElement HTMLOListElement HTMLObjectElement HTMLOptGroupElement HTMLOptionElement HTMLOptionsCollection HTMLOutputElement HTMLParagraphElement HTMLPictureElement HTMLPreElement HTMLProgressElement HTMLQuoteElement HTMLScriptElement HTMLSelectElement HTMLSourceElement HTMLSpanElement HTMLStyleElement HTMLTableCaptionElement HTMLTableCellElement HTMLTableColElement HTMLTableElement HTMLTableRowElement HTMLTableSectionElement HTMLTemplateElement HTMLTextAreaElement HTMLTimeElement HTMLTitleElement HTMLTrackElement HTMLUListElement HTMLUnknownElement HashChangeEvent History ImageData Location MessageChannel MessageEvent MessagePort Navigator PageRevealEvent PageSwapEvent PageTransitionEvent Plugin PluginArray PromiseRejectionEvent RadioNodeList TimeRanges UserActivation ValidityState Window WorkletGlobalScope Guides Using microtasks in JavaScript with queueMicrotask() In depth: Microtasks and the JavaScript runtime environment MDN Your blueprint for a better internet. MDN About Blog Mozilla careers Advertise with us MDN Plus Product help Contribute MDN Community Community resources Writing guidelines MDN Discord MDN on GitHub Developers Web technologies Learn web development Guides Tutorials Glossary Hacks blog Mozilla Website Privacy Notice Telemetry Settings Legal Community Participation Guidelines Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license .