support multiple files at once (#3)
This commit is contained in:
parent
53d19bdb74
commit
33a86cecbd
4 changed files with 71 additions and 32 deletions
12
src/main.ts
12
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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"downlevelIteration": true,
|
||||
"noImplicitAny": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
|
|
Loading…
Reference in a new issue