import * as THREE from "three";
import EventEmitter from "./event-emitter.js";
/** Class to setup the webcam. */
class Webcam extends EventEmitter {
#video;
/**
* Create a Webcam.
* @param constraints {Object} - options to use for initialising the camera.
* This is the same constraints object as used by standard MediaDevices API.
* @param {string} videoElementSelector - selector to obtain the HTML video
* element to render the webcam feed. If a falsy value (e.g. null or
* undefined), a video element will be created.
*/
constructor(
constraints = { video: { facingMode: "environment" } },
videoElementSelector,
) {
super();
this.sceneWebcam = new THREE.Scene();
if (!videoElementSelector) {
this.#video = document.createElement("video");
this.#video.setAttribute("autoplay", true);
this.#video.setAttribute("playsinline", true);
this.#video.style.display = "none";
document.body.appendChild(this.#video);
} else {
this.#video = document.querySelector(videoElementSelector);
}
this.texture = new THREE.VideoTexture(this.#video);
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
this.#video.addEventListener("loadedmetadata", () => {
this.#video.setAttribute("width", this.#video.videoWidth);
this.#video.setAttribute("height", this.#video.videoHeight);
this.#video.play();
/**
* Webcam started event.
* @event Webcam#webcamstarted
* @param {Object} event object containing 'texture' - the texture the webcam will stream to.
*/
this.emit("webcamstarted", { texture: this.texture });
});
this.#video.srcObject = stream;
})
.catch((e) => {
/**
* Webcam error event.
* @event Webcam#webcamerror
* @param {Object} event object with 'code' and 'message' fields.
*/
this.emit("webcamerror", {
code: e.name,
message: e.message,
});
});
} else {
this.emit("webcamerror", {
code: "LOCAR_NO_MEDIA_DEVICES_API",
message: "Media devices API not supported",
});
}
}
/**
* Free up the memory associated with the webcam.
* Should be called when your application closes.
*/
dispose() {
this.texture.dispose();
}
}
export default Webcam;