UNPKG

@photo-sphere-viewer/equirectangular-video-adapter

Version:
1 lines 11.9 kB
{"version":3,"sources":["src/index.ts","src/EquirectangularVideoAdapter.ts","../shared/AbstractVideoAdapter.ts","../shared/video-utils.ts"],"sourcesContent":["export { EquirectangularVideoAdapter } from './EquirectangularVideoAdapter';\nexport * from './model';\n","import type { PanoData, PanoramaPosition, Position, TextureData, Viewer } from '@photo-sphere-viewer/core';\nimport { EquirectangularAdapter, utils } from '@photo-sphere-viewer/core';\nimport { Mesh, MeshBasicMaterial, SphereGeometry, VideoTexture } from 'three';\nimport { AbstractVideoAdapter } from '../../shared/AbstractVideoAdapter';\nimport { EquirectangularVideoAdapterConfig, EquirectangularVideoPanorama } from './model';\n\ntype EquirectangularVideoMesh = Mesh<SphereGeometry, MeshBasicMaterial>;\ntype EquirectangularVideoTextureData = TextureData<VideoTexture, EquirectangularVideoPanorama, PanoData>;\n\nconst getConfig = utils.getConfigParser<EquirectangularVideoAdapterConfig>({\n resolution: 64,\n autoplay: false,\n muted: false,\n});\n\n/**\n * Adapter for equirectangular videos\n */\nexport class EquirectangularVideoAdapter extends AbstractVideoAdapter<\n EquirectangularVideoPanorama,\n PanoData,\n EquirectangularVideoMesh\n> {\n static override readonly id = 'equirectangular-video';\n static override readonly VERSION = PKG_VERSION;\n\n protected override readonly config: EquirectangularVideoAdapterConfig;\n\n private adapter: EquirectangularAdapter;\n\n constructor(viewer: Viewer, config: EquirectangularVideoAdapterConfig) {\n super(viewer);\n\n this.config = getConfig(config);\n\n this.adapter = new EquirectangularAdapter(this.viewer, {\n resolution: this.config.resolution,\n });\n }\n\n override destroy(): void {\n this.adapter.destroy();\n\n delete this.adapter;\n\n super.destroy();\n }\n\n override textureCoordsToSphericalCoords(point: PanoramaPosition, data: PanoData): Position {\n return this.adapter.textureCoordsToSphericalCoords(point, data);\n }\n\n override sphericalCoordsToTextureCoords(position: Position, data: PanoData): PanoramaPosition {\n return this.adapter.sphericalCoordsToTextureCoords(position, data);\n }\n\n override async loadTexture(\n panorama: EquirectangularVideoPanorama,\n _?: boolean,\n newPanoData?: any,\n ): Promise<EquirectangularVideoTextureData> {\n const { texture } = await super.loadTexture(panorama);\n const video: HTMLVideoElement = texture.image;\n\n if (panorama.data) {\n newPanoData = panorama.data;\n }\n if (typeof newPanoData === 'function') {\n newPanoData = newPanoData(video);\n }\n\n const panoData = utils.mergePanoData(video.videoWidth, video.videoHeight, newPanoData);\n\n return { panorama, texture, panoData };\n }\n\n createMesh(panoData: PanoData): EquirectangularVideoMesh {\n return this.adapter.createMesh(panoData);\n }\n\n setTexture(mesh: EquirectangularVideoMesh, { texture }: EquirectangularVideoTextureData) {\n mesh.material.map = texture;\n\n this.switchVideo(texture);\n }\n}\n","import type { TextureData, Viewer } from '@photo-sphere-viewer/core';\nimport { AbstractAdapter, PSVError } from '@photo-sphere-viewer/core';\nimport { BufferGeometry, Material, Mesh, VideoTexture } from 'three';\nimport { createVideo } from './video-utils';\n\nexport type AbstractVideoPanorama = {\n source: string | MediaStream | HTMLVideoElement;\n};\n\nexport type AbstractVideoAdapterConfig = {\n /**\n * automatically start the video\n * @default false\n */\n autoplay?: boolean;\n /**\n * initially mute the video\n * @default false\n */\n muted?: boolean;\n};\n\ntype AbstractVideoMesh = Mesh<BufferGeometry, Material>;\ntype AbstractVideoTextureData = TextureData<VideoTexture>;\n\n/**\n * Base video adapters class\n */\nexport abstract class AbstractVideoAdapter<\n TPanorama extends AbstractVideoPanorama,\n TData,\n TMesh extends AbstractVideoMesh,\n> extends AbstractAdapter<TPanorama, TData, VideoTexture, TMesh> {\n static override readonly supportsDownload = false;\n\n protected abstract readonly config: AbstractVideoAdapterConfig;\n\n private video: HTMLVideoElement;\n\n constructor(viewer: Viewer) {\n super(viewer);\n }\n\n override init() {\n super.init();\n\n this.viewer.needsContinuousUpdate(true);\n }\n\n override destroy() {\n this.__removeVideo();\n\n super.destroy();\n }\n\n override supportsPreload(): boolean {\n return false;\n }\n\n override supportsTransition(): boolean {\n return false;\n }\n\n async loadTexture(panorama: AbstractVideoPanorama): Promise<AbstractVideoTextureData> {\n if (typeof panorama !== 'object' || !panorama.source) {\n return Promise.reject(new PSVError('Invalid panorama configuration, are you using the right adapter?'));\n }\n\n if (!this.viewer.getPlugin('video')) {\n return Promise.reject(new PSVError('Video adapters require VideoPlugin to be loaded too.'));\n }\n\n const video = panorama.source instanceof HTMLVideoElement\n ? panorama.source\n : createVideo({\n src: panorama.source,\n withCredentials: this.viewer.config.withCredentials(panorama.source as any),\n muted: true,\n autoplay: false,\n });\n\n await this.__videoLoadPromise(video);\n\n const texture = new VideoTexture(video);\n return { panorama, texture };\n }\n\n protected switchVideo(texture: VideoTexture) {\n let currentTime;\n let duration;\n let paused = !this.config.autoplay;\n let muted = this.config.muted;\n let volume = 1;\n if (this.video) {\n ({ currentTime, duration, paused, muted, volume } = this.video);\n }\n\n this.__removeVideo();\n this.video = texture.image;\n\n // keep current time when switching resolution\n if (this.video.duration === duration) {\n this.video.currentTime = currentTime;\n }\n\n // keep volume\n this.video.muted = muted;\n this.video.volume = volume;\n\n // play\n if (!paused) {\n this.video.play();\n }\n }\n\n setTextureOpacity(mesh: TMesh, opacity: number) {\n mesh.material.opacity = opacity;\n mesh.material.transparent = opacity < 1;\n }\n\n disposeTexture({ texture }: AbstractVideoTextureData) {\n texture.dispose();\n }\n\n disposeMesh(mesh: AbstractVideoMesh) {\n mesh.geometry.dispose();\n mesh.material.dispose();\n }\n\n private __removeVideo() {\n if (this.video) {\n this.video.pause();\n this.video.remove();\n delete this.video;\n }\n }\n\n private __videoLoadPromise(video: HTMLVideoElement): Promise<void> {\n return new Promise((resolve, reject) => {\n const onLoaded = () => {\n if (this.video && video.duration === this.video.duration) {\n video.currentTime = this.video.currentTime;\n }\n resolve();\n video.removeEventListener('loadedmetadata', onLoaded);\n };\n\n const onError = (err: ErrorEvent) => {\n reject(err);\n video.removeEventListener('error', onError);\n };\n\n video.addEventListener('loadedmetadata', onLoaded);\n video.addEventListener('error', onError);\n });\n }\n}\n","/**\n * Create a standard video element\n */\nexport function createVideo({\n src,\n withCredentials,\n muted,\n autoplay,\n}: {\n src: string | MediaStream;\n withCredentials: boolean;\n muted: boolean;\n autoplay: boolean;\n}): HTMLVideoElement {\n const video = document.createElement('video');\n video.crossOrigin = withCredentials ? 'use-credentials' : 'anonymous';\n video.loop = true;\n video.playsInline = true;\n video.autoplay = autoplay;\n video.muted = muted;\n video.preload = 'metadata';\n if (src instanceof MediaStream) {\n video.srcObject = src;\n } else {\n video.src = src;\n }\n return video;\n}\n"],"mappings":"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","names":["import_core"]}