From 33a86cecbdf7d096fe885b88af2a39545aeec951 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Thu, 24 Aug 2023 15:59:46 +0200 Subject: [PATCH] support multiple files at once (#3) --- src/main.ts | 12 ++++-- src/preload.ts | 4 +- src/scripts/renderer.ts | 86 ++++++++++++++++++++++++++++------------- tsconfig.json | 1 + 4 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/main.ts b/src/main.ts index e057cfd..68597e0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -41,11 +41,11 @@ const createWindow = () => { app.whenReady().then(() => { const win = createWindow(); - /** Ask user a file */ - const askFile = () => { + /** Ask user files */ + const askFiles = () => { return dialog.showOpenDialogSync(win, { filters: [moviesFilter], - properties: ["openFile", "dontAddToRecent"], + properties: ["openFile", "dontAddToRecent", "multiSelections"], }); }; @@ -54,6 +54,9 @@ app.whenReady().then(() => { await dialog.showMessageBox(win, { message }); }; + /** Get filename of a path */ + const getFilename = (filepath: string) => path.parse(filepath).base; + /** Merge all audios track of a video into one */ const mergeAudio = async (file: string) => { const tmpFile = getNewFilename(file, "TMP_"); @@ -128,7 +131,8 @@ app.whenReady().then(() => { /* Context bridge */ ipcMain.handle("argv", () => process.argv); ipcMain.handle("allowedExtensions", () => moviesFilter); - ipcMain.handle("askFile", () => askFile()); + ipcMain.handle("getFilename", (_, filepath: string) => getFilename(filepath)); + ipcMain.handle("askFiles", () => askFiles()); ipcMain.handle("mergeAudio", (_, file: string) => mergeAudio(file)); ipcMain.handle("reduceSize", (_, file: string, bitrate: number) => reduceSize(file, bitrate) diff --git a/src/preload.ts b/src/preload.ts index c500d92..9e775b4 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -9,7 +9,9 @@ ipcRenderer.on("error", (_, err) => { contextBridge.exposeInMainWorld("internals", { argv: () => ipcRenderer.invoke("argv"), allowedExtensions: () => ipcRenderer.invoke("allowedExtensions"), - askFile: () => ipcRenderer.invoke("askFile"), + getFilename: (filepath: string) => + ipcRenderer.invoke("getFilename", filepath), + askFiles: () => ipcRenderer.invoke("askFiles"), mergeAudio: (file: string) => ipcRenderer.invoke("mergeAudio", file), reduceSize: (file: string, bitrate: number) => ipcRenderer.invoke("reduceSize", file, bitrate), diff --git a/src/scripts/renderer.ts b/src/scripts/renderer.ts index e2de345..7119760 100644 --- a/src/scripts/renderer.ts +++ b/src/scripts/renderer.ts @@ -4,7 +4,8 @@ let internals: { allowedExtensions: () => Promise<{ extensions: string[]; }>; - askFile: () => Promise; + getFilename: (filepath: string) => Promise; + askFiles: () => Promise; exit: () => Promise; mergeAudio: ( filename: string @@ -13,22 +14,30 @@ let internals: { confirmation: (text: string) => Promise; }; -/** Search for a file */ -const getFile = async () => { +/** Search for files */ +const getFiles = async () => { const allowedExtensions = (await internals.allowedExtensions()).extensions; const argv = await internals.argv(); - if (argv.length === 2) { - const file = argv.pop(); - if (allowedExtensions.some((ext) => file.endsWith(ext))) { - return file; + if (argv.length >= 2) { + const files = argv.slice(1); + + // Exit if a file isn't supported in the list + if ( + files.filter((file) => + allowedExtensions.some((ext) => file.endsWith(ext)) + ).length !== files.length + ) { + await internals.exit(); } + + return files; } - const file = await internals.askFile(); - if (file === undefined || file.length === 0) { + const files = await internals.askFiles(); + if (files === undefined || files.length === 0) { await internals.exit(); } - return file.join(""); + return files; }; /** Either replace the message, or add some info */ @@ -63,27 +72,50 @@ const updateMessage = ( /** Main function */ const main = async () => { const maxSizeDiscord = 25; - updateMessage("Récupération du fichier..."); - const file = await getFile(); - updateMessage("Mélange des pistes audios vers la piste 1...", true); - const newFile = await internals.mergeAudio(file); - let finalTitle = newFile.title; - updateMessage(`Taille calculée : ~${Math.round(newFile.size)}Mio`); - if (newFile.size > maxSizeDiscord) { - const targetSize = maxSizeDiscord - 2; // keep some room - - // https://trac.ffmpeg.org/wiki/Encode/H.264#twopass - const bitrate = Math.floor((targetSize * 8388.608) / newFile.duration); + updateMessage("Récupération des fichiers..."); + const files = await getFiles(); + let processedFiles = ""; + // Iterate over all the retrieved files + for (const [idx, file] of files.entries()) { + const counter = `${idx + 1}/${files.length}`; + const filename = await internals.getFilename(file); updateMessage( - `\nFichier trop lourd, compression en cours... (bitrate total = ${bitrate}kbps)`, - true, - Mode.Append + `${counter} - Mélange des pistes audios de ${filename}...`, + true ); - finalTitle = await internals.reduceSize(newFile.title, bitrate); + const newFile = await internals.mergeAudio(file); + let finalTitle = newFile.title; + updateMessage( + `${counter} - Taille calculée : ~${Math.round(newFile.size)}Mio` + ); + + // Compress video if needed + if (newFile.size > maxSizeDiscord) { + const targetSize = maxSizeDiscord - 2; // keep some room + + // https://trac.ffmpeg.org/wiki/Encode/H.264#twopass + const bitrate = Math.floor((targetSize * 8388.608) / newFile.duration); + + updateMessage( + `\nFichier trop lourd, compression en cours... (bitrate total = ${bitrate}kbps)`, + true, + Mode.Append + ); + + // Compress the video and change the title to the new one + finalTitle = await internals.reduceSize(newFile.title, bitrate); + } + + // Append title to the list of processed files + processedFiles += `\n- ${finalTitle}`; + updateMessage(`Fichier ${counter} traités.`); } - updateMessage("Fichier prêt ! :)"); - await internals.confirmation(`File ok @ ${finalTitle}!`); + + // Send confirmation to the user that we're done + await internals.confirmation( + `${files.length} fichiers traités : ${processedFiles}` + ); await internals.exit(); }; main(); diff --git a/tsconfig.json b/tsconfig.json index 4e12aea..3f09603 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "module": "commonjs", + "downlevelIteration": true, "noImplicitAny": true, "sourceMap": true, "outDir": "dist",