import * as THREE from "three"; export class VideoController { constructor(container, sourceUrl, playbackRate = 1.0) { this.container = container; this.sourceUrl = sourceUrl; this.playbackRate = playbackRate; this.video = null; this._texture = null; } load() { return new Promise((resolve, reject) => { this.video = document.createElement("video"); this.video.src = this.sourceUrl; this.video.muted = true; this.video.loop = true; this.video.playbackRate = this.playbackRate; this.video.crossOrigin = "anonymous"; this.video.playsInline = true; this.video.setAttribute("playsinline", ""); this.video.style.display = "none"; this.container.appendChild(this.video); this._texture = new THREE.VideoTexture(this.video); this._texture.colorSpace = THREE.SRGBColorSpace; this._texture.minFilter = THREE.NearestFilter; this._texture.magFilter = THREE.NearestFilter; this.video.addEventListener( "loadeddata", () => { resolve(); }, {once: true} ); this.video.addEventListener( "error", (e) => { reject(new Error("Video load failed")); }, {once: true} ); this.video.load(); }); } play() { this.video.playbackRate = this.playbackRate; return this.video.play(); } pause() { this.video.pause(); } seek(time) { this.video.currentTime = time; } setPlaybackRate(rate) { this.playbackRate = rate; if (this.video) { this.video.playbackRate = rate; } } get width() { return this.video.videoWidth; } get height() { return this.video.videoHeight; } get isReady() { return this.video.readyState >= this.video.HAVE_CURRENT_DATA; } get texture() { return this._texture; } }