support multiple files at once (#3)

This commit is contained in:
Mylloon 2023-08-24 15:59:46 +02:00
parent 53d19bdb74
commit 33a86cecbd
Signed by: Anri
GPG key ID: A82D63DFF8D1317F
4 changed files with 71 additions and 32 deletions

View file

@ -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)

View file

@ -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),

View file

@ -4,7 +4,8 @@ let internals: {
allowedExtensions: () => Promise<{
extensions: string[];
}>;
askFile: () => Promise<string[] | undefined>;
getFilename: (filepath: string) => Promise<string>;
askFiles: () => Promise<string[] | undefined>;
exit: () => Promise<void>;
mergeAudio: (
filename: string
@ -13,22 +14,30 @@ let internals: {
confirmation: (text: string) => Promise<void>;
};
/** 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();

View file

@ -1,6 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
"downlevelIteration": true,
"noImplicitAny": true,
"sourceMap": true,
"outDir": "dist",