diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 6367e53b2d..36367f9c66 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1586,6 +1586,9 @@ dependencies: highlight.js: specifier: ~11.8.0 version: 11.8.0 + hls.js: + specifier: ^1.5.15 + version: 1.5.15 html-to-text: specifier: ^9.0.3 version: 9.0.5 @@ -15598,6 +15601,10 @@ packages: requiresBuild: true dev: false + /hls.js@1.5.15: + resolution: {integrity: sha512-6cD7xN6bycBHaXz2WyPIaHn/iXFizE5au2yvY5q9aC4wfihxAr16C9fUy4nxh2a3wOw0fEgLRa9dN6wsYjlpNg==} + dev: false + /hogan.js@3.0.2: resolution: {integrity: sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==} hasBin: true @@ -27291,7 +27298,7 @@ packages: dev: false file:projects/lead-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2): - resolution: {integrity: sha512-TJVh5S1o+GvRWeeNWwXveGOpMtsQTR0n5RMGjK3kXsuAUYCQRPzgMh3noJxe2n4vvijK8IUNjAR9+AjeSPo5kw==, tarball: file:projects/lead-resources.tgz} + resolution: {integrity: sha512-xg8Fq55+BYSO+pwIkFTJFDJGPu1CWGB8CiZ64+J2jqzbAHkRaiOCP0u3R4lOw/z6k1tnqhL0m2bvV9pCUCYTHA==, tarball: file:projects/lead-resources.tgz} id: file:projects/lead-resources.tgz name: '@rush-temp/lead-resources' version: 0.0.0 @@ -30482,6 +30489,7 @@ packages: eslint-plugin-promise: 6.1.1(eslint@8.56.0) eslint-plugin-svelte: 2.35.1(eslint@8.56.0)(svelte@4.2.12)(ts-node@10.9.2) fast-equals: 5.0.1 + hls.js: 1.5.15 jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2) png-chunks-extract: 1.0.0 prettier: 3.2.5 @@ -34795,7 +34803,7 @@ packages: dev: false file:projects/tool.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-LwQbmBaSOZ5IKwCHz2mULcIuEr9rZ2b/7tqUGICHCawUzexUlQVxv2Yt0oFf2aZu83Sittt7dZwnN3sXHX9t9g==, tarball: file:projects/tool.tgz} + resolution: {integrity: sha512-sZH5yB7zg/kTpuIhLSqPYh0wFgw4aOpsriMq4wad8ZHRzlHASseyJAbEylIP8ltfPbFFN4Yy1nXaUOXS49anHg==, tarball: file:projects/tool.tgz} id: file:projects/tool.tgz name: '@rush-temp/tool' version: 0.0.0 @@ -35311,7 +35319,7 @@ packages: dev: false file:projects/view-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2): - resolution: {integrity: sha512-l/K7osn3HZ3KIFeCyBe+rxQGUxvLvM+35if2HgylqgbWtD10Gk/rR+vuW1L54o8hT4ADMkbhvBW7VHE19isd+w==, tarball: file:projects/view-resources.tgz} + resolution: {integrity: sha512-g6op8hiY1zLsms7Sab4cAs29Ucbk6r20mx9hkZrhxn70uPW/VCLS+JW67cfWf85SyMwMloWuvY6ujfQfwNuScw==, tarball: file:projects/view-resources.tgz} id: file:projects/view-resources.tgz name: '@rush-temp/view-resources' version: 0.0.0 @@ -35326,6 +35334,7 @@ packages: eslint-plugin-promise: 6.1.1(eslint@8.56.0) eslint-plugin-svelte: 2.35.1(eslint@8.56.0)(svelte@4.2.12)(ts-node@10.9.2) fast-equals: 5.0.1 + hls.js: 1.5.15 jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2) prettier: 3.2.5 prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.12) diff --git a/packages/presentation/src/preview.ts b/packages/presentation/src/preview.ts index 1b5e2e5a1a..814d89b284 100644 --- a/packages/presentation/src/preview.ts +++ b/packages/presentation/src/preview.ts @@ -6,27 +6,56 @@ import { getFileUrl, getCurrentWorkspaceId } from './file' import presentation from './plugin' export interface PreviewConfig { - previewUrl: string + image: string + video: string } -const defaultPreview = (): string => `/files/${getCurrentWorkspaceId()}?file=:blobId&size=:size` +export interface VideoMeta { + status: 'ready' | 'error' | 'inprogress' | 'queued' | 'downloading' | 'pendingupload' + thumbnail: string + hls: string +} + +const defaultImagePreview = (): string => `/files/${getCurrentWorkspaceId()}?file=:blobId&size=:size` /** * * PREVIEW_CONFIG env variable format. - * previewUrl - an Url with :workspace, :blobId, :downloadFile, :size placeholders, they will be replaced in UI with an appropriate blob values. + * - image - an Url with :workspace, :blobId, :downloadFile, :size placeholders. + * - video - an Url with :workspace, :blobId placeholders. */ export function parsePreviewConfig (config?: string): PreviewConfig | undefined { if (config === undefined) { return } - return { previewUrl: config } + + const previewConfig = { image: defaultImagePreview(), video: '' } + + const configs = config.split(';') + for (const c of configs) { + if (c.includes('|')) { + const [key, value] = c.split('|') + if (key === 'image') { + previewConfig.image = value + } else if (key === 'video') { + previewConfig.video = value + } else { + throw new Error(`Unknown preview config key: ${key}`) + } + } else { + // fallback to image-only config for compatibility + previewConfig.image = c + } + } + + return Object.freeze(previewConfig) } export function getPreviewConfig (): PreviewConfig { return ( (getMetadata(presentation.metadata.PreviewConfig) as PreviewConfig) ?? { - previewUrl: defaultPreview() + image: defaultImagePreview(), + video: '' } ) } @@ -58,7 +87,7 @@ function blobToSrcSet (cfg: PreviewConfig, blob: Ref, width: number | unde return '' } - let url = cfg.previewUrl.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId())) + let url = cfg.image.replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId())) const downloadUrl = getFileUrl(blob) const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin @@ -89,3 +118,25 @@ function blobToSrcSet (cfg: PreviewConfig, blob: Ref, width: number | unde export function getFileSrcSet (_blob: Ref, width?: number): string { return blobToSrcSet(getPreviewConfig(), _blob, width) } + +/** + * @public + */ +export async function getVideoMeta (file: string, filename?: string): Promise { + const cfg = getPreviewConfig() + + const url = cfg.video + .replaceAll(':workspace', encodeURIComponent(getCurrentWorkspaceId())) + .replaceAll(':blobId', encodeURIComponent(file)) + + if (url === '') { + return undefined + } + + try { + const response = await fetch(url) + if (response.ok) { + return (await response.json()) as VideoMeta + } + } catch {} +} diff --git a/plugins/view-resources/package.json b/plugins/view-resources/package.json index 5bb9ff4e37..ba3f0a27c8 100644 --- a/plugins/view-resources/package.json +++ b/plugins/view-resources/package.json @@ -57,6 +57,7 @@ "@hcengineering/text-editor-resources": "^0.6.0", "@hcengineering/analytics": "^0.6.0", "@hcengineering/query": "^0.6.12", - "fast-equals": "^5.0.1" + "fast-equals": "^5.0.1", + "hls.js": "^1.5.15" } } diff --git a/plugins/view-resources/src/components/viewer/VideoViewer.svelte b/plugins/view-resources/src/components/viewer/VideoViewer.svelte index e91194496d..fbed991d3f 100644 --- a/plugins/view-resources/src/components/viewer/VideoViewer.svelte +++ b/plugins/view-resources/src/components/viewer/VideoViewer.svelte @@ -14,20 +14,46 @@ --> -