diff --git a/app/ipcHandlers.js b/app/ipcHandlers.js
index 2e77918..fb70db0 100644
--- a/app/ipcHandlers.js
+++ b/app/ipcHandlers.js
@@ -34,6 +34,7 @@ const FEATURE_WHITELIST = new Set([
"addMetadata",
"verboseLogs",
"autoDownloadPlaylist",
+ "keepPlaylistOrder",
"customCodec",
"theme",
"createPlaylistFolders",
diff --git a/config/config.default.json b/config/config.default.json
index b807dd7..946ddf7 100644
--- a/config/config.default.json
+++ b/config/config.default.json
@@ -7,6 +7,7 @@
"addMetadata": true,
"verboseLogs": false,
"autoDownloadPlaylist": true,
+ "keepPlaylistOrder": false,
"createPlaylistFolders": true,
"customCodec": "h264",
"logSystem": true,
diff --git a/public/index.html b/public/index.html
index 2d134d6..e272fd5 100644
--- a/public/index.html
+++ b/public/index.html
@@ -112,6 +112,14 @@
Automatically fetch information for new downloads.
+
+
+
+
+ Keep Playlist Order
+ Add index before output file, to keep the order.
+
+
diff --git a/server/helpers/buildArgs.helpers.js b/server/helpers/buildArgs.helpers.js
index 45370f0..892c797 100644
--- a/server/helpers/buildArgs.helpers.js
+++ b/server/helpers/buildArgs.helpers.js
@@ -62,7 +62,7 @@ function validateCodec(codec){
*
* @returns {string[]} Array of arguments ready to be passed to yt-dlp.
*/
-function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
+function buildYtDlpArgs({url, audioOnly, quality, outputFolder, isPlaylist}) {
logger.info("--- CONFIGURATION ---");
@@ -70,6 +70,7 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
logger.info(`CONFIG discordRPC: ${configFeatures.discordRPC}`);
logger.info(`CONFIG customTopBar: ${configFeatures.customTopBar}`);
logger.info(`CONFIG autoCheckInfo: ${configFeatures.autoCheckInfo}`);
+ logger.info(`CONFIG keepPlaylistOrder: ${configFeatures.keepPlaylistOrder}`);
logger.info(`CONFIG addThumbnail: ${configFeatures.addThumbnail}`);
logger.info(`CONFIG addMetadata: ${configFeatures.addMetadata}`);
logger.info(`CONFIG verboseLogs: ${configFeatures.verboseLogs}`);
@@ -117,7 +118,19 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) {
};
args.push("-f", qualityMap[quality] || "best");
- args.push("-o", path.join(outputFolder, "%(title)s.%(ext)s"));
+
+ /**
+ * Default title output template
+ * @type {string}
+ */
+ let outputTemplate = "%(title)s.%(ext)s";
+
+ // If it's a playlist, and we want to keep the playlist order. Add an index before the title.
+ if (isPlaylist && configFeatures.keepPlaylistOrder && configFeatures.autoDownloadPlaylist) {
+ outputTemplate = "%(playlist_index)02d - %(title)s.%(ext)s";
+ }
+
+ args.push("-o", path.join(outputFolder, outputTemplate));
args.push(url);
return args.filter(Boolean);
diff --git a/server/services/download.services.js b/server/services/download.services.js
index 49dfe7a..f0570f6 100644
--- a/server/services/download.services.js
+++ b/server/services/download.services.js
@@ -175,7 +175,12 @@ function fetchDownload(options, listeners, speedListeners, stageListeners, playl
logger.info(`Playlist detected but createPlaylistFolders is disabled, using base folder`);
}
- const args = buildYtDlpArgs({ ...options, outputFolder: safeOutputFolder });
+ const args = buildYtDlpArgs({
+ ...options,
+ outputFolder: safeOutputFolder,
+ isPlaylist
+ });
+
logger.info(`[yt-dlp args] ${args.join(" ")}`);
const child = execFile(userYtDlp, args);