convert to mp4
This commit is contained in:
parent
7179b0a603
commit
42b0b6e9bb
3 changed files with 43 additions and 67 deletions
|
@ -10,7 +10,7 @@ import { Events, eventBus } from "@ente/shared/events";
|
|||
import { isPlaybackPossible } from "@ente/shared/media/video-playback";
|
||||
import { Remote } from "comlink";
|
||||
import isElectron from "is-electron";
|
||||
import * as ffmpegService from "services/ffmpeg";
|
||||
import * as ffmpeg from "services/ffmpeg";
|
||||
import { EnteFile } from "types/file";
|
||||
import { generateStreamFromArrayBuffer, getRenderableImage } from "utils/file";
|
||||
import { PhotosDownloadClient } from "./clients/photos";
|
||||
|
@ -610,17 +610,13 @@ async function getPlayableVideo(
|
|||
if (!forceConvert && !runOnWeb && !isElectron()) {
|
||||
return null;
|
||||
}
|
||||
log.info(
|
||||
`video format not supported, converting it name: ${videoNameTitle}`,
|
||||
);
|
||||
const mp4ConvertedVideo = await ffmpegService.convertToMP4(
|
||||
new File([videoBlob], videoNameTitle),
|
||||
);
|
||||
log.info(`video successfully converted ${videoNameTitle}`);
|
||||
return new Blob([mp4ConvertedVideo]);
|
||||
// TODO(MR): This might not work for very large (~ GB) videos. Test.
|
||||
log.info(`Converting video ${videoNameTitle} to mp4`);
|
||||
const convertedVideoData = await ffmpeg.convertToMP4(videoBlob);
|
||||
return new Blob([convertedVideoData]);
|
||||
}
|
||||
} catch (e) {
|
||||
log.error("video conversion failed", e);
|
||||
log.error("Video conversion failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { ElectronFile } from "@/next/types/file";
|
||||
import type { Electron } from "@/next/types/ipc";
|
||||
import { ComlinkWorker } from "@/next/worker/comlink-worker";
|
||||
import { validateAndGetCreationUnixTimeInMicroSeconds } from "@ente/shared/time";
|
||||
|
@ -200,23 +199,6 @@ function parseCreationTime(creationTime: string) {
|
|||
return dateTime;
|
||||
}
|
||||
|
||||
/** Called when viewing a file */
|
||||
export async function convertToMP4(file: File) {
|
||||
return await ffmpegExec2(
|
||||
[
|
||||
ffmpegPathPlaceholder,
|
||||
"-i",
|
||||
inputPathPlaceholder,
|
||||
"-preset",
|
||||
"ultrafast",
|
||||
outputPathPlaceholder,
|
||||
],
|
||||
file,
|
||||
"mp4",
|
||||
30 * 1000,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given FFmpeg command using a wasm FFmpeg running in a web worker.
|
||||
*
|
||||
|
@ -234,55 +216,53 @@ const ffmpegExecWeb = async (
|
|||
};
|
||||
|
||||
/**
|
||||
* Run the given FFmpeg command using a native FFmpeg binary bundled with our
|
||||
* desktop app.
|
||||
* Convert a video from a format that is not supported in the browser to MP4.
|
||||
*
|
||||
* This function is called when the user views a video or a live photo, and we
|
||||
* want to play it back. The idea is to convert it to MP4 which has much more
|
||||
* universal support in browsers.
|
||||
*
|
||||
* @param blob The video blob.
|
||||
*
|
||||
* @returns The mp4 video data.
|
||||
*/
|
||||
export const convertToMP4 = async (blob: Blob) =>
|
||||
ffmpegExecNativeOrWeb(
|
||||
[
|
||||
ffmpegPathPlaceholder,
|
||||
"-i",
|
||||
inputPathPlaceholder,
|
||||
"-preset",
|
||||
"ultrafast",
|
||||
outputPathPlaceholder,
|
||||
],
|
||||
blob,
|
||||
"mp4",
|
||||
30 * 1000,
|
||||
);
|
||||
|
||||
/**
|
||||
* Run the given FFmpeg command using a native FFmpeg binary when we're running
|
||||
* in the context of our desktop app, otherwise using the browser based wasm
|
||||
* FFmpeg implemenation.
|
||||
*
|
||||
* See also: {@link ffmpegExecWeb}.
|
||||
*/
|
||||
/*
|
||||
TODO(MR): Remove me
|
||||
const ffmpegExecNative = async (
|
||||
electron: Electron,
|
||||
const ffmpegExecNativeOrWeb = async (
|
||||
command: string[],
|
||||
blob: Blob,
|
||||
timeoutMs: number = 0,
|
||||
) => {
|
||||
const electron = globalThis.electron;
|
||||
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 (
|
||||
command: string[],
|
||||
inputFile: File | ElectronFile,
|
||||
outputFileExtension: string,
|
||||
timeoutMS: number = 0,
|
||||
timeoutMs: number,
|
||||
) => {
|
||||
const electron = globalThis.electron;
|
||||
if (electron || false) {
|
||||
throw new Error("WIP");
|
||||
// return electron.ffmpegExec(
|
||||
// command,
|
||||
// /* TODO(MR): ElectronFile changes */
|
||||
// inputFile as unknown as string,
|
||||
// outputFileName,
|
||||
// timeoutMS,
|
||||
// );
|
||||
} else {
|
||||
/* TODO(MR): ElectronFile changes */
|
||||
return ffmpegExecWeb(
|
||||
if (electron)
|
||||
return electron.ffmpegExec(
|
||||
command,
|
||||
inputFile as File,
|
||||
new Uint8Array(await blob.arrayBuffer()),
|
||||
outputFileExtension,
|
||||
timeoutMS,
|
||||
timeoutMs,
|
||||
);
|
||||
}
|
||||
else return ffmpegExecWeb(command, blob, outputFileExtension, timeoutMs);
|
||||
};
|
||||
|
||||
/** Lazily create a singleton instance of our worker */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useCallback, useRef, useState } from "react";
|
||||
|
||||
/*
|
||||
/**
|
||||
* TODO (MR): Understand how this is happening, and validate it further (on
|
||||
* first glance this is correct).
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue