diff --git a/web/packages/base/types/ipc.ts b/web/packages/base/types/ipc.ts index 083cc81037..d44a92e980 100644 --- a/web/packages/base/types/ipc.ts +++ b/web/packages/base/types/ipc.ts @@ -316,10 +316,10 @@ export interface Electron { * The behaviour is OS dependent. On macOS we use the `sips` utility, while * on Linux and Windows we use a `vips` bundled with our desktop app. * - * @param dataOrPathOrZipItem The file whose thumbnail we want to generate. - * It can be provided as raw image data (the contents of the image file), or - * the path to the image file, or a tuple containing the path of the zip - * file along with the name of an entry in it. + * @param pathOrZipItem The file whose thumbnail we want to generate. It can + * be provided as raw image data (the contents of the image file), or the + * path to the image file, or a tuple containing the path of the zip file + * along with the name of an entry in it. * * @param maxDimension The maximum width or height of the generated * thumbnail. @@ -329,14 +329,13 @@ export interface Electron { * @returns JPEG data of the generated thumbnail. */ generateImageThumbnail: ( - dataOrPathOrZipItem: Uint8Array | string | ZipItem, + pathOrZipItem: string | ZipItem, maxDimension: number, maxSize: number, ) => Promise; /** - * Execute a FFmpeg {@link command} on the given - * {@link dataOrPathOrZipItem}. + * Execute a FFmpeg {@link command} on the given {@link pathOrZipItem}. * * This executes the command using a FFmpeg executable we bundle with our * desktop app. We also have a Wasm FFmpeg implementation that we use when @@ -349,11 +348,11 @@ export interface Electron { * (respectively {@link inputPathPlaceholder}, * {@link outputPathPlaceholder}, {@link ffmpegPathPlaceholder}). * - * @param dataOrPathOrZipItem The bytes of the input file, or the path to - * the input file on the user's local disk, or the path to a zip file on the - * user's disk and the name of an entry in it. In all three cases, the data - * gets serialized to a temporary file, and then that path gets substituted - * in the FFmpeg {@link command} in lieu of {@link inputPathPlaceholder}. + * @param pathOrZipItem The path to the input file on the user's local disk, + * or the path to a zip file on the user's disk and the name of an entry in + * it. In the second case, the data gets serialized to a temporary file, and + * then that path (or if it was already a path) gets substituted in the + * FFmpeg {@link command} in lieu of {@link inputPathPlaceholder}. * * @param outputFileExtension The extension (without the dot, e.g. "jpeg") * to use for the output file that we ask FFmpeg to create in @@ -366,10 +365,28 @@ export interface Electron { */ ffmpegExec: ( command: FFmpegCommand, - dataOrPathOrZipItem: Uint8Array | string | ZipItem, + pathOrZipItem: string | ZipItem, outputFileExtension: string, ) => Promise; + /** + * Determine the duration (in seconds) of the video present at + * {@link pathOrZipItem} using ffmpeg. + * + * This is a bespoke variant of {@link ffmpegExec} for the sole purpose of + * retrieving the video duration. + * + * @param pathOrZipItem The input file whose duration we want to determine. + * For more details, see the documentation of the {@link ffmpegExec} + * parameter with the same name. + * + * @returns The duration (in seconds) of the video referred to by + * {@link pathOrZipItem}. + */ + ffmpegDetermineVideoDuration: ( + pathOrZipItem: string | ZipItem, + ) => Promise; + // - Utility process /** diff --git a/web/packages/gallery/services/ffmpeg/index.ts b/web/packages/gallery/services/ffmpeg/index.ts index 2fc5b12a54..b31f92b80d 100644 --- a/web/packages/gallery/services/ffmpeg/index.ts +++ b/web/packages/gallery/services/ffmpeg/index.ts @@ -2,7 +2,7 @@ import { ensureElectron } from "ente-base/electron"; import log from "ente-base/log"; import type { Electron } from "ente-base/types/ipc"; import { - toDataOrPathOrZipEntry, + toPathOrZipEntry, type FileSystemUploadItem, type UploadItem, } from "ente-gallery/services/upload"; @@ -74,7 +74,7 @@ export const generateVideoThumbnailNative = async ( _generateVideoThumbnail((seekTime: number) => electron.ffmpegExec( makeGenThumbnailCommand(seekTime), - toDataOrPathOrZipEntry(fsUploadItem), + toPathOrZipEntry(fsUploadItem), "jpeg", ), ); @@ -137,7 +137,7 @@ export const extractVideoMetadata = async ( ? await ffmpegExecWeb(command, uploadItem, "txt") : await ensureElectron().ffmpegExec( command, - toDataOrPathOrZipEntry(uploadItem), + toPathOrZipEntry(uploadItem), "txt", ), ); @@ -274,10 +274,10 @@ export const determineVideoDuration = async ( uploadItem: UploadItem, ): Promise => uploadItem instanceof File - ? await determineVideoDurationWeb(uploadItem) - : 0; /*, await ensureElectron().ffmpegDetermineVideoDuration( - toDataOrPathOrZipEntry(uploadItem), - ));*/ + ? determineVideoDurationWeb(uploadItem) + : ensureElectron().ffmpegDetermineVideoDuration( + toPathOrZipEntry(uploadItem), + ); /** * Convert a video from a format that is not supported in the browser to MP4. diff --git a/web/packages/gallery/services/upload/index.ts b/web/packages/gallery/services/upload/index.ts index 57c50e5f8c..040fd5d082 100644 --- a/web/packages/gallery/services/upload/index.ts +++ b/web/packages/gallery/services/upload/index.ts @@ -283,7 +283,7 @@ export const fileSystemUploadItemIfUnchanged = async ( * context of our desktop app, return a value that can be passed to * {@link Electron} functions over IPC. */ -export const toDataOrPathOrZipEntry = (fsUploadItem: FileSystemUploadItem) => +export const toPathOrZipEntry = (fsUploadItem: FileSystemUploadItem) => typeof fsUploadItem == "string" || Array.isArray(fsUploadItem) ? fsUploadItem : fsUploadItem.path; diff --git a/web/packages/gallery/services/upload/thumbnail.ts b/web/packages/gallery/services/upload/thumbnail.ts index 49c8b78135..a393397921 100644 --- a/web/packages/gallery/services/upload/thumbnail.ts +++ b/web/packages/gallery/services/upload/thumbnail.ts @@ -2,7 +2,7 @@ import log from "ente-base/log"; import { type Electron } from "ente-base/types/ipc"; import * as ffmpeg from "ente-gallery/services/ffmpeg"; import { - toDataOrPathOrZipEntry, + toPathOrZipEntry, type FileSystemUploadItem, } from "ente-gallery/services/upload"; import { FileType, type FileTypeInfo } from "ente-media/file-type"; @@ -196,7 +196,7 @@ export const generateThumbnailNative = async ( ): Promise => fileTypeInfo.fileType === FileType.image ? await electron.generateImageThumbnail( - toDataOrPathOrZipEntry(fsUploadItem), + toPathOrZipEntry(fsUploadItem), maxThumbnailDimension, maxThumbnailSize, ) diff --git a/web/packages/gallery/services/upload/upload-service.ts b/web/packages/gallery/services/upload/upload-service.ts index 0a6e6f2e7f..0dee402d1a 100644 --- a/web/packages/gallery/services/upload/upload-service.ts +++ b/web/packages/gallery/services/upload/upload-service.ts @@ -1,7 +1,6 @@ // TODO: Audit this file /* eslint-disable @typescript-eslint/ban-ts-comment */ -import { isDesktop } from "ente-base/app"; import { streamEncryptionChunkSize } from "ente-base/crypto/libsodium"; import type { BytesOrB64 } from "ente-base/crypto/types"; import { type CryptoWorker } from "ente-base/crypto/worker"; @@ -1053,10 +1052,10 @@ const extractImageOrVideoMetadata = async ( if ( fileType == FileType.video && // TODO(HLS): - !isDesktop && settingsSnapshot().isInternalUser ) { duration = await tryDetermineVideoDuration(uploadItem); + // TODO(HLS): log.debug(() => ["extracted duration", duration]); }