--- DownTube.mjs.orign 2026-05-30 11:54:37.715238308 +0300 +++ DownTube.mjs 2026-05-30 12:03:23.378200112 +0300 @@ -13,8 +13,10 @@ const isPlaylist = (url) => url.includes("&list="); const isFullChannel = (url) => url.includes("/channel/") || url.includes("/@"); -const ytDlpCommand = (url, mode, quality = '', downloadPath) => { - let command = "slack-tube "; +const buildCommand = (url, mode, quality, downloadPath, useAndroidVr) => { + let command = useAndroidVr + ? 'slack-tube --extractor-args "youtube:player_client=android_vr" ' + : 'slack-tube '; let isSPV = isSingleOrPlaylistVideo(url); let isPL = isPlaylist(url); let isFullCH = isFullChannel(url); @@ -65,15 +67,23 @@ command = command.replace("%(uploader)s - ", ""); command = command.replace(".%(ext)s", " - %(uploader)s.%(ext)s"); } + return command; +}; + +const ytDlpCommand = (url, mode, quality = '', downloadPath, useAndroidVr = true) => { + const command = buildCommand(url, mode, quality, downloadPath, useAndroidVr); exec(command, (error, stdout, stderr) => { if (error) { + if (useAndroidVr) { + console.error('android_vr client failed, retrying with default client...'); + ytDlpCommand(url, mode, quality, downloadPath, false); + return; + } console.error(`Error: ${error.message}`); return; } - if (stderr) { - console.error(stderr); - } + if (stderr) console.error(stderr); console.log(stdout); }); }; @@ -99,29 +109,14 @@ rl.question("> ", (mode) => { switch (mode) { - case '1': - ytDlpCommand(url, 'audio', '', downloadPath); - break; - case '2': - ytDlpCommand(url, 'video', '', downloadPath); - break; - case '3': - ytDlpCommand(url, 'video', '2160', downloadPath); - break; - case '4': - ytDlpCommand(url, 'video', '1080', downloadPath); - break; - case '5': - ytDlpCommand(url, 'video', '720', downloadPath); - break; - case '6': - ytDlpCommand(url, 'comments', '', downloadPath); - break; - case '7': - ytDlpCommand(url, 'chat', '', downloadPath); - break; - default: - console.log("Invalid choice."); + case '1': ytDlpCommand(url, 'audio', '', downloadPath); break; + case '2': ytDlpCommand(url, 'video', '', downloadPath); break; + case '3': ytDlpCommand(url, 'video', '2160', downloadPath); break; + case '4': ytDlpCommand(url, 'video', '1080', downloadPath); break; + case '5': ytDlpCommand(url, 'video', '720', downloadPath); break; + case '6': ytDlpCommand(url, 'comments', '', downloadPath); break; + case '7': ytDlpCommand(url, 'chat', '', downloadPath); break; + default: console.log("Invalid choice."); } rl.close(); });