ytdlp-nodejs
Version:
A TypeScript wrapper for the yt-dlp executable
42 lines (37 loc) • 11.7 kB
JavaScript
;var q=Object.create;var P=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var T=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var j=(e,t,r,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of N(t))!B.call(e,o)&&o!==r&&P(e,o,{get:()=>t[o],enumerable:!(l=L(t,o))||l.enumerable});return e};var _=(e,t,r)=>(r=e!=null?q(T(e)):{},j(t||!e||!e.__esModule?P(r,"default",{value:e,enumerable:!0}):r,e));var k=_(require("fs")),C=_(require("path"));var n={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",underscore:"\x1B[4m",blink:"\x1B[5m",reverse:"\x1B[7m",hidden:"\x1B[8m",fg:{black:"\x1B[30m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m"},bg:{black:"\x1B[40m",red:"\x1B[41m",green:"\x1B[42m",yellow:"\x1B[43m",blue:"\x1B[44m",magenta:"\x1B[45m",cyan:"\x1B[46m",white:"\x1B[47m"}};function i(e,t){return`${t}${e}${n.reset}`}var s={title:e=>i(e,n.fg.cyan+n.bright),success:e=>i(e,n.fg.green),error:e=>i(e,n.fg.red),warning:e=>i(e,n.fg.yellow),info:e=>i(e,n.fg.blue),muted:e=>i(e,n.dim)};function Y(){try{let e=C.default.resolve(__dirname,"..","package.json"),t=k.default.readFileSync(e,"utf8");return JSON.parse(t).version||"0.0.0"}catch{return"0.0.0"}}function Q(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function I(e){let t,r=[],l={},o=[],a=[...e];a[0]&&!a[0].startsWith("-")&&(t=a.shift());for(let c=0;c<a.length;c++){let f=a[c];if(f==="--"){o.push(...a.slice(c+1));break}if(f.startsWith("--")){let p=f.indexOf("="),g=p===-1?f.slice(2):f.slice(2,p),m=!0;if(p!==-1?m=f.slice(p+1):a[c+1]&&!a[c+1].startsWith("-")&&(m=a[c+1],c+=1),g==="raw"){m===!0?a[c+1]&&(o.push(a[c+1]),c+=1):o.push(String(m));continue}l[g]===void 0?l[g]=m:Array.isArray(l[g])?l[g]=[...l[g],String(m)]:l[g]=[String(l[g]),String(m)]}else r.push(f)}let u={};for(let[c,f]of Object.entries(l))u[Q(c)]=f;if(u.raw){let c=u.raw;Array.isArray(c)?o.push(...c.map(String)):typeof c=="string"&&o.push(c)}return o.length>0&&(u.raw=o),{command:t,positionals:r,options:u}}function F(e){if(e.length===0)return s.warning("No formats found.");let t=["ID","Ext","Resolution","Note"],r=[Math.max(t[0].length,...e.map(a=>a.formatId.length)),Math.max(t[1].length,...e.map(a=>a.extension.length)),Math.max(t[2].length,...e.map(a=>a.resolution.length))],o=[[i(t[0].padEnd(r[0]),n.fg.cyan),i(t[1].padEnd(r[1]),n.fg.cyan),i(t[2].padEnd(r[2]),n.fg.cyan),i(t[3],n.fg.cyan)].join(" "),i(`${"-".repeat(r[0])} ${"-".repeat(r[1])} ${"-".repeat(r[2])} ${"-".repeat(t[3].length)}`,n.dim)];for(let a of e)o.push(`${i(a.formatId.padEnd(r[0]),n.fg.yellow)} ${a.extension.padEnd(r[1])} ${a.resolution.padEnd(r[2])} ${a.note}`);return o.join(`
`)}function $(e){let t={};return e.output&&(t.output=String(e.output)),e.proxy&&(t.proxy=String(e.proxy)),e.cookies&&(t.cookies=String(e.cookies)),e.cookiesFromBrowser&&(t.cookiesFromBrowser=String(e.cookiesFromBrowser)),e.socketTimeout&&(t.socketTimeout=Number(e.socketTimeout)),e.concurrentFragments&&(t.concurrentFragments=Number(e.concurrentFragments)),e.retries&&(t.retries=Number(e.retries)),e.retrySleep&&(t.retrySleep=Number(e.retrySleep)),e.limitRate&&(t.limitRate=String(e.limitRate)),e.downloadSections&&(t.downloadSections=String(e.downloadSections)),e.playlistItems&&(t.playlistItems=String(e.playlistItems)),e.noPlaylist&&(t.noPlaylist=!0),e.formatSort&&(t.formatSort=String(e.formatSort).split(",").map(r=>r.trim()).filter(Boolean)),e.mergeOutputFormat&&(t.mergeOutputFormat=String(e.mergeOutputFormat)),e.raw&&(t.rawArgs=e.raw),e.verbose&&(t.verbose=!0),t}function S(e){return t=>{let r=t.percentage_str??"N/A";process.stdout.write(`\x1B[2K\r${s.info(e)} ${s.success(r)}`)}}function d(){console.log(`
${s.title(`ytdlp ${Y()}`)}
${s.warning("Usage:")}
${i("ytdlp",n.fg.green)} Launch interactive mode
${i("ytdlp download <url>",n.fg.green)} Download a video
${i("ytdlp audio <url>",n.fg.green)} Download audio only
${i("ytdlp info <url>",n.fg.green)} Get info as JSON
${i("ytdlp ffmpeg",n.fg.green)} Download FFmpeg binaries
${i("ytdlp version",n.fg.green)} Show version
${s.warning("Options:")}
${i("--output",n.fg.cyan)} <template> Output filename template
${i("--quality",n.fg.cyan)} <q> Video quality (1080p, 720p, etc)
${i("--verbose",n.fg.cyan)} Enable verbose logging
`)}var R=require("..");var D=_(require("readline"));function b(){let e=D.default.createInterface({input:process.stdin,output:process.stdout,terminal:!1});return{ask:r=>new Promise(l=>e.question(r,l)),close:()=>e.close()}}async function h(e,t,r){let l=r?`${s.info("?")} ${t} ${s.muted(`(${r})`)}: `:`${s.info("?")} ${t}: `;process.stdout.write(l);let o=(await e("")).trim();return!o&&r!==void 0?r:o.toLowerCase()==="q"?null:o}async function x(e,t,r,l){console.log(`
${s.title(t)}`),r.forEach((u,c)=>{let f=`${c+1}.`;console.log(` ${i(f,n.fg.green)} ${u.label}`)}),console.log(s.muted(" q. Quit")),console.log("");let o=l?r.findIndex(u=>u.value===l)+1:0,a=o?`${s.info("?")} Select (1-${r.length}) ${s.muted(`[${o}]`)}: `:`${s.info("?")} Select (1-${r.length}): `;for(;;){process.stdout.write(a);let u=(await e("")).trim();if(u.toLowerCase()==="q")return null;if(!u&&o)return r[o-1].value;let c=Number(u);if(Number.isInteger(c)&&c>=1&&c<=r.length)return r[c-1].value;console.log(s.error("Invalid selection. Please try again."))}}async function M(e){let t=await h(e,"Extra args (e.g. --embed-subs) [Enter to skip]");return t?t.split(" ").map(r=>r.trim()).filter(Boolean):[]}async function w(e,t=!1,r){let{ask:l,close:o}=b();try{let a=r||await h(l,"Video URL");if(!a)return;let u,c;if(t){let g=await x(l,"Audio Format/Quality",[{value:"mp3",label:"MP3 (Best compatibility)"},{value:"m4a",label:"M4A (Better quality)"},{value:"wav",label:"WAV (Uncompressed)"},{value:"best",label:"Best Quality (Auto)"}]);if(!g)return;c=g==="best"?void 0:g}else{let g=await x(l,"Video Quality",[{value:"best",label:"Best Available"},{value:"2160",label:"4K (2160p)"},{value:"1440",label:"2K (1440p)"},{value:"1080",label:"Full HD (1080p)"},{value:"720",label:"HD (720p)"},{value:"480",label:"SD (480p)"},{value:"worst",label:"Smallest File"}]);if(!g)return;g==="best"?u="best":g==="worst"?u="worst":u=`bestvideo[height<=${g}]+bestaudio/best[height<=${g}]`}let f=await M(l);console.log(`
${s.info("Starting download...")}
`);let p=$({});if(f.length>0&&(p.rawArgs=f),t){let g={...p,format:{filter:"audioonly",type:c||"mp3",quality:0},onProgress:S("Downloading Audio")},m=await e.downloadAsync(a,g);console.log(`
${s.success("Download Complete!")}`),m.filePaths.length&&console.log(m.filePaths.map(v=>` - ${v}`).join(`
`))}else{let g={...p,format:u,mergeOutputFormat:"mp4",onProgress:S("Downloading Video")},m=await e.downloadAsync(a,g);console.log(`
${s.success("Download Complete!")}`),m.filePaths.length&&console.log(m.filePaths.map(v=>` - ${v}`).join(`
`))}}catch(a){console.error(`
${s.error("Error occurred:")} ${a}`)}finally{o()}}function H(e){if(console.log(`
${s.title("Video Information")}`),console.log(` ${i("Title:",n.fg.cyan)} ${e.title}`),console.log(` ${i("Uploader:",n.fg.cyan)} ${e.uploader} ${s.muted(`(${e.uploader_id})`)}`),console.log(` ${i("Channel:",n.fg.cyan)} ${e.channel} ${e.channel_follower_count?s.muted(`(${e.channel_follower_count.toLocaleString()} subs)`):""}`),console.log(` ${i("Duration:",n.fg.cyan)} ${e.duration_string||e.duration+"s"}`),console.log(` ${i("Views:",n.fg.cyan)} ${e.view_count?.toLocaleString()}`),e.like_count&&console.log(` ${i("Likes:",n.fg.cyan)} ${e.like_count.toLocaleString()}`),e.comment_count&&console.log(` ${i("Comments:",n.fg.cyan)} ${e.comment_count.toLocaleString()}`),console.log(` ${i("Resolution:",n.fg.cyan)} ${e.resolution||e.width+"x"+e.height} ${e.fps?`(${e.fps}fps)`:""}`),console.log(` ${i("Date:",n.fg.cyan)} ${e.upload_date}`),console.log(` ${i("URL:",n.fg.cyan)} ${e.webpage_url}`),e.tags&&e.tags.length>0){let t=e.tags.slice(0,5).join(", ")+(e.tags.length>5?"...":"");console.log(` ${i("Tags:",n.fg.cyan)} ${s.muted(t)}`)}if(e.description){let t=e.description.split(`
`)[0].substring(0,100)+(e.description.length>100?"...":"");console.log(` ${i("Description:",n.fg.cyan)} ${s.muted(t)}`)}}function W(e){console.log(`
${s.title("Playlist Information")}`),console.log(` ${i("Title:",n.fg.cyan)} ${e.title}`),console.log(` ${i("Count:",n.fg.cyan)} ${e.playlist_count} videos`),console.log(` ${i("URL:",n.fg.cyan)} ${e.webpage_url}`),e.entries&&e.entries.length>0&&(console.log(`
${s.info("First 5 entries:")}`),e.entries.slice(0,5).forEach((t,r)=>{console.log(` ${r+1}. ${t.title} ${s.muted(`(${t.duration_string||"N/A"})`)}`)}),e.entries.length>5&&console.log(` ... and ${e.entries.length-5} more`))}async function A(e,t){let{ask:r,close:l}=b();try{let o=t||await h(r,"Video URL");if(!o)return;console.log(s.info("Fetching info..."));let a=await e.getInfoAsync(o);a._type==="playlist"?W(a):H(a)}catch(o){let a=o instanceof Error?o.message:String(o);console.error(`
${s.error("Error:")} ${a}`)}finally{l()}}async function V(){let e=new R.YtDlp;console.clear(),console.log(i(`
__ __ _____ ____ _ ____
\\ \\ / /|_ _|| _ \\ | | | _ \\
\\ V / | | | | | || | | |_) |
| | | | | |_| || |___ | __/
|_| |_| |____/ |_____||_|
`,n.fg.red)),console.log(s.muted(` Powerful yt-dlp wrapper for Node.js
`));let{ask:t,close:r}=b();try{let l=await x(t,"Choose Action",[{value:"download",label:"Download Video"},{value:"audio",label:"Download Audio Only"},{value:"info",label:"Get Video Info"},{value:"update",label:"Update yt-dlp Binary"},{value:"ffmpeg",label:"Download FFmpeg"}]);if(l)switch(l){case"download":await w(e,!1);break;case"audio":await w(e,!0);break;case"info":await A(e);break;case"update":{console.log(s.info("Updating yt-dlp..."));let o=await e.updateYtDlpAsync();console.log(s.success(`Updated to ${o.version||"latest"}`));break}case"ffmpeg":{console.log(s.info("Downloading FFmpeg..."));let o=await e.downloadFFmpeg();console.log(o?s.success(`FFmpeg available at: ${o}`):s.error("Failed to download FFmpeg."));break}}}finally{r()}}var U=require("..");function K(e){if(e.source==="json"){let t=e.formats.map(r=>({formatId:r.format_id,extension:r.ext||"",resolution:r.resolution||"",note:r.format_note||"",raw:""}));console.log(F(t))}else console.log(F(e.table.rows))}async function E(e,t,r){let l=new U.YtDlp;if(e==="download"){let o=t[0];if(!o){d();return}await w(l,!1,String(o));return}if(e==="info"){let o=t[0];if(!o){d();return}await A(l,String(o));return}if(e==="formats"){let o=t[0];if(!o){d();return}let a=await l.getFormatsAsync(String(o));K(a);return}if(e==="audio"){let o=t[0];if(!o){d();return}await w(l,!0,String(o));return}if(e==="video"){let o=t[0];if(!o){d();return}let a=$(r),u=r.quality?String(r.quality):"best",c=await l.downloadVideo(String(o),u,a);c.filePaths.length>0&&console.log(c.filePaths.join(`
`));return}if(e==="ffmpeg"){console.log(s.info("Downloading FFmpeg..."));let o=await l.downloadFFmpeg();console.log(o?s.success(`FFmpeg available at: ${o}`):s.error("Failed to download FFmpeg."));return}if(e==="update"){let o=await l.updateYtDlpAsync();console.log(s.success(`Updated via ${o.method}. Binary: ${o.binaryPath}${o.version?` (version ${o.version})`:""}`));return}d()}async function O(){let{command:e,positionals:t,options:r}=I(process.argv.slice(2));if(!e){await V();return}if(r.help||e==="help"){d();return}await E(e,t,r)}O().catch(e=>{console.error(e),process.exit(1)});