106 lines
2.3 KiB
TypeScript
106 lines
2.3 KiB
TypeScript
import Hls from 'hls.js';
|
|
import {
|
|
FrontSide,
|
|
Mesh,
|
|
MeshBasicMaterial,
|
|
PlaneGeometry,
|
|
VideoTexture,
|
|
} from 'three';
|
|
import { clamp } from 'three/src/math/MathUtils';
|
|
|
|
export class VideoPlayer {
|
|
public video = document.createElement('video');
|
|
public material!: MeshBasicMaterial;
|
|
public texture!: VideoTexture;
|
|
public mesh!: Mesh;
|
|
public hls?: Hls;
|
|
public playable: boolean;
|
|
public geometry!: PlaneGeometry;
|
|
|
|
constructor(public width: number, public height: number) {}
|
|
|
|
initialize() {
|
|
this.texture = new VideoTexture(this.video);
|
|
this.material = new MeshBasicMaterial({
|
|
map: this.texture,
|
|
side: FrontSide,
|
|
toneMapped: false,
|
|
});
|
|
this.geometry = new PlaneGeometry(this.width, this.height);
|
|
this.mesh = new Mesh(this.geometry, this.material);
|
|
|
|
this.video.addEventListener('canplay', () => {
|
|
this.playable = true;
|
|
});
|
|
|
|
this.video.addEventListener('error', () => {
|
|
this.playable = false;
|
|
this.video.pause();
|
|
this.video.src = undefined;
|
|
});
|
|
|
|
this.video.volume = 0.8;
|
|
}
|
|
|
|
public setSource(source: string, autoplay = false) {
|
|
this.video.pause();
|
|
if (this.hls) {
|
|
this.hls.stopLoad();
|
|
this.hls.destroy();
|
|
}
|
|
|
|
if (source.endsWith('m3u8')) {
|
|
if (Hls.isSupported()) {
|
|
this.hls = new Hls();
|
|
this.hls.loadSource(source);
|
|
this.hls.attachMedia(this.video);
|
|
|
|
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
this.playable = true;
|
|
|
|
if (autoplay) {
|
|
this.video.play();
|
|
} else {
|
|
this.hls.stopLoad();
|
|
}
|
|
});
|
|
|
|
this.hls.on(Hls.Events.ERROR, (e, d) => {
|
|
if (d.fatal) {
|
|
this.playable = false;
|
|
this.video.pause();
|
|
this.hls.stopLoad();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
this.video.src = source;
|
|
|
|
if (autoplay) {
|
|
this.video.play();
|
|
}
|
|
}
|
|
|
|
public play() {
|
|
if (this.playable) {
|
|
if (this.hls) {
|
|
this.hls.startLoad(-1);
|
|
}
|
|
this.video.play();
|
|
}
|
|
}
|
|
|
|
public stop() {
|
|
this.video.pause();
|
|
if (this.hls) {
|
|
this.hls.stopLoad();
|
|
}
|
|
}
|
|
|
|
public setVolume(percent: number) {
|
|
const setter = clamp(percent, 0, 100) / 100;
|
|
this.video.volume = setter;
|
|
}
|
|
}
|