117 lines
4.2 KiB
JavaScript
117 lines
4.2 KiB
JavaScript
import { ExtensionType } from '../../../../extensions/Extensions.mjs';
|
|
import { VideoSource } from '../../../../rendering/renderers/shared/texture/sources/VideoSource.mjs';
|
|
import { detectVideoAlphaMode } from '../../../../utils/browser/detectVideoAlphaMode.mjs';
|
|
import { getResolutionOfUrl } from '../../../../utils/network/getResolutionOfUrl.mjs';
|
|
import { checkDataUrl } from '../../../utils/checkDataUrl.mjs';
|
|
import { checkExtension } from '../../../utils/checkExtension.mjs';
|
|
import { createTexture } from './utils/createTexture.mjs';
|
|
|
|
"use strict";
|
|
const validVideoExtensions = [".mp4", ".m4v", ".webm", ".ogg", ".ogv", ".h264", ".avi", ".mov"];
|
|
const validVideoMIMEs = validVideoExtensions.map((ext) => `video/${ext.substring(1)}`);
|
|
function crossOrigin(element, url, crossorigin) {
|
|
if (crossorigin === void 0 && !url.startsWith("data:")) {
|
|
element.crossOrigin = determineCrossOrigin(url);
|
|
} else if (crossorigin !== false) {
|
|
element.crossOrigin = typeof crossorigin === "string" ? crossorigin : "anonymous";
|
|
}
|
|
}
|
|
function preloadVideo(element) {
|
|
return new Promise((resolve, reject) => {
|
|
element.addEventListener("canplaythrough", loaded);
|
|
element.addEventListener("error", error);
|
|
element.load();
|
|
function loaded() {
|
|
cleanup();
|
|
resolve();
|
|
}
|
|
function error(err) {
|
|
cleanup();
|
|
reject(err);
|
|
}
|
|
function cleanup() {
|
|
element.removeEventListener("canplaythrough", loaded);
|
|
element.removeEventListener("error", error);
|
|
}
|
|
});
|
|
}
|
|
function determineCrossOrigin(url, loc = globalThis.location) {
|
|
if (url.startsWith("data:")) {
|
|
return "";
|
|
}
|
|
loc = loc || globalThis.location;
|
|
const parsedUrl = new URL(url, document.baseURI);
|
|
if (parsedUrl.hostname !== loc.hostname || parsedUrl.port !== loc.port || parsedUrl.protocol !== loc.protocol) {
|
|
return "anonymous";
|
|
}
|
|
return "";
|
|
}
|
|
const loadVideoTextures = {
|
|
name: "loadVideo",
|
|
extension: {
|
|
type: ExtensionType.LoadParser,
|
|
name: "loadVideo"
|
|
},
|
|
test(url) {
|
|
const isValidDataUrl = checkDataUrl(url, validVideoMIMEs);
|
|
const isValidExtension = checkExtension(url, validVideoExtensions);
|
|
return isValidDataUrl || isValidExtension;
|
|
},
|
|
async load(url, asset, loader) {
|
|
const options = {
|
|
...VideoSource.defaultOptions,
|
|
resolution: asset.data?.resolution || getResolutionOfUrl(url),
|
|
alphaMode: asset.data?.alphaMode || await detectVideoAlphaMode(),
|
|
...asset.data
|
|
};
|
|
const videoElement = document.createElement("video");
|
|
const attributeMap = {
|
|
preload: options.autoLoad !== false ? "auto" : void 0,
|
|
"webkit-playsinline": options.playsinline !== false ? "" : void 0,
|
|
playsinline: options.playsinline !== false ? "" : void 0,
|
|
muted: options.muted === true ? "" : void 0,
|
|
loop: options.loop === true ? "" : void 0,
|
|
autoplay: options.autoPlay !== false ? "" : void 0
|
|
};
|
|
Object.keys(attributeMap).forEach((key) => {
|
|
const value = attributeMap[key];
|
|
if (value !== void 0)
|
|
videoElement.setAttribute(key, value);
|
|
});
|
|
if (options.muted === true) {
|
|
videoElement.muted = true;
|
|
}
|
|
crossOrigin(videoElement, url, options.crossorigin);
|
|
const sourceElement = document.createElement("source");
|
|
let mime;
|
|
if (url.startsWith("data:")) {
|
|
mime = url.slice(5, url.indexOf(";"));
|
|
} else if (!url.startsWith("blob:")) {
|
|
const ext = url.split("?")[0].slice(url.lastIndexOf(".") + 1).toLowerCase();
|
|
mime = VideoSource.MIME_TYPES[ext] || `video/${ext}`;
|
|
}
|
|
sourceElement.src = url;
|
|
if (mime) {
|
|
sourceElement.type = mime;
|
|
}
|
|
return new Promise((resolve) => {
|
|
const onCanPlay = async () => {
|
|
const base = new VideoSource({ ...options, resource: videoElement });
|
|
videoElement.removeEventListener("canplay", onCanPlay);
|
|
if (asset.data.preload) {
|
|
await preloadVideo(videoElement);
|
|
}
|
|
resolve(createTexture(base, loader, url));
|
|
};
|
|
videoElement.addEventListener("canplay", onCanPlay);
|
|
videoElement.appendChild(sourceElement);
|
|
});
|
|
},
|
|
unload(texture) {
|
|
texture.destroy(true);
|
|
}
|
|
};
|
|
|
|
export { crossOrigin, determineCrossOrigin, loadVideoTextures, preloadVideo };
|
|
//# sourceMappingURL=loadVideoTextures.mjs.map
|