icy3dw/src/client/object/other/video-player.ts

106 lines
2.3 KiB
TypeScript
Raw Normal View History

2022-04-09 18:53:02 +00:00
import Hls from 'hls.js';
import {
FrontSide,
Mesh,
MeshBasicMaterial,
PlaneGeometry,
VideoTexture,
} from 'three';
2022-04-09 19:01:48 +00:00
import { clamp } from 'three/src/math/MathUtils';
2022-04-09 18:53:02 +00:00
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;
2022-04-10 08:33:52 +00:00
constructor(public width: number, public height: number) {}
2022-04-09 18:53:02 +00:00
initialize() {
this.texture = new VideoTexture(this.video);
this.material = new MeshBasicMaterial({
map: this.texture,
side: FrontSide,
toneMapped: false,
});
2022-04-10 08:33:52 +00:00
this.geometry = new PlaneGeometry(this.width, this.height);
2022-04-09 18:53:02 +00:00
this.mesh = new Mesh(this.geometry, this.material);
2022-04-10 08:33:52 +00:00
2022-04-09 18:53:02 +00:00
this.video.addEventListener('canplay', () => {
this.playable = true;
});
2022-04-09 19:01:48 +00:00
this.video.addEventListener('error', () => {
this.playable = false;
this.video.pause();
this.video.src = undefined;
});
2022-04-09 19:53:14 +00:00
this.video.volume = 0.8;
2022-04-09 18:53:02 +00:00
}
public setSource(source: string, autoplay = false) {
2022-04-10 08:33:52 +00:00
this.video.pause();
2022-04-09 18:53:02 +00:00
if (this.hls) {
this.hls.stopLoad();
this.hls.destroy();
}
if (source.endsWith('m3u8')) {
2022-04-10 06:16:30 +00:00
if (Hls.isSupported()) {
2022-04-09 18:53:02 +00:00
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();
}
});
2022-04-09 19:53:14 +00:00
2022-04-09 18:53:02 +00:00
this.hls.on(Hls.Events.ERROR, (e, d) => {
2022-04-09 19:53:14 +00:00
if (d.fatal) {
this.playable = false;
2022-04-10 08:33:52 +00:00
this.video.pause();
this.hls.stopLoad();
2022-04-09 19:53:14 +00:00
}
2022-04-09 18:53:02 +00:00
});
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();
}
}
2022-04-09 19:01:48 +00:00
public setVolume(percent: number) {
const setter = clamp(percent, 0, 100) / 100;
this.video.volume = setter;
}
2022-04-09 18:53:02 +00:00
}