This commit is contained in:
Manav Rathi 2024-05-13 16:18:03 +05:30
parent c76b2f0794
commit 3c7c14e11c
No known key found for this signature in database
3 changed files with 45 additions and 59 deletions

View file

@ -114,47 +114,26 @@ const ffmpegBinaryPath = () => {
* handle the MP4 conversion of large video files.
*
* See: [Note: Convert to MP4]
*
* @param command
* @param dataOrPathOrZipItem
* @param outputFileExtension
* @param timeoutMS
* @returns
* @param inputFilePath The path to a file on the user's local file system. This
* is the video we want to convert.
* @param inputFilePath The path to a file on the user's local file system where
* we should write the converted MP4 video.
*/
export const ffmpegConvertToMP4 = async (
command: string[],
dataOrPathOrZipItem: Uint8Array | string | ZipItem,
outputFileExtension: string,
timeoutMS: number,
): Promise<Uint8Array> => {
// TODO (MR): This currently copies files for both input (when
// dataOrPathOrZipItem is data) and output. This needs to be tested
// extremely large video files when invoked downstream of `convertToMP4` in
// the web code.
inputFilePath: string,
outputFilePath: string,
): Promise<void> => {
const command = [
ffmpegPathPlaceholder,
"-i",
inputPathPlaceholder,
"-preset",
"ultrafast",
outputPathPlaceholder,
];
const {
path: inputFilePath,
isFileTemporary: isInputFileTemporary,
writeToTemporaryFile: writeToTemporaryInputFile,
} = await makeFileForDataOrPathOrZipItem(dataOrPathOrZipItem);
const cmd = substitutePlaceholders(command, inputFilePath, outputFilePath);
const outputFilePath = await makeTempFilePath(outputFileExtension);
try {
await writeToTemporaryInputFile();
const cmd = substitutePlaceholders(
command,
inputFilePath,
outputFilePath,
);
if (timeoutMS) await withTimeout(execAsync(cmd), timeoutMS);
else await execAsync(cmd);
return fs.readFile(outputFilePath);
} finally {
if (isInputFileTemporary)
await deleteTempFileIgnoringErrors(inputFilePath);
await deleteTempFileIgnoringErrors(outputFilePath);
}
await withTimeout(execAsync(cmd), 30 * 1000);
};

View file

@ -10,6 +10,7 @@ import { Readable } from "node:stream";
import { ReadableStream } from "node:stream/web";
import { pathToFileURL } from "node:url";
import log from "./log";
import { ffmpegConvertToMP4 } from "./services/ffmpeg";
import { ensure } from "./utils/common";
import {
deleteTempFile,
@ -158,7 +159,7 @@ const handleWrite = async (path: string, request: Request) => {
*
* The returned promise resolves when the write completes.
*
* @param filePath The local filesystem path where the file should be written.
* @param filePath The local file system path where the file should be written.
*
* @param readableStream A web
* [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).
@ -233,9 +234,9 @@ const handleConvertToMP4Write = async (request: Request) => {
const inputTempFilePath = await makeTempFilePath();
await writeStream(inputTempFilePath, ensure(request.body));
const outputTempFilePath = await makeTempFilePath();
const outputTempFilePath = await makeTempFilePath("mp4");
try {
//
await ffmpegConvertToMP4(inputTempFilePath, outputTempFilePath);
} catch (e) {
await deleteTempFileIgnoringErrors(inputTempFilePath);
await deleteTempFileIgnoringErrors(outputTempFilePath);

View file

@ -98,8 +98,8 @@ const makeGenThumbnailCommand = (seekTime: number) => [
* of videos that the user is uploading.
*
* @param uploadItem A {@link File}, or the absolute path to a file on the
* user's local filesytem. A path can only be provided when we're running in the
* context of our desktop app.
* user's local file sytem. A path can only be provided when we're running in
* the context of our desktop app.
*/
export const extractVideoMetadata = async (
uploadItem: UploadItem,
@ -234,22 +234,28 @@ const ffmpegExecWeb = async (
*
* @param blob The video blob.
*
* @returns The mp4 video data.
* @returns The mp4 video blob.
*/
export const convertToMP4 = async (blob: Blob) =>
ffmpegExecNativeOrWeb(
[
ffmpegPathPlaceholder,
"-i",
inputPathPlaceholder,
"-preset",
"ultrafast",
outputPathPlaceholder,
],
blob,
"mp4",
30 * 1000,
);
export const convertToMP4 = async (blob: Blob) => {
const electron = globalThis.electron;
if (electron) {
//
} else {
return ffmpegExecWeb(
[
ffmpegPathPlaceholder,
"-i",
inputPathPlaceholder,
"-preset",
"ultrafast",
outputPathPlaceholder,
],
blob,
"mp4",
30 * 1000,
);
}
};
/**
* Run the given FFmpeg command using a native FFmpeg binary when we're running