Video frames shake/stutter when rendering HTML5 video to Canvas during CSS animation
I'm experiencing video frame shaking/stuttering in a video carousel where videos are rendered to Canvas while a CSS animation is running. The videos should play smoothly but instead show visual jitter and frame drops.
Setup
I have a video carousel that:
- Uses HTML5
<video>elements with Canvas rendering viadrawImage() - Runs a continuous CSS animation (
transform: translateY()) - Uses
IntersectionObserverto control video playback - Renders video frames using
requestAnimationFrame
The Problem
Videos shake/stutter when the carousel animation is running. When I disable the CSS animation, videos play smoothly.
Relevant Code
Canvas Video Rendering:
function setupCanvasVideoPlayer(container, video) {
const canvas = document.createElement('canvas');
canvas.className = 'video-canvas';
container.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
let animationId;
let isPlaying = false;
const renderFrame = () => {
if (!container.isConnected || !isPlaying) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
try {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
} catch (e) {
// Handle drawing errors
}
animationId = requestAnimationFrame(renderFrame);
};
video.addEventListener('play', () => {
isPlaying = true;
if (!animationId) {
animationId = requestAnimationFrame(renderFrame);
}
});
}
CSS Animation:
.carousel-track {
animation: scrollVideos 20s linear infinite;
will-change: transform;
backface-visibility: hidden;
transform: translateZ(0);
}
@keyframes scrollVideos {
0% { transform: translateY(0); }
100% { transform: translateY(-1760px); }
}
HTML Structure:
<div class="right-carousel">
<div class="carousel-track">
<div class="carousel-video">
<video src="video1.mp4" autoplay muted playsinline></video>
</div>
<div class="carousel-video">
<video src="video2.mp4" autoplay muted playsinline></video>
</div>
<!-- More videos... -->
</div>
</div>
What I've Tried
GPU Acceleration optimizations:
will-change: transform; backface-visibility: hidden; transform: translateZ(0);Canvas optimizations:
ctx.imageSmoothingEnabled = false; // Using requestAnimationFrame for renderingVideo element positioning:
video.style.visibility = 'hidden'; video.style.position = 'absolute'; video.style.pointerEvents = 'none';
Questions
- Why does the CSS animation cause Canvas video rendering to shake?
- How can I synchronize Canvas rendering with CSS animations?
- Are there better approaches for smooth video playback in animated containers?
- Should I use
transform3d()instead oftranslateY()for better performance?
Browser Testing
- Chrome: Severe shaking
- Firefox: Moderate shaking
- Safari: Used Fallback Image
Expected Result
Smooth video playback without frame drops or visual stuttering during carousel animation.
Actual Result
Videos appear to shake/stutter, creating a poor user experience.
Environment:
- Modern browsers (Chrome 120+, Firefox 115+)
- Video format: MP4
- Canvas 2D context
- CSS animations + requestAnimationFrame
Any insights on resolving this Canvas + CSS animation conflict would be greatly appreciated!
div.carousel-video, and calling the function for each container-video pair? Does the problem persist if you try a different device (other desktop/laptop, a tablet, a mobile phone)?IntersectionObserver:document.querySelectorAll('.carousel-video').forEach(container => { const video = container.querySelector('video'); if (video) { videoObserver.observe(container); } });The function gets triggered when videos enter the viewport. Device testing: The problem persists across different devices - severe shaking on desktop Chrome, moderate on Firefox.<video>elements from the DOM. Browsers do throttle video elements that are in the DOM but not visible on screen (though that would be weird I don't experience it on my setup).