feat(web): support 360 video (equirectangular) (#8762)

* [web]: support 360 video

* lint

* lint

* fix typing

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
TruongSinh Tran-Nguyen 2024-04-21 12:14:54 -07:00 committed by GitHub
parent f004487be0
commit 0d3cc28f45
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 80 additions and 10 deletions

View file

@ -1,22 +1,39 @@
<script lang="ts">
import { serveFile, type AssetResponseDto } from '@immich/sdk';
import { serveFile, type AssetResponseDto, AssetTypeEnum } from '@immich/sdk';
import { fade } from 'svelte/transition';
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
import { getKey } from '$lib/utils';
export let asset: AssetResponseDto;
import type { AdapterConstructor, PluginConstructor } from '@photo-sphere-viewer/core';
export let asset: Pick<AssetResponseDto, 'id' | 'type'>;
const photoSphereConfigs =
asset.type === AssetTypeEnum.Video
? ([
import('@photo-sphere-viewer/equirectangular-video-adapter').then(
({ EquirectangularVideoAdapter }) => EquirectangularVideoAdapter,
),
import('@photo-sphere-viewer/video-plugin').then(({ VideoPlugin }) => [VideoPlugin]),
true,
import('@photo-sphere-viewer/video-plugin/index.css'),
] as [PromiseLike<AdapterConstructor>, Promise<PluginConstructor[]>, true, unknown])
: ([undefined, [], false] as [undefined, [], false]);
const loadAssetData = async () => {
const data = await serveFile({ id: asset.id, isWeb: false, isThumb: false, key: getKey() });
return URL.createObjectURL(data);
const url = URL.createObjectURL(data);
if (asset.type === AssetTypeEnum.Video) {
return { source: url };
}
return url;
};
</script>
<div transition:fade={{ duration: 150 }} class="flex h-full select-none place-content-center place-items-center">
<!-- the photo sphere viewer is quite large, so lazy load it in parallel with loading the data -->
{#await Promise.all([loadAssetData(), import('./photo-sphere-viewer-adapter.svelte')])}
{#await Promise.all([loadAssetData(), import('./photo-sphere-viewer-adapter.svelte'), ...photoSphereConfigs])}
<LoadingSpinner />
{:then [data, module]}
<svelte:component this={module.default} panorama={data} />
{:then [data, module, adapter, plugins, navbar]}
<svelte:component this={module.default} panorama={data} plugins={plugins ?? undefined} {navbar} {adapter} />
{:catch}
Failed to load asset
{/await}