@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
160 lines (159 loc) • 6.12 kB
JavaScript
;
import { VideoTexture, Loader } from "three";
import { CoreLoaderTexture } from "../Texture";
import { CoreBaseLoader } from "./../_Base";
import { Poly } from "../../../engine/Poly";
const VIDEO_SOURCE_TYPE_BY_EXT = {
ogg: 'video/ogg; codecs="theora, vorbis"',
ogv: 'video/ogg; codecs="theora, vorbis"',
mp4: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
};
class VideoTextureLoader extends Loader {
constructor(manager, originalUrls) {
super(manager);
this.originalUrls = originalUrls;
}
loadMultipleUrls(urls, onLoad, onProgress, onError) {
const video = document.createElement("video");
video.setAttribute("crossOrigin", "anonymous");
video.setAttribute("playinline", `${true}`);
video.setAttribute("muted", `${true}`);
video.setAttribute("autoplay", `${true}`);
video.style.display = "none";
const texture = new VideoTexture(video);
video.onloadedmetadata = () => {
onLoad(texture);
};
video.onprogress = (ev) => {
if (onProgress) {
onProgress(ev.loaded / ev.total);
}
};
const _onError = (error) => {
if (onError) {
onError(new Error("failed to load video"));
}
};
video.onerror = _onError;
const urlsCount = urls.length;
for (let i = 0; i < urlsCount; i++) {
const blobUrl = urls[i];
const originalUrl = this.originalUrls[i];
const ext = CoreBaseLoader.extension(originalUrl);
const type = VIDEO_SOURCE_TYPE_BY_EXT[ext] || `video/${ext}`;
const source = document.createElement("source");
source.src = blobUrl;
source.type = type;
video.append(source);
}
}
}
export class CoreVideoTextureLoader extends CoreBaseLoader {
async loadVideo() {
const urls = this._urlToLoad();
return new Promise(async (resolve, reject) => {
const loader = await this._getLoader();
urls.forEach((url) => CoreLoaderTexture.incrementInProgressLoadsCount());
await CoreLoaderTexture.waitForMaxConcurrentLoadsQueueFreed();
loader.loadMultipleUrls(
urls,
(texture) => {
urls.forEach((url, i) => {
const isLast = i == urls.length - 1;
CoreLoaderTexture.decrementInProgressLoadsCount(url, isLast ? texture : void 0);
});
resolve(texture);
},
void 0,
(error) => {
urls.forEach((url) => CoreLoaderTexture.decrementInProgressLoadsCount(url));
Poly.warn("error", error);
reject();
}
);
});
}
async _getLoader() {
const loader = new VideoTextureLoader(this.loadingManager, this._url);
return loader;
}
// constructor(protected override _url: string, protected override _node: BaseNodeType) {
// super(_url, _node);
// }
// loadVideo(): Promise<VideoTexture> {
// // if (1 + 1) {
// // return this._loadVideoFull();
// // } else {
// return this._loadVideoDefault();
// // }
// }
// // private _loadVideoFull(): Promise<VideoTexture> {
// // return new Promise(async (resolve) => {
// // const url = await this._urlToLoad();
// // console.log(url);
// // fetch(url, {mode: 'no-cors'}).then(async (response) => {
// // console.log({response});
// // const blob = await response.blob();
// // console.log({blob});
// // const source = URL.createObjectURL(blob);
// // console.log(source);
// // const video = document.createElement('video');
// // video.src = source;
// // const texture = new VideoTexture(video);
// // // document.body.append(video)
// // resolve(texture);
// // });
// // });
// // }
// private _loadVideoDefault(): Promise<VideoTexture> {
// return new Promise(async (resolve, reject) => {
// const url = await this._urlToLoad();
// CoreLoaderTexture.incrementInProgressLoadsCount();
// await CoreLoaderTexture.waitForMaxConcurrentLoadsQueueFreed();
// const video = document.createElement('video');
// video.setAttribute('crossOrigin', 'anonymous');
// video.setAttribute('autoplay', `${true}`); // to ensure it loads
// video.setAttribute('loop', `${true}`);
// // wait for onloadedmetadata to ensure that we have a duration
// // video.onloadeddata = function (e) {
// // console.log('onloadeddata', e);
// // };
// video.onloadedmetadata = function () {
// video.pause();
// const texture = new VideoTexture(video);
// // video.setAttribute('controls', true)
// // video.style="display:none"
// CoreLoaderTexture.decrementInProgressLoadsCount(url, texture);
// resolve(texture);
// };
// // add source as is
// const originalSource = document.createElement('source');
// const originalExt = CoreBaseLoader.extension(url) as keyof VideoSourceTypeByExt;
// let type: string = VideoTextureLoader.VIDEO_SOURCE_TYPE_BY_EXT[originalExt];
// type = type || VideoTextureLoader._default_video_source_type(url);
// originalSource.setAttribute('type', type);
// originalSource.setAttribute('src', url);
// video.appendChild(originalSource);
// // add secondary source, either mp4 or ogv depending on the first url
// let secondaryUrl: string | undefined;
// if (originalExt == 'mp4') {
// // add ogv
// secondaryUrl = CoreLoaderTexture.replaceExtension(url, 'ogv');
// } else {
// // add mp4
// secondaryUrl = CoreLoaderTexture.replaceExtension(url, 'mp4');
// }
// const secondary_source = document.createElement('source');
// const secondary_ext = CoreBaseLoader.extension(secondaryUrl) as keyof VideoSourceTypeByExt;
// type = VideoTextureLoader.VIDEO_SOURCE_TYPE_BY_EXT[secondary_ext];
// type = type || VideoTextureLoader._default_video_source_type(url);
// secondary_source.setAttribute('type', type);
// secondary_source.setAttribute('src', url);
// video.appendChild(secondary_source);
// });
// }
// static _default_video_source_type(url: string) {
// const ext = CoreBaseLoader.extension(url);
// return `video/${ext}`;
// }
}