Kaynağa Gözat

Desktop side

Manav Rathi 1 yıl önce
ebeveyn
işleme
4461775283

+ 2 - 3
desktop/src/main/ipc.ts

@@ -156,10 +156,9 @@ export const attachIPCHandlers = () => {
         (
             _,
             command: string[],
-            inputDataOrPath: Uint8Array | string,
-            outputFileName: string,
+            dataOrPath: Uint8Array | string,
             timeoutMS: number,
-        ) => ffmpegExec(command, inputDataOrPath, outputFileName, timeoutMS),
+        ) => ffmpegExec(command, dataOrPath, timeoutMS),
     );
 
     // - ML

+ 2 - 2
desktop/src/main/services/convert.ts

@@ -14,7 +14,7 @@ export const convertToJPEG = async (
     imageData: Uint8Array,
 ): Promise<Uint8Array> => {
     const inputFilePath = await makeTempFilePath(fileName);
-    const outputFilePath = await makeTempFilePath("output.jpeg");
+    const outputFilePath = await makeTempFilePath(".jpeg");
 
     // Construct the command first, it may throw on NotAvailable on win32.
     const command = convertToJPEGCommand(inputFilePath, outputFilePath);
@@ -150,7 +150,7 @@ async function generateImageThumbnail_(
     let tempOutputFilePath: string;
     let quality = MAX_QUALITY;
     try {
-        tempOutputFilePath = await makeTempFilePath("thumb.jpeg");
+        tempOutputFilePath = await makeTempFilePath(".jpeg");
         let thumbnail: Uint8Array;
         do {
             await execAsync(

+ 6 - 7
desktop/src/main/services/ffmpeg.ts

@@ -37,8 +37,7 @@ const outputPathPlaceholder = "OUTPUT";
  */
 export const ffmpegExec = async (
     command: string[],
-    inputDataOrPath: Uint8Array | string,
-    outputFileName: string,
+    dataOrPath: Uint8Array | string,
     timeoutMS: number,
 ): Promise<Uint8Array> => {
     // TODO (MR): This currently copies files for both input and output. This
@@ -47,18 +46,18 @@ export const ffmpegExec = async (
 
     let inputFilePath: string;
     let isInputFileTemporary: boolean;
-    if (typeof inputDataOrPath == "string") {
-        inputFilePath = inputDataOrPath;
+    if (typeof dataOrPath == "string") {
+        inputFilePath = dataOrPath;
         isInputFileTemporary = false;
     } else {
-        inputFilePath = await makeTempFilePath("input" /* arbitrary */);
+        inputFilePath = await makeTempFilePath(".in");
         isInputFileTemporary = true;
-        await fs.writeFile(inputFilePath, inputDataOrPath);
+        await fs.writeFile(inputFilePath, dataOrPath);
     }
 
     let outputFilePath: string | undefined;
     try {
-        outputFilePath = await makeTempFilePath(outputFileName);
+        outputFilePath = await makeTempFilePath(".out");
 
         const cmd = substitutePlaceholders(
             command,

+ 1 - 1
desktop/src/main/services/ml-clip.ts

@@ -20,7 +20,7 @@ const cachedCLIPImageSession = makeCachedInferenceSession(
 );
 
 export const clipImageEmbedding = async (jpegImageData: Uint8Array) => {
-    const tempFilePath = await makeTempFilePath("");
+    const tempFilePath = await makeTempFilePath();
     const imageStream = new Response(jpegImageData.buffer).body;
     await writeStream(tempFilePath, imageStream);
     try {

+ 7 - 6
desktop/src/main/utils-temp.ts

@@ -25,20 +25,21 @@ const randomPrefix = () => {
 };
 
 /**
- * Return the path to a temporary file with the given {@link formatSuffix}.
+ * Return the path to a temporary file with the given {@link suffix}.
  *
  * The function returns the path to a file in the system temp directory (in an
- * Ente specific folder therin) with a random prefix and the given
- * {@link formatSuffix}. It ensures that there is no existing file with the same
- * name already.
+ * Ente specific folder therin) with a random prefix and an (optional)
+ * {@link suffix}.
+ *
+ * It ensures that there is no existing file with the same name already.
  *
  * Use {@link deleteTempFile} to remove this file when you're done.
  */
-export const makeTempFilePath = async (formatSuffix: string) => {
+export const makeTempFilePath = async (suffix?: string) => {
     const tempDir = await enteTempDirPath();
     let result: string;
     do {
-        result = path.join(tempDir, randomPrefix() + "-" + formatSuffix);
+        result = path.join(tempDir, `${randomPrefix()}${suffix ?? ""}`);
     } while (existsSync(result));
     return result;
 };

+ 2 - 9
desktop/src/preload.ts

@@ -144,17 +144,10 @@ const generateImageThumbnail = (
 
 const ffmpegExec = (
     command: string[],
-    inputDataOrPath: Uint8Array | string,
-    outputFileName: string,
+    dataOrPath: Uint8Array | string,
     timeoutMS: number,
 ): Promise<Uint8Array> =>
-    ipcRenderer.invoke(
-        "ffmpegExec",
-        command,
-        inputDataOrPath,
-        outputFileName,
-        timeoutMS,
-    );
+    ipcRenderer.invoke("ffmpegExec", command, dataOrPath, timeoutMS);
 
 // - ML
 

+ 12 - 15
web/apps/photos/src/services/ffmpeg.ts

@@ -36,7 +36,6 @@ export const generateVideoThumbnail = async (blob: Blob) => {
                 outputPathPlaceholder,
             ],
             blob,
-            "thumb.jpeg",
         );
 
     try {
@@ -161,27 +160,25 @@ export async function convertToMP4(file: File) {
  * Run the given FFmpeg command.
  *
  * If we're running in the context of our desktop app, use the FFmpeg binary we
- * bundle with our desktop app to run the command. Otherwise fallback to using
- * the wasm FFmpeg we link to from our web app in a web worker.
+ * bundle with our desktop app to run the command. Otherwise fallback to using a
+ * wasm FFmpeg in a web worker.
  *
- * As a rough ballpark, the native FFmpeg integration in the desktop app is
- * 10-20x faster than the wasm one currently. See: [Note: FFmpeg in Electron].
+ * As a rough ballpark, currently the native FFmpeg integration in the desktop
+ * app is 10-20x faster than the wasm one. See: [Note: FFmpeg in Electron].
  */
 const ffmpegExec = async (
     command: string[],
     blob: Blob,
-    outputFileName: string,
     timeoutMs: number = 0,
-): Promise<Uint8Array> => {
+) => {
     const electron = globalThis.electron;
-    if (electron)
-        return electron.ffmpegExec(command, blob, outputFileName, timeoutMs);
-    else
-        return workerFactory
-            .lazy()
-            .then((worker) =>
-                worker.exec(command, blob, outputFileName, timeoutMs),
-            );
+    if (electron) {
+        const data = new Uint8Array(await blob.arrayBuffer());
+        return await electron.ffmpegExec(command, data, timeoutMs);
+    } else {
+        const worker = await workerFactory.lazy()
+        return await worker.exec(command, blob, timeoutMs);
+    }
 };
 
 const ffmpegExec2 = async (

+ 10 - 15
web/packages/next/types/ipc.ts

@@ -237,11 +237,11 @@ export interface Electron {
     ) => Promise<Uint8Array>;
 
     /**
-     * Execute a ffmpeg {@link command}.
+     * Execute a FFmpeg {@link command} on the given {@link dataOrPath}.
      *
-     * This executes the command using the ffmpeg executable we bundle with our
-     * desktop app. There is also a ffmpeg wasm implementation that we use when
-     * running on the web, it also has a sibling function with the same
+     * This executes the command using a FFmpeg executable we bundle with our
+     * desktop app. We also have a wasm FFmpeg wasm implementation that we use
+     * when running on the web, which has a sibling function with the same
      * parameters. See [Note: ffmpeg in Electron].
      *
      * @param command An array of strings, each representing one positional
@@ -250,25 +250,20 @@ export interface Electron {
      * (respectively {@link inputPathPlaceholder},
      * {@link outputPathPlaceholder}, {@link ffmpegPathPlaceholder}).
      *
-     * @param inputDataOrPath The bytes of the input file, or the path to the
-     * input file on the user's local disk. In both cases, the data gets
-     * serialized to a temporary file, and then that path gets substituted in
-     * the ffmpeg {@link command} by {@link inputPathPlaceholder}.
-     *
-     * @param outputFileName The name of the file we instruct ffmpeg to produce
-     * when giving it the given {@link command}. The contents of this file get
-     * returned as the result.
+     * @param dataOrPath The bytes of the input file, or the path to the input
+     * file on the user's local disk. In both 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 timeoutMS If non-zero, then abort and throw a timeout error if the
      * ffmpeg command takes more than the given number of milliseconds.
      *
      * @returns The contents of the output file produced by the ffmpeg command
-     * at {@link outputFileName}.
+     * (specified as {@link outputPathPlaceholder} in {@link command}).
      */
     ffmpegExec: (
         command: string[],
-        inputDataOrPath: Uint8Array | string,
-        outputFileName: string,
+        dataOrPath: Uint8Array | string,
         timeoutMS: number,
     ) => Promise<Uint8Array>;