pixi.js
Version:
<p align="center"> <a href="https://pixijs.com" target="_blank" rel="noopener noreferrer"> <img height="150" src="https://files.pixijs.download/branding/pixijs-logo-transparent-dark.svg?v=1" alt="PixiJS logo"> </a> </p> <br/> <p align="center">
1 lines • 15.3 kB
Source Map (JSON)
{"version":3,"file":"loadVideoTextures.mjs","sources":["../../../../../src/assets/loader/parsers/textures/loadVideoTextures.ts"],"sourcesContent":["/* eslint-disable no-restricted-globals */\nimport { type ImageLike } from '../../../../environment/ImageLike';\nimport { ExtensionType } from '../../../../extensions/Extensions';\nimport { VideoSource } from '../../../../rendering/renderers/shared/texture/sources/VideoSource';\nimport { detectVideoAlphaMode } from '../../../../utils/browser/detectVideoAlphaMode';\nimport { getResolutionOfUrl } from '../../../../utils/network/getResolutionOfUrl';\nimport { testVideoFormat } from '../../../detections/utils/testVideoFormat';\nimport { checkDataUrl } from '../../../utils/checkDataUrl';\nimport { checkExtension } from '../../../utils/checkExtension';\nimport { createTexture } from './utils/createTexture';\n\nimport type { VideoSourceOptions } from '../../../../rendering/renderers/shared/texture/sources/VideoSource';\nimport type { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport type { ResolvedAsset } from '../../../types';\nimport type { Loader } from '../../Loader';\nimport type { LoaderParser } from '../LoaderParser';\n\nconst potentialVideoExtensions = ['.mp4', '.m4v', '.webm', '.ogg', '.ogv', '.h264', '.avi', '.mov'];\nlet validVideoExtensions: string[];\nlet validVideoMIMEs: string[];\n\n/**\n * Set cross origin based detecting the url and the crossorigin\n * @param element - Element to apply crossOrigin\n * @param url - URL to check\n * @param crossorigin - Cross origin value to use\n * @category assets\n * @advanced\n */\nexport function crossOrigin(element: ImageLike | HTMLVideoElement, url: string, crossorigin?: boolean | string): void\n{\n if (crossorigin === undefined && !url.startsWith('data:'))\n {\n element.crossOrigin = determineCrossOrigin(url);\n }\n else if (crossorigin !== false)\n {\n element.crossOrigin = typeof crossorigin === 'string' ? crossorigin : 'anonymous';\n }\n}\n\n/**\n * Preload a video element\n * @param element - Video element to preload\n * @internal\n */\nexport function preloadVideo(element: HTMLVideoElement): Promise<void>\n{\n return new Promise((resolve, reject) =>\n {\n element.addEventListener('canplaythrough', loaded);\n element.addEventListener('error', error);\n\n element.load();\n\n function loaded(): void\n {\n cleanup();\n resolve();\n }\n\n function error(err: ErrorEvent): void\n {\n cleanup();\n reject(err);\n }\n\n function cleanup(): void\n {\n element.removeEventListener('canplaythrough', loaded);\n element.removeEventListener('error', error);\n }\n });\n}\n\n/**\n * Sets the `crossOrigin` property for this resource based on if the url\n * for this resource is cross-origin. If crossOrigin was manually set, this\n * function does nothing.\n * Nipped from the resource loader!\n * @ignore\n * @param url - The url to test.\n * @param {object} [loc=window.location] - The location object to test against.\n * @returns The crossOrigin value to use (or empty string for none).\n * @category assets\n */\nexport function determineCrossOrigin(url: string, loc: Location = globalThis.location): string\n{\n // data: and javascript: urls are considered same-origin\n if (url.startsWith('data:'))\n {\n return '';\n }\n\n // default is window.location\n loc ||= globalThis.location;\n\n const parsedUrl = new URL(url, document.baseURI);\n\n // if cross origin\n if (parsedUrl.hostname !== loc.hostname || parsedUrl.port !== loc.port || parsedUrl.protocol !== loc.protocol)\n {\n return 'anonymous';\n }\n\n return '';\n}\n\ntype LoadVideoData = VideoSourceOptions & {\n mime?: string;\n};\n\n/**\n * Get the supported video extensions and MIME types based on the browser's capabilities.\n * This function checks the potential video extensions against the browser's supported formats.\n * @returns An object containing valid video extensions and MIME types.\n * @internal\n */\nfunction getBrowserSupportedVideoExtensions()\n{\n const supportedExtensions: string[] = [];\n const supportedMimes: string[] = [];\n\n for (const ext of potentialVideoExtensions)\n {\n const mimeType = VideoSource.MIME_TYPES[ext.substring(1)] || `video/${ext.substring(1)}`;\n\n if (testVideoFormat(mimeType))\n {\n supportedExtensions.push(ext);\n if (!supportedMimes.includes(mimeType))\n {\n supportedMimes.push(mimeType);\n }\n }\n }\n\n return {\n validVideoExtensions: supportedExtensions,\n validVideoMime: supportedMimes\n };\n}\n\n/**\n * A simple plugin to load video textures.\n *\n * You can pass VideoSource options to the loader via the .data property of the asset descriptor\n * when using Assets.load().\n * ```js\n * // Set the data\n * const texture = await Assets.load({\n * src: './assets/city.mp4',\n * data: {\n * preload: true,\n * autoPlay: true,\n * },\n * });\n * ```\n * @category assets\n * @advanced\n */\nexport const loadVideoTextures = {\n\n /** used for deprecation purposes */\n name: 'loadVideo',\n id: 'video',\n\n extension: {\n type: ExtensionType.LoadParser,\n name: 'loadVideo',\n },\n\n test(url: string): boolean\n {\n if (!validVideoExtensions || !validVideoMIMEs)\n {\n const { validVideoExtensions: ve, validVideoMime: vm } = getBrowserSupportedVideoExtensions();\n\n validVideoExtensions = ve;\n validVideoMIMEs = vm;\n }\n const isValidDataUrl = checkDataUrl(url, validVideoMIMEs);\n const isValidExtension = checkExtension(url, validVideoExtensions);\n\n return isValidDataUrl || isValidExtension;\n },\n\n async load(url: string, asset: ResolvedAsset<LoadVideoData>, loader: Loader): Promise<Texture>\n {\n // --- Merge default and provided options ---\n const options: LoadVideoData = {\n ...VideoSource.defaultOptions,\n resolution: asset.data?.resolution || getResolutionOfUrl(url),\n alphaMode: asset.data?.alphaMode || await detectVideoAlphaMode(),\n ...asset.data,\n };\n\n // --- Create and configure HTMLVideoElement ---\n const videoElement = document.createElement('video');\n\n // Set attributes based on options\n const attributeMap = {\n preload: options.autoLoad !== false ? 'auto' : undefined,\n 'webkit-playsinline': options.playsinline !== false ? '' : undefined,\n playsinline: options.playsinline !== false ? '' : undefined,\n muted: options.muted === true ? '' : undefined,\n loop: options.loop === true ? '' : undefined,\n autoplay: options.autoPlay !== false ? '' : undefined\n };\n\n Object.keys(attributeMap).forEach((key) =>\n {\n const value = attributeMap[key as keyof typeof attributeMap];\n\n if (value !== undefined) videoElement.setAttribute(key, value);\n });\n\n if (options.muted === true)\n {\n videoElement.muted = true;\n }\n\n crossOrigin(videoElement, url, options.crossorigin); // Assume crossOrigin is globally available\n\n // --- Set up source and MIME type ---\n const sourceElement = document.createElement('source');\n\n // Determine MIME type\n let mime: string | undefined;\n\n if (options.mime)\n {\n mime = options.mime;\n }\n else if (url.startsWith('data:'))\n {\n mime = url.slice(5, url.indexOf(';'));\n }\n else if (!url.startsWith('blob:'))\n {\n const ext = url.split('?')[0].slice(url.lastIndexOf('.') + 1).toLowerCase();\n\n mime = VideoSource.MIME_TYPES[ext] || `video/${ext}`;\n }\n\n sourceElement.src = url;\n\n if (mime)\n {\n sourceElement.type = mime;\n }\n\n // this promise will make sure that video is ready to play - as in we have a valid width, height and it can be\n // uploaded to the GPU. Our textures are kind of dumb now, and don't want to handle resizing right now.\n return new Promise((resolve, reject) =>\n {\n if (options.preload && !options.autoPlay)\n {\n videoElement.load();\n }\n\n videoElement.addEventListener('canplay', onCanPlay);\n videoElement.addEventListener('error', onError);\n sourceElement.addEventListener('error', onError);\n videoElement.appendChild(sourceElement);\n\n async function onCanPlay()\n {\n const base = new VideoSource({ ...options, resource: videoElement });\n\n cleanup();\n\n if (asset.data.preload)\n {\n await preloadVideo(videoElement);\n }\n\n resolve(createTexture(base, loader, url));\n }\n\n function onError(event: Event | ErrorEvent)\n {\n cleanup();\n reject(event);\n }\n\n function cleanup()\n {\n videoElement.removeEventListener('canplay', onCanPlay);\n videoElement.removeEventListener('error', onError);\n sourceElement.removeEventListener('error', onError);\n }\n });\n },\n\n unload(texture: Texture): void\n {\n texture.destroy(true);\n }\n} satisfies LoaderParser<Texture, LoadVideoData>;\n"],"names":[],"mappings":"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"}