From 6ef977be9cd409806cd73068b00642c8ec013334 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 18 Mar 2025 19:14:16 +0530 Subject: [PATCH] Sketch --- web/packages/gallery/services/video.ts | 35 +++++++++++++++++-- web/packages/new/photos/services/file-data.ts | 24 +++++++++++-- .../new/photos/services/ml/ml-data.ts | 4 +-- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/web/packages/gallery/services/video.ts b/web/packages/gallery/services/video.ts index 948e2acffa..a6f908050d 100644 --- a/web/packages/gallery/services/video.ts +++ b/web/packages/gallery/services/video.ts @@ -1,13 +1,42 @@ +import { assertionFailed } from "@/base/assert"; import type { EnteFile } from "@/media/file"; -import { wait } from "@/utils/promise"; +import { FileType } from "@/media/file-type"; +import { fetchFileData } from "@/new/photos/services/file-data"; /** * Return a HLS playlist that can be used to stream playback of thne given video * {@link file}. * - * @param file An {@link EnteFile} of type + * @param file An {@link EnteFile} of type video. + * + * [Note: Video playlist vs 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"). */ export const hlsPlaylistForFile = async (file: EnteFile) => { - await wait(0); + if (file.metadata.fileType != FileType.video) { + assertionFailed(); + return undefined; + } + + const encryptedHLS = await fetchFileData("vid_preview", file.id); + console.log(encryptedHLS); return file.id; }; diff --git a/web/packages/new/photos/services/file-data.ts b/web/packages/new/photos/services/file-data.ts index c7367ccbea..0940e7dd5d 100644 --- a/web/packages/new/photos/services/file-data.ts +++ b/web/packages/new/photos/services/file-data.ts @@ -18,7 +18,9 @@ import { z } from "zod"; * There are specialized APIs for fetching and uploading the originals and the * thumbnails. But for the other associated data, we can use the file data APIs. */ -type FileDataType = "mldata" /* See: [Note: "mldata" format] */; +type FileDataType = + | "mldata" /* See: [Note: "mldata" format] */ + | "vid_preview" /* See: [Note: Video playlist vs preview] */; const RemoteFileData = z.object({ /** @@ -61,7 +63,7 @@ type RemoteFileData = z.infer; * payload, but we don't parse that information currently since the higher * levels of our code that use this function handle such rare skips gracefully. */ -export const fetchFileData = async ( +export const fetchFilesData = async ( type: FileDataType, fileIDs: number[], ): Promise => { @@ -75,6 +77,24 @@ export const fetchFileData = async ( .data; }; +/** + * A variant of {@link fetchFilesData} that fetches data for a single file. + * + * Unlike {@link fetchFilesData}, this uses a HTTP GET request. + */ +export const fetchFileData = async ( + type: FileDataType, + fileID: number, +): Promise => { + const params = new URLSearchParams({ type, fileID: fileID.toString() }); + const url = await apiURL("/files/data/fetch"); + const res = await fetch(`${url}?${params.toString()}`, { + headers: await authenticatedRequestHeaders(), + }); + ensureOk(res); + return z.object({ data: RemoteFileData }).parse(await res.json()).data; +}; + /** * Upload file data associated with the given file to remote. * diff --git a/web/packages/new/photos/services/ml/ml-data.ts b/web/packages/new/photos/services/ml/ml-data.ts index fc6313a25f..58a3d52dd0 100644 --- a/web/packages/new/photos/services/ml/ml-data.ts +++ b/web/packages/new/photos/services/ml/ml-data.ts @@ -4,7 +4,7 @@ import type { EnteFile } from "@/media/file"; import { nullToUndefined } from "@/utils/transform"; import { z } from "zod"; import { gunzip, gzip } from "../../utils/gzip"; -import { fetchFileData, putFileData } from "../file-data"; +import { fetchFilesData, putFileData } from "../file-data"; import { type RemoteCLIPIndex } from "./clip"; import { type RemoteFaceIndex } from "./face"; @@ -153,7 +153,7 @@ const ParsedRemoteMLData = z.object({ export const fetchMLData = async ( filesByID: Map, ): Promise> => { - const remoteFileDatas = await fetchFileData("mldata", [ + const remoteFileDatas = await fetchFilesData("mldata", [ ...filesByID.keys(), ]);