From 2d245ea8e46c19ddd7dfdbf52987bb346c8f8a4a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 24 Mar 2025 15:36:30 +0530 Subject: [PATCH] URL --- web/packages/gallery/services/file-data.ts | 55 +++++++++++++++++++++- web/packages/gallery/services/video.ts | 32 ++++--------- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/web/packages/gallery/services/file-data.ts b/web/packages/gallery/services/file-data.ts index 724db99a73..d9444474fe 100644 --- a/web/packages/gallery/services/file-data.ts +++ b/web/packages/gallery/services/file-data.ts @@ -82,7 +82,9 @@ export const fetchFilesData = async ( * * Unlike {@link fetchFilesData}, this uses a HTTP GET request. * - * Returns `undefined` if no video preview has been generated for this file yet. + * Returns `undefined` if no file data of the given type has been uploaded for + * this file yet (e.g. if type was "vid_preview", this would indicate that a + * video preview has been generated for this file yet). */ export const fetchFileData = async ( type: FileDataType, @@ -134,3 +136,54 @@ export const putFileData = async ( }); ensureOk(res); }; + +/** + * Fetch the preview file data the given file. + * + * @param type The {@link FileDataType} which we want. + * + * @param fileIDs The id of the files for which we want the file preview data. + * + * @returns the (presigned) URL to the preview data, or undefined if there is + * not preview data of the given type for the given file yet. + * + * [Note: File data vs file preview data] + * + * In museum's ontology, there is a distinction between two concepts: + * + * S3 metadata (museum term, the APIs call it "file data") is data that museum + * uploads on behalf of the client. e.g., + * + * - ML data. + * + * - Preview video playlist. + * + * S3 file data (museum term, the APIs call it "file preview data") is data that + * a client itself uploads. e.g., + * + * - The preview video itself. + * + * - Additional preview images. + * + * [Note: Video playlist and preview] + * + * For a streaming video, both these concepts are needed: + * + * - The encrypted HLS playlist is stored as "file data" of type "vid_preview", + * + * - The encrypted video chunks that the playlist refers to are stored as "file + * preview data" of type "vid_preview". + */ +export const fetchFilePreviewData = async ( + type: FileDataType, + fileID: number, +): Promise => { + const params = new URLSearchParams({ type, fileID: fileID.toString() }); + const url = await apiURL("/files/data/preview"); + const res = await fetch(`${url}?${params.toString()}`, { + headers: await authenticatedRequestHeaders(), + }); + if (res.status == 404) return undefined; + ensureOk(res); + return z.object({ url: z.string() }).parse(await res.json()).url; +}; diff --git a/web/packages/gallery/services/video.ts b/web/packages/gallery/services/video.ts index a20538345e..a0be8b45ed 100644 --- a/web/packages/gallery/services/video.ts +++ b/web/packages/gallery/services/video.ts @@ -6,7 +6,7 @@ import { FileType } from "@/media/file-type"; import { gunzip } from "@/new/photos/utils/gzip"; import { ensurePrecondition } from "@/utils/ensure"; import { z } from "zod"; -import { fetchFileData } from "./file-data"; +import { fetchFileData, fetchFilePreviewData } from "./file-data"; /** * Return a HLS playlist that can be used to stream playback of thne given video @@ -17,26 +17,7 @@ import { fetchFileData } from "./file-data"; * @returns The HLS playlist as a string, or `undefined` if there is no video * preview associated with the given file. * - * [Note: Video playlist and preview] - * - * In museum's ontology, there is a distinction between two concepts: - * - * S3 metadata is the data that museum uploads (on behalf of the client): - * - ML data. - * - Preview video playlist. - * - * S3 file data is the data that client uploads: - * - Preview video itself. - * - Additional preview images. - * - * Because of this separation, there are separate code paths dealing with the - * two parts we need to play streaming video: - * - * - The encrypted HLS playlist (which is stored as file data of type - * "vid_preview"), - * - * - And the encrypted video chunks that it (the playlist) refers to (which are - * stored as file preview data of type "vid_preview"). + * See: [Note: Video playlist and preview] */ export const hlsPlaylistForFile = async (file: EnteFile) => { ensurePrecondition(file.metadata.fileType == FileType.video); @@ -44,11 +25,17 @@ export const hlsPlaylistForFile = async (file: EnteFile) => { const playlistFileData = await fetchFileData("vid_preview", file.id); if (!playlistFileData) return undefined; + const videoURL = await fetchFilePreviewData("vid_preview", file.id); + if (!videoURL) return undefined; + // See: [Note: strict mode migration] // // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - const { playlist } = await decryptPlaylistJSON(playlistFileData, file); + const { playlist: playlistTemplate } = await decryptPlaylistJSON( + playlistFileData, + file, + ); // [Note: HLS playlist format] // @@ -102,6 +89,7 @@ export const hlsPlaylistForFile = async (file: EnteFile) => { // (AES-128 for us), URI and IV attributes. The URI attribute value is a // quoted string containing a URI that specfies how to obtain the key. + const playlist = playlistTemplate.replaceAll("output.ts", videoURL); log.debug(() => ["hlsPlaylistForFile", playlist]); return file.id; };