Modern web applications increasingly rely on sophisticated video processing, from real-time video effects and analysis to synchronized canvas rendering and interactive media experiences. The requestVideoFrameCallback() API represents a significant advancement in how developers can work with video content in the browser, providing efficient, frame-level access that was previously difficult or impossible to achieve reliably. When building video processing pipelines, understanding how to work with canvas elements is essential for rendering processed frames.
This API, part of the HTMLVideoElement interface, enables developers to register callback functions that execute precisely when new video frames are sent to the compositor. Unlike older approaches that relied on imprecise timing mechanisms or polling, requestVideoFrameCallback() provides direct, efficient access to each individual video frame as it becomes available for display.
The introduction of this API reflects the growing importance of video on the web and the increasing sophistication of web-based media applications. Whether you're building a video editor, implementing real-time visual effects, creating interactive video experiences, or developing video analysis tools, understanding requestVideoFrameCallback() is essential for achieving optimal performance and visual quality.
For developers building complex video applications, our custom software development team has extensive experience implementing advanced video processing solutions. We also offer comprehensive web development services to help you leverage modern APIs like requestVideoFrameCallback.
What is requestVideoFrameCallback?
The requestVideoFrameCallback() method 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, such as processing, analysis, or rendering to a canvas element. The API is designed specifically for video-oriented use cases and provides timing and metadata information that is not available through other mechanisms.
At its core, requestVideoFrameCallback() solves a fundamental challenge in web video development: how to reliably execute code in sync with the actual frames being displayed. Traditional approaches like using requestAnimationFrame() or listening for timeupdate events either fire at the screen refresh rate (typically 60Hz) rather than the video frame rate, or fire too infrequently and unpredictably to be useful for frame-accurate operations.
Historical Context
The need for frame-level video access in web applications has existed since video became a prominent part of the web experience. Early attempts at video processing in browsers relied on techniques like periodically sampling video.currentTime and attempting to draw frames at approximately the right moments. These approaches were inherently unreliable, missing frames, processing the same frame multiple times, or introducing noticeable lag.
The requestAnimationFrame() API, while revolutionary for animation, was not designed with video in mind. It fires in sync with the browser's paint cycle, typically at the display's refresh rate (60Hz on most monitors), rather than the video's actual frame rate. For a 24fps video playing on a 60Hz display, requestAnimationFrame() would fire approximately two to three times per video frame, but at irregular intervals relative to when each frame is actually displayed.
Use Cases
- Video processing and effects: Apply filters, transformations, or visual effects to each frame in real-time
- Canvas synchronization: Draw video frames to canvas with perfect synchronization
- Video analysis: Analyze each frame for content, extract statistics, detect scenes
- Audio synchronization: Synchronize audio tracks with video using precise timing information
- Interactive experiences: Create video-based games and interactive content
For developers building complex video applications, our custom software development team has extensive experience implementing advanced video processing solutions. When working with canvas and video together, understanding related canvas APIs like Int8Array for pixel data manipulation and Buffer for efficient data handling can significantly improve your implementation.
API Reference
Syntax
const callbackId = videoElement.requestVideoFrameCallback(callback);
Callback Parameters
The callback receives two arguments:
- now: A
DOMHighResTimeStamprepresenting when the callback was called - metadata: An object containing detailed frame information
Metadata Properties
| Property | Type | Description |
|---|---|---|
presentationTime | DOMHighResTimeStamp | When the browser submitted the frame for composition |
expectedDisplayTime | DOMHighResTimeStamp | When the browser expects the frame to be visible |
mediaTime | number | Media presentation timestamp in seconds |
width | number | Frame width in media pixels |
height | number | Frame height in media pixels |
presentedFrames | number | Total frames sent to compositor |
processingDuration | number | Time from decoder submission to frame ready |
Return Value
Returns a numeric callback ID that can be used with cancelVideoFrameCallback() to unregister the callback.
WebRTC-Specific Properties
| Property | Type | Description |
|---|---|---|
captureTime | DOMHighResTimeStamp | When the frame was captured |
receiveTime | DOMHighResTimeStamp | When the encoded frame was received |
rtpTimestamp | number | RTP timestamp associated with the frame |
For complete technical details, see the MDN Web Docs - requestVideoFrameCallback documentation. Also check out the web.dev - RequestVideoFrameCallback Guide for best practices and implementation tips. When accessing DOM properties like width and height, understanding how ClientHeight and similar properties work can help with responsive video implementations.
Basic Usage Example
Here's a simple example of using requestVideoFrameCallback() to draw video frames to a canvas:
function processFrame(now, metadata) {
// Draw video frame to canvas
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
// Log frame information
console.log(`Frame ${metadata.presentedFrames} at ${metadata.mediaTime.toFixed(3)}s`);
// Request next frame
video.requestVideoFrameCallback(processFrame);
}
// Start processing
video.requestVideoFrameCallback(processFrame);
Feature Detection
function isRequestVideoFrameCallbackSupported() {
return 'requestVideoFrameCallback' in HTMLVideoElement.prototype;
}
Comparison with Alternatives
requestAnimationFrame vs requestVideoFrameCallback
| Aspect | requestAnimationFrame | requestVideoFrameCallback |
|---|---|---|
| Syncs with | Display refresh rate (typically 60Hz) | Video frame rate |
| Use case | General animations | Video-specific operations |
| Frame access | Indirect, requires detection | Direct, guaranteed per-frame |
| Timing precision | ~16ms intervals | Exact frame timing |
The requestVideoFrameCallback() API fires at the video's frame rate rather than the screen's refresh rate. For a 24fps video on a 60Hz display, callbacks fire 24 times per second instead of 60. This provides frame-accurate access and eliminates the need for frame detection logic.
timeupdate Event
The timeupdate event fires as infrequently as every 250ms per HTML specification, making it unsuitable for frame-level operations. requestVideoFrameCallback() fires for every single frame with detailed metadata, providing a fundamental difference in purpose--timeupdate is designed for coarse-grained progress tracking, while requestVideoFrameCallback() is designed for fine-grained frame access and processing.
Performance Benefits
- Reduced overhead: Callbacks only fire when new frames are available
- Better timing: Precise timestamps eliminate guesswork
- Automatic lifecycle: Browser manages callback suspension/resumption
- Frame metadata: Built-in access to timing and frame information
Learn more about efficient video processing in the web.dev - RequestVideoFrameCallback Guide. Understanding how Long Animation Frame Timing impacts your application can help you optimize video processing performance even further.
Browser Support
The requestVideoFrameCallback() API is supported in:
| Browser | Version | Release Date |
|---|---|---|
| Chrome | 83+ | May 2020 |
| Edge | 83+ | May 2020 |
| Firefox | 132+ | November 2024 |
| Safari | 15.4+ | March 2022 |
The API is part of the Baseline initiative, indicating broad support across modern browsers. For users with up-to-date browsers, no special handling is required.
Polyfill
For applications that need to support older browsers, a polyfill is available that uses requestAnimationFrame() and getVideoPlaybackQuality() as fallback mechanisms. The polyfill approximates the behavior of requestVideoFrameCallback() by using requestAnimationFrame() to check for new frames, though it has limitations in timing accuracy and available metadata.
Check current browser support on Can I Use - requestVideoFrameCallback.
Best Practices
Minimize Callback Processing Time
Keep callbacks short to prevent frame display delays. Offload heavy processing to Web Workers when necessary. For applications requiring optimal performance, our performance optimization services can help you implement best practices for video processing.
const worker = new Worker('video-processor.js');
function processFrame(now, metadata) {
// Offload heavy work
worker.postMessage({ imageData: getCurrentFrameData() });
// Keep callback minimal
video.requestVideoFrameCallback(processFrame);
}
Cancel Unused Callbacks
Clean up callbacks when they're no longer needed:
let callbackId = null;
function startProcessing() {
callbackId = video.requestVideoFrameCallback(processFrame);
}
function stopProcessing() {
if (callbackId !== null) {
video.cancelVideoFrameCallback(callbackId);
callbackId = null;
}
}
// Clean up when page is hidden
document.addEventListener('visibilitychange', () => {
if (document.hidden) stopProcessing();
else if (!video.paused) startProcessing();
});
Handle Video State Changes
Manage callbacks properly through video lifecycle events:
function handleVideoStateChange() {
if (video.paused || video.ended) {
stopProcessing();
} else {
startProcessing();
}
}
video.addEventListener('play', handleVideoStateChange);
video.addEventListener('pause', handleVideoStateChange);
video.addEventListener('ended', handleVideoStateChange);
Need help implementing these best practices? Our web development services include performance optimization and code review.
Advanced Use Cases
Real-Time Video Effects
Apply effects like sepia, blur, or color grading to each frame:
function applySepiaEffect(now, metadata) {
ctx.drawImage(video, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const r = data[i], g = data[i + 1], b = data[i + 2];
data[i] = Math.min(255, (r * 0.393) + (g * 0.769) + (b * 0.189));
data[i + 1] = Math.min(255, (r * 0.349) + (g * 0.686) + (b * 0.168));
data[i + 2] = Math.min(255, (r * 0.272) + (g * 0.534) + (b * 0.131));
}
ctx.putImageData(imageData, 0, 0);
video.requestVideoFrameCallback(applySepiaEffect);
}
Performance Monitoring
Track frame drops and processing delays:
let lastFrameCount = 0;
let droppedFrames = 0;
function monitorPerformance(now, metadata) {
const framesSinceLast = metadata.presentedFrames - lastFrameCount;
if (framesSinceLast > 1) {
droppedFrames += framesSinceLast - 1;
console.log(`Dropped frames: ${droppedFrames}`);
}
lastFrameCount = metadata.presentedFrames;
video.requestVideoFrameCallback(monitorPerformance);
}
Interactive Overlays
Create clickable areas synchronized with video content:
function renderInteractiveOverlay(now, metadata) {
ctx.drawImage(video, 0, 0);
const currentScene = getSceneAtTime(metadata.mediaTime);
currentScene.hotspots.forEach(spot => {
ctx.strokeStyle = 'yellow';
ctx.strokeRect(spot.x, spot.y, spot.width, spot.height);
});
video.requestVideoFrameCallback(renderInteractiveOverlay);
}
For enterprise-grade video applications requiring advanced features, our custom software development services can help you build scalable, high-performance solutions. When embedding video content in your web applications, understanding how the HtmlIFrameElement works can help with secure video embedding patterns.
Conclusion
The requestVideoFrameCallback() API provides web developers with reliable, efficient access to individual video frames as they are displayed. By synchronizing with the video frame rate rather than the display refresh rate, it enables applications that were previously difficult to implement in browsers.
Key advantages:
- Frame-accurate timing with detailed metadata
- Automatic lifecycle management by the browser
- Optimized performance through video pipeline integration
- Support across all major modern browsers
Whether you're building video editors, real-time effects systems, interactive experiences, or video analysis tools, requestVideoFrameCallback() is an essential tool for precise video frame control in modern web development. The API represents a significant advancement in web video capabilities, enabling sophisticated applications that push the boundaries of what's possible in browsers.
As web applications continue to incorporate more sophisticated video functionality, requestVideoFrameCallback() will become an increasingly important tool for developers. For complete technical specifications, see the WICG Video-RFC Specification.
Looking to implement advanced video features in your project? Our experienced team at Digital Thrive specializes in building cutting-edge web applications with advanced video processing capabilities. Contact us today to discuss your web development or custom software development needs.