How to Autoplay and Loop Three.js VideoTexture
To display autoplaying video in Three.js, you must configure the
underlying HTML5 <video> element to comply with
modern browser autoplay policies. Browsers block autoplaying videos with
audio to prevent intrusive user experiences. By programmatically setting
the video element to be muted, loop, and play inline, you can seamlessly
initialize a Three.js VideoTexture that plays automatically
upon loading without throwing console errors or being blocked by the
browser.
1. Configure the HTML5 Video Element
Three.js relies on a standard HTML5 <video>
element to source its video frames. Before passing this element to
Three.js, you must define the properties required by modern browsers
(such as Chrome, Safari, and iOS) to allow autoplay.
Create and configure the video element in your JavaScript file:
// Create the HTML5 video element
const video = document.createElement('video');
// Set the video source path
video.src = 'path/to/your/video.mp4';
// Required properties for autoplay compliance
video.muted = true; // Must be muted to bypass autoplay restrictions
video.loop = true; // Ensures the video loops continuously
video.playsInline = true; // Required for iOS/Safari mobile compatibility
video.autoplay = true; // Instructs the browser to start playback immediately
// Load the video source
video.load();
// Trigger playback programmatically
video.play().catch((error) => {
console.error("Autoplay was prevented by the browser. Waiting for user interaction.", error);
});2. Create and Apply the Three.js VideoTexture
Once the video element is configured, pass it directly into the
THREE.VideoTexture constructor. This specialized texture
class automatically updates the WebGL texture map every time a new video
frame is ready.
import * as THREE from 'three';
// Initialize the VideoTexture
const videoTexture = new THREE.VideoTexture(video);
// Optional: Set texture filtering and color space for better quality
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
videoTexture.colorSpace = THREE.SRGBColorSpace;
// Create a material using the video texture
const material = new THREE.MeshBasicMaterial({
map: videoTexture,
side: THREE.DoubleSide
});
// Apply the material to a mesh (e.g., a screen plane)
const geometry = new THREE.PlaneGeometry(16 / 9, 1); // 16:9 aspect ratio
const screenMesh = new THREE.Mesh(geometry, material);
scene.add(screenMesh);3. Handling Strict Browser Restrictions
While setting video.muted = true satisfies standard
autoplay policies, some strict browser environments may still block
video playback until a user interaction occurs. To guarantee your video
texture plays, you can add a global event listener that triggers
playback on the first user click or touch.
const startVideoOnInteraction = () => {
if (video.paused) {
video.play();
}
// Remove listeners once the video is successfully playing
window.removeEventListener('click', startVideoOnInteraction);
window.removeEventListener('touchstart', startVideoOnInteraction);
};
window.addEventListener('click', startVideoOnInteraction);
window.addEventListener('touchstart', startVideoOnInteraction);