@pieda/video-dl 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,7 @@ type TUseInstagram = {
5
5
  dest: string;
6
6
  tempDir: string;
7
7
  ffmpegConfig: {
8
+ ffmpegDir: string;
8
9
  ffmpegPath: string;
9
10
  ffmpegProbePath: string;
10
11
  ffmpegPlayPath: string;
@@ -5,6 +5,7 @@ type TUseVimeo = {
5
5
  dest: string;
6
6
  tempDir: string;
7
7
  ffmpegConfig: {
8
+ ffmpegDir: string;
8
9
  ffmpegPath: string;
9
10
  ffmpegProbePath: string;
10
11
  ffmpegPlayPath: string;
@@ -5,6 +5,7 @@ type TUseYoutube = {
5
5
  debug?: boolean;
6
6
  tempDir: string;
7
7
  ffmpegConfig: {
8
+ ffmpegDir: string;
8
9
  ffmpegPath: string;
9
10
  ffmpegProbePath: string;
10
11
  ffmpegPlayPath: string;
@@ -1,14 +1,14 @@
1
1
  type TUseYtdlp = {
2
2
  debug?: boolean;
3
- ytdlpPath: string;
4
- videoUrl: string;
3
+ command: string;
5
4
  dest: string;
6
5
  tempDir: string;
7
6
  ffmpegConfig: {
7
+ ffmpegDir: string;
8
8
  ffmpegPath: string;
9
9
  ffmpegProbePath: string;
10
10
  ffmpegPlayPath: string;
11
11
  };
12
12
  };
13
- export declare const useYtdlp: ({ debug, ytdlpPath, videoUrl, dest, tempDir, ffmpegConfig, }: TUseYtdlp) => Promise<[Error | null, boolean | null]>;
13
+ export declare const useYtdlp: ({ debug, command, dest, tempDir, ffmpegConfig, }: TUseYtdlp) => Promise<[Error | null, boolean | null]>;
14
14
  export {};
package/dist/video-dl.cjs CHANGED
@@ -1 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=(t=!1)=>({log:(...o)=>{t&&console.log(...o)},error:(...o)=>{t&&console.error(...o)}}),u=t=>new Promise((o,s)=>{import(t).then(r=>o(r.default)).catch(s)}),S=async(t,o,s)=>{const r=await u("fs"),e=await u("axios");return console.log(`Downloading ${t} to ${o}`),new Promise((i,n)=>{e.get(t,{responseType:"stream",headers:s}).then(a=>{const g=a.data,l=r.createWriteStream(o);g.pipe(l),l.on("finish",function(){l.close(()=>{i()})})}).catch(n)})},v=async({debug:t=!1,ytdlpPath:o,videoUrl:s,dest:r,tempDir:e,ffmpegConfig:i})=>{const n=d(t);n.log(`Downloading video: ${s} to: ${r}`);const a=await u("fs"),g=await u("path"),{exec:l,execSync:f}=await u("child_process"),w=()=>new Promise((c,m)=>{const p=`${o} -f mergeall --audio-multistreams --video-multistreams ${s} --downloader ffmpeg -o "${e}/%(id)s.%(ext)s" --merge-output-format mp4`;n.log(`[yt-dlp] 執行命令: ${p}`),l(p,(h,$,y)=>{if(n.log(`[yt-dlp] stdout: ${$}`),h){m(h);return}c()})});return a.existsSync(g.dirname(r))||(a.mkdirSync(g.dirname(r),{recursive:!0},777),n.log(`建立 ${g.dirname(r)}`)),new Promise(async(c,m)=>{try{await w();let p=!1;const h=a.readdirSync(e);for(const $ of h){const y=g.join(e,$),M=`${i.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${y}"`,k=f(M).toString("utf-8"),A=k.includes("video"),D=k.includes("audio");if(A&&D){p=!0,a.copyFileSync(y,r);break}}if(!p)throw new Error("無法下載影音正常的影片");n.log(`下載完成 ${r}`),c([null,!0])}catch(p){n.error(`下載失敗: ${p.message}`),c([p,null])}})},b=async({debug:t=!1,ytdlpPath:o,videoId:s,dest:r,tempDir:e,ffmpegConfig:i})=>{d(t).log(`Downloading video: ${s} to: ${r}`);const a=`https://www.youtube.com/watch?v=${s}`;return v({debug:t,ytdlpPath:o,videoUrl:a,dest:r,tempDir:e,ffmpegConfig:i})},P=async({videoId:t,dest:o,debug:s=!1,headless:r=!0})=>{try{const e=d(s);e.log(`Downloading video: ${t} to: ${o}`);const i=`https://m.facebook.com/watch/?v=${t}`,n=await u("fs"),a=await u("path"),g=await u("puppeteer");n.existsSync(a.dirname(o))||(n.mkdirSync(a.dirname(o),{recursive:!0},777),e.log(`建立 ${a.dirname(o)}`));const l={};r||(l.headless=!1);const f=await g.launch(l);e.log("啟動 puppeteer");const w=await f.newPage();await w.setUserAgent("'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'"),e.log("開新分頁"),e.log(`前往 ${i}`),await Promise.race([w.goto(i,{waitUntil:"networkidle0"}),w.waitForSelector("video")]),e.log("找到 video 元素");const c=await w.$eval("video",m=>m.getAttribute("src"));return e.log(`取得 video url: ${c}`),await f.close(),e.log("關閉 puppeteer"),await S(c,o),e.log(`下載完成 ${c}`),[null,!0]}catch(e){return[e,null]}},U=async({debug:t=!1,ytdlpPath:o,videoId:s,dest:r,tempDir:e,ffmpegConfig:i})=>{d(t).log(`Downloading video: ${s} to: ${r}`);const a=`https://vimeo.com/${s}`;return v({debug:t,ytdlpPath:o,videoUrl:a,dest:r,tempDir:e,ffmpegConfig:i})},x=async({debug:t=!1,ytdlpPath:o,videoId:s,dest:r,tempDir:e,ffmpegConfig:i})=>{d(t).log(`Downloading video: ${s} to: ${r}`);const a=`https://www.instagram.com/reel/${s}/`;return v({debug:t,ytdlpPath:o,videoUrl:a,dest:r,tempDir:e,ffmpegConfig:i})},F=async({videoLink:t,dest:o,debug:s=!1,headless:r=!0})=>{try{const e=d(s);e.log(`Downloading video: ${t} to: ${o}`);const i=t,n=await u("fs"),a=await u("path"),g=await u("puppeteer");n.existsSync(a.dirname(o))||(n.mkdirSync(a.dirname(o),{recursive:!0},777),e.log(`建立 ${a.dirname(o)}`));const l={};r||(l.headless=!1);const f=await g.launch(l);e.log("啟動 puppeteer");const w=await f.newPage();e.log("開新分頁"),e.log(`前往 ${i}`),await Promise.race([w.goto(i,{waitUntil:"networkidle0"}),w.waitForSelector("video")]),e.log("找到 video 元素");const c=await w.$eval('video source[src^="https://www.tiktok.com/aweme/v1/play/"]',m=>m.getAttribute("src"));return e.log(`取得 video url: ${c}`),await f.close(),e.log("關閉 puppeteer"),await S(c,o,{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",Referer:"https://www.tiktok.com/"}),e.log(`下載完成 ${c}`),[null,!0]}catch(e){return[e,null]}},T=({type:t})=>{switch(t){case"youtube":case"yt-short":return b;case"facebook":case"fb-reel":return P;case"vimeo":return U;case"instagram":case"ig":case"ig-reel":return x;case"tiktok":case"tiktok-reel":return F;default:throw new Error(`Invalid video type: ${t}`)}};exports.useDownloader=T;exports.useFacebook=P;exports.useInstagram=x;exports.useTiktok=F;exports.useVimeo=U;exports.useYoutube=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=(t=!1)=>({log:(...o)=>{t&&console.log(...o)},error:(...o)=>{t&&console.error(...o)}}),u=t=>new Promise((o,a)=>{import(t).then(i=>o(i.default)).catch(a)}),P=async(t,o,a)=>{const i=await u("fs"),e=await u("axios");return console.log(`Downloading ${t} to ${o}`),new Promise((n,c)=>{e.get(t,{responseType:"stream",headers:a}).then(s=>{const l=s.data,g=i.createWriteStream(o);l.pipe(g),g.on("finish",function(){g.close(()=>{n()})})}).catch(c)})},x=async({debug:t=!1,command:o,dest:a,tempDir:i,ffmpegConfig:e})=>{const n=v(t),c=await u("fs"),s=await u("path"),{exec:l,execSync:g}=await u("child_process"),d=()=>new Promise((r,p)=>{n.log(`[yt-dlp] 執行命令: ${o}`),l(o,(w,b,f)=>{if(n.log(`[yt-dlp] stdout: ${b}`),w){p(w);return}r()})});return c.existsSync(s.dirname(a))||(c.mkdirSync(s.dirname(a),{recursive:!0},777),n.log(`建立 ${s.dirname(a)}`)),new Promise(async(r,p)=>{try{await d();let w=!1;const b=c.readdirSync(i);for(const f of b){const h=s.join(i,f),y=`${e.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${h}"`,m=g(y).toString("utf-8"),$=m.includes("video"),S=m.includes("audio");if($&&S){w=!0,c.copyFileSync(h,a);break}}if(!w)throw new Error("無法下載影音正常的影片");n.log(`下載完成 ${a}`),r([null,!0])}catch(w){n.error(`下載失敗: ${w.message}`),r([w,null])}})},T=async({debug:t=!1,ytdlpPath:o,videoId:a,dest:i,tempDir:e,ffmpegConfig:n})=>{const c=v(t);c.log(`Downloading video: ${a} to: ${i}`);const s=await u("fs"),l=await u("path"),g=await u("puppeteer"),d=`https://www.youtube.com/watch?v=${a}`,r=l.join(l.dirname(o),"cookies.txt"),p=(f=[])=>{const h=["# Netscape HTTP Cookie File","# https://curl.se/docs/http-cookies.html","# This file was generated by Puppeteer",""].join(`
2
+ `),y=f.map(m=>{const $=m.domain.startsWith(".")?m.domain:`.${m.domain}`,S="TRUE",k=m.path||"/",A=m.secure?"TRUE":"FALSE",M=m.expires?Math.floor(m.expires):Math.floor(Date.now()/1e3)+3600*24*365,E=m.name,_=m.value;return[$,S,k,A,M,E,_].join(" ")});return h+`
3
+ `+y.join(`
4
+ `)+`
5
+ `};await(async()=>{const f=l.join(l.dirname(o),"chrome-profile");if(s.existsSync(f)||s.mkdirSync(f,{recursive:!0},777),s.existsSync(r)&&s.statSync(r).mtimeMs+6e5>Date.now()){c.log("Using existing cookies.txt");return}console.log("Launching Chrome…");const h=await g.launch({headless:!1,userDataDir:f,defaultViewport:null,args:["--disable-blink-features=AutomationControlled"]}),y=await h.newPage();await y.goto("https://www.youtube.com",{waitUntil:"networkidle2"}),console.log("If not logged in, please log in manually."),console.log("Waiting 30 seconds…"),await new Promise(k=>setTimeout(k,3e4));const $=(await y.cookies()).filter(k=>k.domain.includes("youtube.com")||k.domain.includes("google.com"));$.length===0&&(console.error("No YouTube cookies found. Are you logged in?"),process.exit(1));const S=p($);s.writeFileSync(r,S,{encoding:"utf8"}),console.log(`cookies.txt written to ${r}`),console.log(`Cookies count: ${$.length}`),await h.close()})();const b=[`${o}`,'-f "bv*[vcodec^=avc1][acodec^=mp4a][height<=1080]/ba/b"',"--js-runtimes node",`${d}`,`-o "${e}/%(id)s.%(ext)s"`,`--cookies ${r}`,n.ffmpegDir?`--ffmpeg-location "${n.ffmpegDir}"`:""];return x({debug:t,command:b.join(" "),dest:i,tempDir:e,ffmpegConfig:n})},U=async({videoId:t,dest:o,debug:a=!1,headless:i=!0})=>{try{const e=v(a);e.log(`Downloading video: ${t} to: ${o}`);const n=`https://m.facebook.com/watch/?v=${t}`,c=await u("fs"),s=await u("path"),l=await u("puppeteer");c.existsSync(s.dirname(o))||(c.mkdirSync(s.dirname(o),{recursive:!0},777),e.log(`建立 ${s.dirname(o)}`));const g={};i||(g.headless=!1);const d=await l.launch(g);e.log("啟動 puppeteer");const r=await d.newPage();await r.setUserAgent("'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'"),e.log("開新分頁"),e.log(`前往 ${n}`),await r.goto(n,{waitUntil:"networkidle2"}),await r.waitForSelector("video"),e.log("找到 video 元素");const p=await r.$eval("video",w=>w.getAttribute("src"));return e.log(`取得 video url: ${p}`),await d.close(),e.log("關閉 puppeteer"),await P(p,o),e.log(`下載完成 ${p}`),[null,!0]}catch(e){return[e,null]}},j=async({debug:t=!1,ytdlpPath:o,videoId:a,dest:i,tempDir:e,ffmpegConfig:n})=>{v(t).log(`Downloading video: ${a} to: ${i}`);const s=`https://vimeo.com/${a}`,l=[`${o}`,'-f "bv*[vcodec^=avc1][acodec^=mp4a][height<=1080]/ba/b"',"--js-runtimes node",`${s}`,`-o "${e}/%(id)s.%(ext)s"`];return x({debug:t,command:l.join(" "),dest:i,tempDir:e,ffmpegConfig:n})},D=async({debug:t=!1,ytdlpPath:o,videoId:a,dest:i,tempDir:e,ffmpegConfig:n})=>{v(t).log(`Downloading video: ${a} to: ${i}`);const s=`https://www.instagram.com/reel/${a}/`,l=[`${o}`,"-f mergeall","--audio-multistreams","--video-multistreams","--js-runtimes node",`${s}`,"--downloader ffmpeg",`-o "${e}/%(id)s.%(ext)s"`,"--merge-output-format mp4",n.ffmpegDir?`--ffmpeg-location "${n.ffmpegDir}"`:""];return x({debug:t,command:l.join(" "),dest:i,tempDir:e,ffmpegConfig:n})},F=async({videoLink:t,dest:o,debug:a=!1,headless:i=!0})=>{try{const e=v(a);e.log(`Downloading video: ${t} to: ${o}`);const n=t,c=await u("fs"),s=await u("path"),l=await u("puppeteer");c.existsSync(s.dirname(o))||(c.mkdirSync(s.dirname(o),{recursive:!0},777),e.log(`建立 ${s.dirname(o)}`));const g={};i||(g.headless=!1);const d=await l.launch(g);e.log("啟動 puppeteer");const r=await d.newPage();e.log("開新分頁"),e.log(`前往 ${n}`),await r.goto(n,{waitUntil:"networkidle2"}),await r.waitForSelector("video"),e.log("找到 video 元素");const p=await r.$eval('video source[src^="https://www.tiktok.com/aweme/v1/play/"]',w=>w.getAttribute("src"));return e.log(`取得 video url: ${p}`),await d.close(),e.log("關閉 puppeteer"),await P(p,o,{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",Referer:"https://www.tiktok.com/"}),e.log(`下載完成 ${p}`),[null,!0]}catch(e){return[e,null]}},W=({type:t})=>{switch(t){case"youtube":case"yt-short":return T;case"facebook":case"fb-reel":return U;case"vimeo":return j;case"instagram":case"ig":case"ig-reel":return D;case"tiktok":case"tiktok-reel":return F;default:throw new Error(`Invalid video type: ${t}`)}};exports.useDownloader=W;exports.useFacebook=U;exports.useInstagram=D;exports.useTiktok=F;exports.useVimeo=j;exports.useYoutube=T;
package/dist/video-dl.js CHANGED
@@ -1,209 +1,261 @@
1
- const d = (t = !1) => ({
1
+ const v = (t = !1) => ({
2
2
  log: (...o) => {
3
3
  t && console.log(...o);
4
4
  },
5
5
  error: (...o) => {
6
6
  t && console.error(...o);
7
7
  }
8
- }), u = (t) => new Promise((o, n) => {
9
- import(t).then((r) => o(r.default)).catch(n);
10
- }), S = async (t, o, n) => {
11
- const r = await u("fs"), e = await u("axios");
12
- return console.log(`Downloading ${t} to ${o}`), new Promise((i, s) => {
8
+ }), u = (t) => new Promise((o, a) => {
9
+ import(t).then((i) => o(i.default)).catch(a);
10
+ }), U = async (t, o, a) => {
11
+ const i = await u("fs"), e = await u("axios");
12
+ return console.log(`Downloading ${t} to ${o}`), new Promise((s, c) => {
13
13
  e.get(t, {
14
14
  responseType: "stream",
15
- headers: n
16
- }).then((a) => {
17
- const g = a.data, l = r.createWriteStream(o);
18
- g.pipe(l), l.on("finish", function() {
19
- l.close(() => {
20
- i();
15
+ headers: a
16
+ }).then((n) => {
17
+ const l = n.data, g = i.createWriteStream(o);
18
+ l.pipe(g), g.on("finish", function() {
19
+ g.close(() => {
20
+ s();
21
21
  });
22
22
  });
23
- }).catch(s);
23
+ }).catch(c);
24
24
  });
25
- }, v = async ({
25
+ }, x = async ({
26
26
  debug: t = !1,
27
- ytdlpPath: o,
28
- videoUrl: n,
29
- dest: r,
30
- tempDir: e,
31
- ffmpegConfig: i
27
+ command: o,
28
+ dest: a,
29
+ tempDir: i,
30
+ ffmpegConfig: e
32
31
  }) => {
33
- const s = d(t);
34
- s.log(`Downloading video: ${n} to: ${r}`);
35
- const a = await u("fs"), g = await u("path"), { exec: l, execSync: f } = await u("child_process"), w = () => new Promise((c, m) => {
36
- const p = `${o} -f mergeall --audio-multistreams --video-multistreams ${n} --downloader ffmpeg -o "${e}/%(id)s.%(ext)s" --merge-output-format mp4`;
37
- s.log(`[yt-dlp] 執行命令: ${p}`), l(p, (h, $, y) => {
38
- if (s.log(`[yt-dlp] stdout: ${$}`), h) {
39
- m(h);
32
+ const s = v(t), c = await u("fs"), n = await u("path"), { exec: l, execSync: g } = await u("child_process"), d = () => new Promise((r, m) => {
33
+ s.log(`[yt-dlp] 執行命令: ${o}`), l(o, (w, b, f) => {
34
+ if (s.log(`[yt-dlp] stdout: ${b}`), w) {
35
+ m(w);
40
36
  return;
41
37
  }
42
- c();
38
+ r();
43
39
  });
44
40
  });
45
- return a.existsSync(g.dirname(r)) || (a.mkdirSync(g.dirname(r), { recursive: !0 }, 777), s.log(`建立 ${g.dirname(r)}`)), new Promise(async (c, m) => {
41
+ return c.existsSync(n.dirname(a)) || (c.mkdirSync(n.dirname(a), { recursive: !0 }, 777), s.log(`建立 ${n.dirname(a)}`)), new Promise(async (r, m) => {
46
42
  try {
47
- await w();
48
- let p = !1;
49
- const h = a.readdirSync(e);
50
- for (const $ of h) {
51
- const y = g.join(e, $), P = `${i.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${y}"`, k = f(P).toString("utf-8"), b = k.includes("video"), x = k.includes("audio");
52
- if (b && x) {
53
- p = !0, a.copyFileSync(y, r);
43
+ await d();
44
+ let w = !1;
45
+ const b = c.readdirSync(i);
46
+ for (const f of b) {
47
+ const h = n.join(i, f), y = `${e.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${h}"`, p = g(y).toString("utf-8"), $ = p.includes("video"), S = p.includes("audio");
48
+ if ($ && S) {
49
+ w = !0, c.copyFileSync(h, a);
54
50
  break;
55
51
  }
56
52
  }
57
- if (!p)
53
+ if (!w)
58
54
  throw new Error("無法下載影音正常的影片");
59
- s.log(`下載完成 ${r}`), c([null, !0]);
60
- } catch (p) {
61
- s.error(`下載失敗: ${p.message}`), c([p, null]);
55
+ s.log(`下載完成 ${a}`), r([null, !0]);
56
+ } catch (w) {
57
+ s.error(`下載失敗: ${w.message}`), r([w, null]);
62
58
  }
63
59
  });
64
- }, U = async ({
60
+ }, D = async ({
65
61
  debug: t = !1,
66
62
  ytdlpPath: o,
67
- videoId: n,
68
- dest: r,
63
+ videoId: a,
64
+ dest: i,
69
65
  tempDir: e,
70
- ffmpegConfig: i
66
+ ffmpegConfig: s
71
67
  }) => {
72
- d(t).log(`Downloading video: ${n} to: ${r}`);
73
- const a = `https://www.youtube.com/watch?v=${n}`;
74
- return v({
68
+ const c = v(t);
69
+ c.log(`Downloading video: ${a} to: ${i}`);
70
+ const n = await u("fs"), l = await u("path"), g = await u("puppeteer"), d = `https://www.youtube.com/watch?v=${a}`, r = l.join(l.dirname(o), "cookies.txt"), m = (f = []) => {
71
+ const h = [
72
+ "# Netscape HTTP Cookie File",
73
+ "# https://curl.se/docs/http-cookies.html",
74
+ "# This file was generated by Puppeteer",
75
+ ""
76
+ ].join(`
77
+ `), y = f.map((p) => {
78
+ const $ = p.domain.startsWith(".") ? p.domain : `.${p.domain}`, S = "TRUE", k = p.path || "/", A = p.secure ? "TRUE" : "FALSE", P = p.expires ? Math.floor(p.expires) : Math.floor(Date.now() / 1e3) + 3600 * 24 * 365, T = p.name, j = p.value;
79
+ return [$, S, k, A, P, T, j].join(" ");
80
+ });
81
+ return h + `
82
+ ` + y.join(`
83
+ `) + `
84
+ `;
85
+ };
86
+ await (async () => {
87
+ const f = l.join(l.dirname(o), "chrome-profile");
88
+ if (n.existsSync(f) || n.mkdirSync(f, { recursive: !0 }, 777), n.existsSync(r) && n.statSync(r).mtimeMs + 6e5 > Date.now()) {
89
+ c.log("Using existing cookies.txt");
90
+ return;
91
+ }
92
+ console.log("Launching Chrome…");
93
+ const h = await g.launch({
94
+ headless: !1,
95
+ // 必須 false
96
+ userDataDir: f,
97
+ // 關鍵
98
+ defaultViewport: null,
99
+ args: ["--disable-blink-features=AutomationControlled"]
100
+ }), y = await h.newPage();
101
+ await y.goto("https://www.youtube.com", {
102
+ waitUntil: "networkidle2"
103
+ }), console.log("If not logged in, please log in manually."), console.log("Waiting 30 seconds…"), await new Promise((k) => setTimeout(k, 3e4));
104
+ const $ = (await y.cookies()).filter((k) => k.domain.includes("youtube.com") || k.domain.includes("google.com"));
105
+ $.length === 0 && (console.error("No YouTube cookies found. Are you logged in?"), process.exit(1));
106
+ const S = m($);
107
+ n.writeFileSync(r, S, { encoding: "utf8" }), console.log(`cookies.txt written to ${r}`), console.log(`Cookies count: ${$.length}`), await h.close();
108
+ })();
109
+ const b = [
110
+ `${o}`,
111
+ '-f "bv*[vcodec^=avc1][acodec^=mp4a][height<=1080]/ba/b"',
112
+ "--js-runtimes node",
113
+ `${d}`,
114
+ `-o "${e}/%(id)s.%(ext)s"`,
115
+ `--cookies ${r}`,
116
+ s.ffmpegDir ? `--ffmpeg-location "${s.ffmpegDir}"` : ""
117
+ ];
118
+ return x({
75
119
  debug: t,
76
- ytdlpPath: o,
77
- videoUrl: a,
78
- dest: r,
120
+ command: b.join(" "),
121
+ dest: i,
79
122
  tempDir: e,
80
- ffmpegConfig: i
123
+ ffmpegConfig: s
81
124
  });
82
- }, A = async ({
125
+ }, F = async ({
83
126
  videoId: t,
84
127
  dest: o,
85
- debug: n = !1,
86
- headless: r = !0
128
+ debug: a = !1,
129
+ headless: i = !0
87
130
  }) => {
88
131
  try {
89
- const e = d(n);
132
+ const e = v(a);
90
133
  e.log(`Downloading video: ${t} to: ${o}`);
91
- const i = `https://m.facebook.com/watch/?v=${t}`, s = await u("fs"), a = await u("path"), g = await u("puppeteer");
92
- s.existsSync(a.dirname(o)) || (s.mkdirSync(a.dirname(o), { recursive: !0 }, 777), e.log(`建立 ${a.dirname(o)}`));
93
- const l = {};
94
- r || (l.headless = !1);
95
- const f = await g.launch(l);
134
+ const s = `https://m.facebook.com/watch/?v=${t}`, c = await u("fs"), n = await u("path"), l = await u("puppeteer");
135
+ c.existsSync(n.dirname(o)) || (c.mkdirSync(n.dirname(o), { recursive: !0 }, 777), e.log(`建立 ${n.dirname(o)}`));
136
+ const g = {};
137
+ i || (g.headless = !1);
138
+ const d = await l.launch(g);
96
139
  e.log("啟動 puppeteer");
97
- const w = await f.newPage();
98
- await w.setUserAgent(
140
+ const r = await d.newPage();
141
+ await r.setUserAgent(
99
142
  "'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1'"
100
- ), e.log("開新分頁"), e.log(`前往 ${i}`), await Promise.race([
101
- w.goto(i, {
102
- waitUntil: "networkidle0"
103
- }),
104
- w.waitForSelector("video")
105
- ]), e.log("找到 video 元素");
106
- const c = await w.$eval("video", (m) => m.getAttribute("src"));
107
- return e.log(`取得 video url: ${c}`), await f.close(), e.log("關閉 puppeteer"), await S(c, o), e.log(`下載完成 ${c}`), [null, !0];
143
+ ), e.log("開新分頁"), e.log(`前往 ${s}`), await r.goto(s, {
144
+ waitUntil: "networkidle2"
145
+ }), await r.waitForSelector("video"), e.log("找到 video 元素");
146
+ const m = await r.$eval("video", (w) => w.getAttribute("src"));
147
+ return e.log(`取得 video url: ${m}`), await d.close(), e.log("關閉 puppeteer"), await U(m, o), e.log(`下載完成 ${m}`), [null, !0];
108
148
  } catch (e) {
109
149
  return [e, null];
110
150
  }
111
- }, F = async ({
151
+ }, M = async ({
112
152
  debug: t = !1,
113
153
  ytdlpPath: o,
114
- videoId: n,
115
- dest: r,
154
+ videoId: a,
155
+ dest: i,
116
156
  tempDir: e,
117
- ffmpegConfig: i
157
+ ffmpegConfig: s
118
158
  }) => {
119
- d(t).log(`Downloading video: ${n} to: ${r}`);
120
- const a = `https://vimeo.com/${n}`;
121
- return v({
159
+ v(t).log(`Downloading video: ${a} to: ${i}`);
160
+ const n = `https://vimeo.com/${a}`, l = [
161
+ `${o}`,
162
+ '-f "bv*[vcodec^=avc1][acodec^=mp4a][height<=1080]/ba/b"',
163
+ "--js-runtimes node",
164
+ `${n}`,
165
+ `-o "${e}/%(id)s.%(ext)s"`
166
+ ];
167
+ return x({
122
168
  debug: t,
123
- ytdlpPath: o,
124
- videoUrl: a,
125
- dest: r,
169
+ command: l.join(" "),
170
+ dest: i,
126
171
  tempDir: e,
127
- ffmpegConfig: i
172
+ ffmpegConfig: s
128
173
  });
129
- }, M = async ({
174
+ }, E = async ({
130
175
  debug: t = !1,
131
176
  ytdlpPath: o,
132
- videoId: n,
133
- dest: r,
177
+ videoId: a,
178
+ dest: i,
134
179
  tempDir: e,
135
- ffmpegConfig: i
180
+ ffmpegConfig: s
136
181
  }) => {
137
- d(t).log(`Downloading video: ${n} to: ${r}`);
138
- const a = `https://www.instagram.com/reel/${n}/`;
139
- return v({
182
+ v(t).log(`Downloading video: ${a} to: ${i}`);
183
+ const n = `https://www.instagram.com/reel/${a}/`, l = [
184
+ `${o}`,
185
+ "-f mergeall",
186
+ "--audio-multistreams",
187
+ "--video-multistreams",
188
+ "--js-runtimes node",
189
+ `${n}`,
190
+ "--downloader ffmpeg",
191
+ `-o "${e}/%(id)s.%(ext)s"`,
192
+ "--merge-output-format mp4",
193
+ s.ffmpegDir ? `--ffmpeg-location "${s.ffmpegDir}"` : ""
194
+ ];
195
+ return x({
140
196
  debug: t,
141
- ytdlpPath: o,
142
- videoUrl: a,
143
- dest: r,
197
+ command: l.join(" "),
198
+ dest: i,
144
199
  tempDir: e,
145
- ffmpegConfig: i
200
+ ffmpegConfig: s
146
201
  });
147
- }, D = async ({
202
+ }, _ = async ({
148
203
  videoLink: t,
149
204
  dest: o,
150
- debug: n = !1,
151
- headless: r = !0
205
+ debug: a = !1,
206
+ headless: i = !0
152
207
  }) => {
153
208
  try {
154
- const e = d(n);
209
+ const e = v(a);
155
210
  e.log(`Downloading video: ${t} to: ${o}`);
156
- const i = t, s = await u("fs"), a = await u("path"), g = await u("puppeteer");
157
- s.existsSync(a.dirname(o)) || (s.mkdirSync(a.dirname(o), { recursive: !0 }, 777), e.log(`建立 ${a.dirname(o)}`));
158
- const l = {};
159
- r || (l.headless = !1);
160
- const f = await g.launch(l);
211
+ const s = t, c = await u("fs"), n = await u("path"), l = await u("puppeteer");
212
+ c.existsSync(n.dirname(o)) || (c.mkdirSync(n.dirname(o), { recursive: !0 }, 777), e.log(`建立 ${n.dirname(o)}`));
213
+ const g = {};
214
+ i || (g.headless = !1);
215
+ const d = await l.launch(g);
161
216
  e.log("啟動 puppeteer");
162
- const w = await f.newPage();
163
- e.log("開新分頁"), e.log(`前往 ${i}`), await Promise.race([
164
- w.goto(i, {
165
- waitUntil: "networkidle0"
166
- }),
167
- w.waitForSelector("video")
168
- ]), e.log("找到 video 元素");
169
- const c = await w.$eval(
217
+ const r = await d.newPage();
218
+ e.log("開新分頁"), e.log(`前往 ${s}`), await r.goto(s, {
219
+ waitUntil: "networkidle2"
220
+ }), await r.waitForSelector("video"), e.log("找到 video 元素");
221
+ const m = await r.$eval(
170
222
  'video source[src^="https://www.tiktok.com/aweme/v1/play/"]',
171
- (m) => m.getAttribute("src")
223
+ (w) => w.getAttribute("src")
172
224
  );
173
- return e.log(`取得 video url: ${c}`), await f.close(), e.log("關閉 puppeteer"), await S(c, o, {
225
+ return e.log(`取得 video url: ${m}`), await d.close(), e.log("關閉 puppeteer"), await U(m, o, {
174
226
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
175
227
  Referer: "https://www.tiktok.com/"
176
228
  // 設定 Referer
177
- }), e.log(`下載完成 ${c}`), [null, !0];
229
+ }), e.log(`下載完成 ${m}`), [null, !0];
178
230
  } catch (e) {
179
231
  return [e, null];
180
232
  }
181
- }, T = ({ type: t }) => {
233
+ }, W = ({ type: t }) => {
182
234
  switch (t) {
183
235
  case "youtube":
184
236
  case "yt-short":
185
- return U;
237
+ return D;
186
238
  case "facebook":
187
239
  case "fb-reel":
188
- return A;
189
- case "vimeo":
190
240
  return F;
241
+ case "vimeo":
242
+ return M;
191
243
  case "instagram":
192
244
  case "ig":
193
245
  case "ig-reel":
194
- return M;
246
+ return E;
195
247
  case "tiktok":
196
248
  case "tiktok-reel":
197
- return D;
249
+ return _;
198
250
  default:
199
251
  throw new Error(`Invalid video type: ${t}`);
200
252
  }
201
253
  };
202
254
  export {
203
- T as useDownloader,
204
- A as useFacebook,
205
- M as useInstagram,
206
- D as useTiktok,
207
- F as useVimeo,
208
- U as useYoutube
255
+ W as useDownloader,
256
+ F as useFacebook,
257
+ E as useInstagram,
258
+ _ as useTiktok,
259
+ M as useVimeo,
260
+ D as useYoutube
209
261
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pieda/video-dl",
3
3
  "private": false,
4
- "version": "1.10.3",
4
+ "version": "1.11.0",
5
5
  "type": "module",
6
6
  "main": "dist/video-dl.cjs",
7
7
  "module": "dist/video-dl.js",