const path = require("path"); const getUserBrowser = require("./getBrowser.helpers.js"); const { ffmpegPath, denoPath} = require("./path.helpers.js"); const { configFeatures } = require("../../config.js"); const { logger } = require("../logger.js"); /** * Validates whether the provided codec is supported by the application. * * If the codec is supported, it is returned unchanged. * Otherwise, a warning is logged and the default codec ("h264") * is returned as a fallback. * * Supported codecs: * - av01 * - vp9.2 * - vp9 * - h265 * - h264 * - vp8 * - h263 * - theora * * @param {string} codec - Codec identifier to validate. * @returns {string} A valid codec identifier. */ function validateCodec(codec){ const validCodec = [ "av01","vp9.2", "vp9" , "h265" , "h264" , "vp8" , "h263", "theora" ] if(validCodec.includes(codec)){ logger.info(`Codec Valid: ${codec}`) return codec } else{ logger.error(`Codec not valid: ${codec}. Using default codec`) return "h264" } } /** * Builds the complete yt-dlp argument list based on the * application configuration and download options. * * The generated arguments include: * - Browser cookie extraction * - FFmpeg integration * - Deno runtime configuration * - Metadata and thumbnail embedding * - Playlist handling * - Video/audio format selection * - Quality filtering * - Output file destination * * @param {Object} options - Download configuration. * @param {string} options.url - Video or playlist URL. * @param {boolean} options.audioOnly - Whether to extract audio only. * @param {string} options.quality - Requested quality preset. * @param {string} options.outputFolder - Download destination folder. * * @returns {string[]} Array of arguments ready to be passed to yt-dlp. */ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { logger.info("--- CONFIGURATION ---"); logger.info(`CONFIG autoUpdate: ${configFeatures.autoUpdate}`); logger.info(`CONFIG discordRPC: ${configFeatures.discordRPC}`); logger.info(`CONFIG customTopBar: ${configFeatures.customTopBar}`); logger.info(`CONFIG autoCheckInfo: ${configFeatures.autoCheckInfo}`); logger.info(`CONFIG addThumbnail: ${configFeatures.addThumbnail}`); logger.info(`CONFIG addMetadata: ${configFeatures.addMetadata}`); logger.info(`CONFIG verboseLogs: ${configFeatures.verboseLogs}`); logger.info(`CONFIG autoDownloadPlaylist: ${configFeatures.autoDownloadPlaylist}`); logger.info(`CONFIG customCodec: ${configFeatures.customCodec}`); // ACTIVATE THEM WHEN THE FEATURE IS IMPLEMENTED // logger.info(`CONFIG logSystem: ${configFeatures.logSystem}`); // logger.info(`CONFIG outputTitleCheck: ${configFeatures.outputTitleCheck}`); // logger.info(`CONFIG downloadSystem: ${configFeatures.downloadSystem}`); // logger.info(`CONFIG notifySystem: ${configFeatures.notifySystem}`); logger.info("---------------------"); const args = [ configFeatures.verboseLogs ? "--verbose" : null, // Verbose Logs "--cookies-from-browser", `${getUserBrowser()}`, "--no-continue", "--no-overwrites", "--newline", // YT-DLP Logs Format configFeatures.addThumbnail ? "--embed-thumbnail" : null, configFeatures.addMetadata ? "--add-metadata" : null, "--concurrent-fragments", "8", "--retries", "10", "--fragment-retries", "10", "--ffmpeg-location", ffmpegPath, "--extractor-args","youtube:player_client=default", "--js-runtimes", `deno:${denoPath}`, "-S", `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`+ `,acodec:aac`, configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist" ]; if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3"); else args.push("--merge-output", "mp4"); const qualityMap = { best: "bestvideo+bestaudio/best/mp4", medium: "bestvideo[height<=720]+bestaudio/best[height<=720]/mp4", worst: "worstvideo+worstaudio/worst/mp4", 1080: "bestvideo[height<=1080]+bestaudio/best[height<=1080]/mp4", 720: "bestvideo[height<=720]+bestaudio/best[height<=720]/mp4", 480: "bestvideo[height<=480]+bestaudio/best[height<=480]/mp4", }; args.push("-f", qualityMap[quality] || "best"); args.push("-o", path.join(outputFolder, "%(title)s.%(ext)s")); args.push(url); return args.filter(Boolean); } module.exports = { buildYtDlpArgs };