@pieda/video-dl 1.9.0 → 1.10.2

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.
@@ -4,3 +4,4 @@ export { useFacebook } from './useFacebook';
4
4
  export { useVimeo } from './useVimeo';
5
5
  export { useInstagram } from './useInstagram';
6
6
  export { useTiktok } from './useTiktok';
7
+ export { useYtdlp } from './useYtdlp';
@@ -1,8 +1,14 @@
1
1
  type TUseInstagram = {
2
+ debug?: boolean;
2
3
  ytdlpPath: string;
3
4
  videoId: string;
4
5
  dest: string;
5
- debug?: boolean;
6
+ tempDir: string;
7
+ ffmpegConfig: {
8
+ ffmpegPath: string;
9
+ ffmpegProbePath: string;
10
+ ffmpegPlayPath: string;
11
+ };
6
12
  };
7
- export declare const useInstagram: ({ ytdlpPath, videoId, dest, debug, }: TUseInstagram) => Promise<[Error | null, boolean | null]>;
13
+ export declare const useInstagram: ({ debug, ytdlpPath, videoId, dest, tempDir, ffmpegConfig, }: TUseInstagram) => Promise<[Error | null, boolean | null]>;
8
14
  export {};
@@ -1,9 +1,14 @@
1
1
  type TUseVimeo = {
2
+ debug?: boolean;
2
3
  ytdlpPath: string;
3
4
  videoId: string;
4
5
  dest: string;
5
- downloadBtnSelector?: string;
6
- debug?: boolean;
6
+ tempDir: string;
7
+ ffmpegConfig: {
8
+ ffmpegPath: string;
9
+ ffmpegProbePath: string;
10
+ ffmpegPlayPath: string;
11
+ };
7
12
  };
8
- export declare const useVimeo: ({ ytdlpPath, videoId, dest, debug, }: TUseVimeo) => Promise<[Error | null, boolean | null]>;
13
+ export declare const useVimeo: ({ debug, ytdlpPath, videoId, dest, tempDir, ffmpegConfig, }: TUseVimeo) => Promise<[Error | null, boolean | null]>;
9
14
  export {};
@@ -3,6 +3,12 @@ type TUseYoutube = {
3
3
  videoId: string;
4
4
  dest: string;
5
5
  debug?: boolean;
6
+ tempDir: string;
7
+ ffmpegConfig: {
8
+ ffmpegPath: string;
9
+ ffmpegProbePath: string;
10
+ ffmpegPlayPath: string;
11
+ };
6
12
  };
7
- export declare const useYoutube: ({ ytdlpPath, videoId, dest, debug, }: TUseYoutube) => Promise<[Error | null, boolean | null]>;
13
+ export declare const useYoutube: ({ debug, ytdlpPath, videoId, dest, tempDir, ffmpegConfig, }: TUseYoutube) => Promise<[Error | null, boolean | null]>;
8
14
  export {};
@@ -0,0 +1,14 @@
1
+ type TUseYtdlp = {
2
+ debug?: boolean;
3
+ ytdlpPath: string;
4
+ videoUrl: string;
5
+ dest: string;
6
+ tempDir: string;
7
+ ffmpegConfig: {
8
+ ffmpegPath: string;
9
+ ffmpegProbePath: string;
10
+ ffmpegPlayPath: string;
11
+ };
12
+ };
13
+ export declare const useYtdlp: ({ debug, ytdlpPath, videoUrl, dest, tempDir, ffmpegConfig, }: TUseYtdlp) => Promise<[Error | null, boolean | null]>;
14
+ export {};
package/dist/video-dl.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=i=>new Promise((r,t)=>{import(i).then(g=>r(g.default)).catch(t)}),f=async(i,r,t)=>{const g=await l("fs"),e=await l("axios");return console.log(`Downloading ${i} to ${r}`),new Promise((w,s)=>{e.get(i,{responseType:"stream",headers:t}).then(u=>{const p=u.data,a=g.createWriteStream(r);p.pipe(a),a.on("finish",function(){a.close(()=>{w()})})}).catch(s)})},d=(i=!1)=>({log:(...r)=>{i&&console.log(...r)},error:(...r)=>{i&&console.error(...r)}}),y=async({ytdlpPath:i,videoId:r,dest:t,debug:g=!1})=>{const e=d(g);e.log(`Downloading video: ${r} to: ${t}`);const w=await l("fs"),s=await l("path"),{exec:u}=await l("child_process"),p=(a="")=>new Promise((c,o)=>{const n=`${i} -f b -g https://www.youtube.com/watch?v=${a}`;e.log(`[yt-dlp] 執行命令: ${n}`),u(n,(m,h,$)=>{if(e.log(`[yt-dlp] stdout: ${h}`),!h.includes("https://")){c("");return}c(h)})});return w.existsSync(s.dirname(t))||(w.mkdirSync(s.dirname(t),{recursive:!0},777),e.log(`建立 ${s.dirname(t)}`)),new Promise(async(a,c)=>{try{const o=await p(r);if(!o)throw new Error("無法取得 videoUrl");e.log(`取得 videoUrl ${o}`),await f(o,t).catch(n=>{throw e.error(`下載失敗: ${n.message}`),n}),e.log(`下載完成 ${t}`),a([null,!0])}catch(o){e.error(`下載失敗: ${o.message}`),a([o,null])}})},k=async({videoId:i,dest:r,debug:t=!1,headless:g=!0})=>{try{const e=d(t);e.log(`Downloading video: ${i} to: ${r}`);const w=`https://m.facebook.com/watch/?v=${i}`,s=await l("fs"),u=await l("path"),p=await l("puppeteer");s.existsSync(u.dirname(r))||(s.mkdirSync(u.dirname(r),{recursive:!0},777),e.log(`建立 ${u.dirname(r)}`));const a={};g||(a.headless=!1);const c=await p.launch(a);e.log("啟動 puppeteer");const o=await c.newPage();await o.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(`前往 ${w}`),await Promise.race([o.goto(w,{waitUntil:"networkidle0"}),o.waitForSelector("video")]),e.log("找到 video 元素");const n=await o.$eval("video",m=>m.getAttribute("src"));return e.log(`取得 video url: ${n}`),await c.close(),e.log("關閉 puppeteer"),await f(n,r),e.log(`下載完成 ${n}`),[null,!0]}catch(e){return[e,null]}},v=async({ytdlpPath:i,videoId:r,dest:t,debug:g=!1})=>{const e=d(g);e.log(`Downloading video: ${r} to: ${t}`);const w=await l("fs"),s=await l("path"),{exec:u}=await l("child_process"),p=(a="")=>new Promise((c,o)=>{const n=`${i} -f b -g https://vimeo.com/${a}`;console.log(`執行命令: ${n}`),u(n,(m,h,$)=>{if(e.log(`yt-dlp stdout: ${h}`),!h.includes("https://")){c("");return}c(h)})});return w.existsSync(s.dirname(t))||(w.mkdirSync(s.dirname(t),{recursive:!0},777),e.log(`建立 ${s.dirname(t)}`)),new Promise(async(a,c)=>{try{const o=await p(r);if(!o)throw new Error("無法取得 videoUrl");e.log(`取得 videoUrl ${o}`),await f(o,t).catch(n=>{throw e.error(`下載失敗: ${n.message}`),n}),e.log(`下載完成 ${t}`),a([null,!0])}catch(o){e.error(`下載失敗: ${o.message}`),a([o,null])}})},b=async({ytdlpPath:i,videoId:r,dest:t,debug:g=!1})=>{const e=d(g);e.log(`Downloading video: ${r} to: ${t}`);const w=await l("fs"),s=await l("path"),{exec:u}=await l("child_process"),p=(a="")=>new Promise((c,o)=>{const n=`https://www.instagram.com/reel/${a}/`,m=`${i} -f b -g ${n}`;console.log(`執行命令: ${m}`),u(m,(h,$,P)=>{if(e.log(`yt-dlp stdout: ${$}`),!$.includes("https://")){c("");return}c($)})});return w.existsSync(s.dirname(t))||(w.mkdirSync(s.dirname(t),{recursive:!0},777),e.log(`建立 ${s.dirname(t)}`)),new Promise(async(a,c)=>{try{const o=await p(r);if(!o)throw new Error("無法取得 videoUrl");e.log(`取得 videoUrl ${o}`),await f(o,t).catch(n=>{throw e.error(`下載失敗: ${n.message}`),n}),e.log(`下載完成 ${t}`),a([null,!0])}catch(o){e.error(`下載失敗: ${o.message}`),a([o,null])}})},S=async({videoLink:i,dest:r,debug:t=!1,headless:g=!0})=>{try{const e=d(t);e.log(`Downloading video: ${i} to: ${r}`);const w=i,s=await l("fs"),u=await l("path"),p=await l("puppeteer");s.existsSync(u.dirname(r))||(s.mkdirSync(u.dirname(r),{recursive:!0},777),e.log(`建立 ${u.dirname(r)}`));const a={};g||(a.headless=!1);const c=await p.launch(a);e.log("啟動 puppeteer");const o=await c.newPage();e.log("開新分頁"),e.log(`前往 ${w}`),await Promise.race([o.goto(w,{waitUntil:"networkidle0"}),o.waitForSelector("video")]),e.log("找到 video 元素");const n=await o.$eval('video source[src^="https://www.tiktok.com/aweme/v1/play/"]',m=>m.getAttribute("src"));return e.log(`取得 video url: ${n}`),await c.close(),e.log("關閉 puppeteer"),await f(n,r,{"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(`下載完成 ${n}`),[null,!0]}catch(e){return[e,null]}},U=({type:i})=>{switch(i){case"youtube":case"yt-short":return y;case"facebook":case"fb-reel":return k;case"vimeo":return v;case"instagram":case"ig":case"ig-reel":return b;case"tiktok":case"tiktok-reel":return S;default:throw new Error(`Invalid video type: ${i}`)}};exports.useDownloader=U;exports.useFacebook=k;exports.useInstagram=b;exports.useTiktok=S;exports.useVimeo=v;exports.useYoutube=y;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=(e=!1)=>({log:(...o)=>{e&&console.log(...o)},error:(...o)=>{e&&console.error(...o)}});var s=[];for(var S=0;S<256;++S)s.push((S+256).toString(16).slice(1));function E(e,o=0){return(s[e[o+0]]+s[e[o+1]]+s[e[o+2]]+s[e[o+3]]+"-"+s[e[o+4]]+s[e[o+5]]+"-"+s[e[o+6]]+s[e[o+7]]+"-"+s[e[o+8]]+s[e[o+9]]+"-"+s[e[o+10]]+s[e[o+11]]+s[e[o+12]]+s[e[o+13]]+s[e[o+14]]+s[e[o+15]]).toLowerCase()}var $,I=new Uint8Array(16);function K(){if(!$&&($=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!$))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return $(I)}var _=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto);const D={randomUUID:_};function C(e,o,n){if(D.randomUUID&&!o&&!e)return D.randomUUID();e=e||{};var r=e.random||(e.rng||K)();if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,o){n=n||0;for(var t=0;t<16;++t)o[n+t]=r[t];return o}return E(r)}const w=e=>new Promise((o,n)=>{import(e).then(r=>o(r.default)).catch(n)}),P=async(e,o,n)=>{const r=await w("fs"),t=await w("axios");return console.log(`Downloading ${e} to ${o}`),new Promise((c,i)=>{t.get(e,{responseType:"stream",headers:n}).then(a=>{const u=a.data,g=r.createWriteStream(o);u.pipe(g),g.on("finish",function(){g.close(()=>{c()})})}).catch(i)})},U=async({debug:e=!1,ytdlpPath:o,videoUrl:n,dest:r,tempDir:t,ffmpegConfig:c})=>{const i=h(e);i.log(`Downloading video: ${n} to: ${r}`);const a=await w("fs"),u=await w("path"),{exec:g,execSync:y}=await w("child_process"),l=u.join(t,C()),p=()=>new Promise((d,b)=>{const m=`${o} -f mergeall --audio-multistreams --video-multistreams ${n} --downloader ffmpeg -o "${l}/%(id)s.%(ext)s" --merge-output-format mp4`;i.log(`[yt-dlp] 執行命令: ${m}`),g(m,(v,f,k)=>{if(i.log(`[yt-dlp] stdout: ${f}`),v){b(v);return}d()})});return a.existsSync(u.dirname(r))||(a.mkdirSync(u.dirname(r),{recursive:!0},777),i.log(`建立 ${u.dirname(r)}`)),new Promise(async(d,b)=>{try{await p();let m=!1;const v=a.readdirSync(l);for(const f of v){const k=u.join(l,f),j=`${c.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${k}"`,x=y(j).toString("utf-8"),R=x.includes("video"),W=x.includes("audio");if(R&&W){m=!0,a.copyFileSync(k,r);break}}if(!m)throw new Error("無法下載影音正常的影片");i.log(`下載完成 ${r}`),d([null,!0])}catch(m){i.error(`下載失敗: ${m.message}`),d([m,null])}})},A=async({debug:e=!1,ytdlpPath:o,videoId:n,dest:r,tempDir:t,ffmpegConfig:c})=>{h(e).log(`Downloading video: ${n} to: ${r}`);const a=`https://www.youtube.com/watch?v=${n}`;return U({debug:e,ytdlpPath:o,videoUrl:a,dest:r,tempDir:t,ffmpegConfig:c})},F=async({videoId:e,dest:o,debug:n=!1,headless:r=!0})=>{try{const t=h(n);t.log(`Downloading video: ${e} to: ${o}`);const c=`https://m.facebook.com/watch/?v=${e}`,i=await w("fs"),a=await w("path"),u=await w("puppeteer");i.existsSync(a.dirname(o))||(i.mkdirSync(a.dirname(o),{recursive:!0},777),t.log(`建立 ${a.dirname(o)}`));const g={};r||(g.headless=!1);const y=await u.launch(g);t.log("啟動 puppeteer");const l=await y.newPage();await l.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'"),t.log("開新分頁"),t.log(`前往 ${c}`),await Promise.race([l.goto(c,{waitUntil:"networkidle0"}),l.waitForSelector("video")]),t.log("找到 video 元素");const p=await l.$eval("video",d=>d.getAttribute("src"));return t.log(`取得 video url: ${p}`),await y.close(),t.log("關閉 puppeteer"),await P(p,o),t.log(`下載完成 ${p}`),[null,!0]}catch(t){return[t,null]}},M=async({debug:e=!1,ytdlpPath:o,videoId:n,dest:r,tempDir:t,ffmpegConfig:c})=>{h(e).log(`Downloading video: ${n} to: ${r}`);const a=`https://vimeo.com/${n}`;return U({debug:e,ytdlpPath:o,videoUrl:a,dest:r,tempDir:t,ffmpegConfig:c})},T=async({debug:e=!1,ytdlpPath:o,videoId:n,dest:r,tempDir:t,ffmpegConfig:c})=>{h(e).log(`Downloading video: ${n} to: ${r}`);const a=`https://www.instagram.com/reel/${n}/`;return U({debug:e,ytdlpPath:o,videoUrl:a,dest:r,tempDir:t,ffmpegConfig:c})},V=async({videoLink:e,dest:o,debug:n=!1,headless:r=!0})=>{try{const t=h(n);t.log(`Downloading video: ${e} to: ${o}`);const c=e,i=await w("fs"),a=await w("path"),u=await w("puppeteer");i.existsSync(a.dirname(o))||(i.mkdirSync(a.dirname(o),{recursive:!0},777),t.log(`建立 ${a.dirname(o)}`));const g={};r||(g.headless=!1);const y=await u.launch(g);t.log("啟動 puppeteer");const l=await y.newPage();t.log("開新分頁"),t.log(`前往 ${c}`),await Promise.race([l.goto(c,{waitUntil:"networkidle0"}),l.waitForSelector("video")]),t.log("找到 video 元素");const p=await l.$eval('video source[src^="https://www.tiktok.com/aweme/v1/play/"]',d=>d.getAttribute("src"));return t.log(`取得 video url: ${p}`),await y.close(),t.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/"}),t.log(`下載完成 ${p}`),[null,!0]}catch(t){return[t,null]}},H=({type:e})=>{switch(e){case"youtube":case"yt-short":return A;case"facebook":case"fb-reel":return F;case"vimeo":return M;case"instagram":case"ig":case"ig-reel":return T;case"tiktok":case"tiktok-reel":return V;default:throw new Error(`Invalid video type: ${e}`)}};exports.useDownloader=H;exports.useFacebook=F;exports.useInstagram=T;exports.useTiktok=V;exports.useVimeo=M;exports.useYoutube=A;
package/dist/video-dl.js CHANGED
@@ -1,206 +1,239 @@
1
- const l = (i) => new Promise((r, t) => {
2
- import(i).then((u) => r(u.default)).catch(t);
3
- }), f = async (i, r, t) => {
4
- const u = await l("fs"), e = await l("axios");
5
- return console.log(`Downloading ${i} to ${r}`), new Promise((w, c) => {
6
- e.get(i, {
1
+ const h = (e = !1) => ({
2
+ log: (...o) => {
3
+ e && console.log(...o);
4
+ },
5
+ error: (...o) => {
6
+ e && console.error(...o);
7
+ }
8
+ });
9
+ var c = [];
10
+ for (var U = 0; U < 256; ++U)
11
+ c.push((U + 256).toString(16).slice(1));
12
+ function V(e, o = 0) {
13
+ return (c[e[o + 0]] + c[e[o + 1]] + c[e[o + 2]] + c[e[o + 3]] + "-" + c[e[o + 4]] + c[e[o + 5]] + "-" + c[e[o + 6]] + c[e[o + 7]] + "-" + c[e[o + 8]] + c[e[o + 9]] + "-" + c[e[o + 10]] + c[e[o + 11]] + c[e[o + 12]] + c[e[o + 13]] + c[e[o + 14]] + c[e[o + 15]]).toLowerCase();
14
+ }
15
+ var v, T = new Uint8Array(16);
16
+ function R() {
17
+ if (!v && (v = typeof crypto < "u" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto), !v))
18
+ throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
19
+ return v(T);
20
+ }
21
+ var W = typeof crypto < "u" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
22
+ const P = {
23
+ randomUUID: W
24
+ };
25
+ function j(e, o, n) {
26
+ if (P.randomUUID && !o && !e)
27
+ return P.randomUUID();
28
+ e = e || {};
29
+ var r = e.random || (e.rng || R)();
30
+ if (r[6] = r[6] & 15 | 64, r[8] = r[8] & 63 | 128, o) {
31
+ n = n || 0;
32
+ for (var t = 0; t < 16; ++t)
33
+ o[n + t] = r[t];
34
+ return o;
35
+ }
36
+ return V(r);
37
+ }
38
+ const w = (e) => new Promise((o, n) => {
39
+ import(e).then((r) => o(r.default)).catch(n);
40
+ }), b = async (e, o, n) => {
41
+ const r = await w("fs"), t = await w("axios");
42
+ return console.log(`Downloading ${e} to ${o}`), new Promise((s, i) => {
43
+ t.get(e, {
7
44
  responseType: "stream",
8
- headers: t
9
- }).then((g) => {
10
- const p = g.data, a = u.createWriteStream(r);
11
- p.pipe(a), a.on("finish", function() {
12
- a.close(() => {
13
- w();
45
+ headers: n
46
+ }).then((a) => {
47
+ const u = a.data, g = r.createWriteStream(o);
48
+ u.pipe(g), g.on("finish", function() {
49
+ g.close(() => {
50
+ s();
14
51
  });
15
52
  });
16
- }).catch(c);
53
+ }).catch(i);
17
54
  });
18
- }, d = (i = !1) => ({
19
- log: (...r) => {
20
- i && console.log(...r);
21
- },
22
- error: (...r) => {
23
- i && console.error(...r);
24
- }
25
- }), y = async ({
26
- ytdlpPath: i,
27
- videoId: r,
28
- dest: t,
29
- debug: u = !1
55
+ }, S = async ({
56
+ debug: e = !1,
57
+ ytdlpPath: o,
58
+ videoUrl: n,
59
+ dest: r,
60
+ tempDir: t,
61
+ ffmpegConfig: s
30
62
  }) => {
31
- const e = d(u);
32
- e.log(`Downloading video: ${r} to: ${t}`);
33
- const w = await l("fs"), c = await l("path"), { exec: g } = await l("child_process"), p = (a = "") => new Promise((s, o) => {
34
- const n = `${i} -f b -g https://www.youtube.com/watch?v=${a}`;
35
- e.log(`[yt-dlp] 執行命令: ${n}`), g(n, (m, h, $) => {
36
- if (e.log(`[yt-dlp] stdout: ${h}`), !h.includes("https://")) {
37
- s("");
63
+ const i = h(e);
64
+ i.log(`Downloading video: ${n} to: ${r}`);
65
+ const a = await w("fs"), u = await w("path"), { exec: g, execSync: y } = await w("child_process"), l = u.join(t, j()), p = () => new Promise((d, x) => {
66
+ const m = `${o} -f mergeall --audio-multistreams --video-multistreams ${n} --downloader ffmpeg -o "${l}/%(id)s.%(ext)s" --merge-output-format mp4`;
67
+ i.log(`[yt-dlp] 執行命令: ${m}`), g(m, ($, f, k) => {
68
+ if (i.log(`[yt-dlp] stdout: ${f}`), $) {
69
+ x($);
38
70
  return;
39
71
  }
40
- s(h);
72
+ d();
41
73
  });
42
74
  });
43
- return w.existsSync(c.dirname(t)) || (w.mkdirSync(c.dirname(t), { recursive: !0 }, 777), e.log(`建立 ${c.dirname(t)}`)), new Promise(async (a, s) => {
75
+ return a.existsSync(u.dirname(r)) || (a.mkdirSync(u.dirname(r), { recursive: !0 }, 777), i.log(`建立 ${u.dirname(r)}`)), new Promise(async (d, x) => {
44
76
  try {
45
- const o = await p(r);
46
- if (!o)
47
- throw new Error("無法取得 videoUrl");
48
- e.log(`取得 videoUrl ${o}`), await f(o, t).catch((n) => {
49
- throw e.error(`下載失敗: ${n.message}`), n;
50
- }), e.log(`下載完成 ${t}`), a([null, !0]);
51
- } catch (o) {
52
- e.error(`下載失敗: ${o.message}`), a([o, null]);
77
+ await p();
78
+ let m = !1;
79
+ const $ = a.readdirSync(l);
80
+ for (const f of $) {
81
+ const k = u.join(l, f), A = `${s.ffmpegProbePath} -v error -show_entries stream=codec_type -of csv=p=0 "${k}"`, D = y(A).toString("utf-8"), F = D.includes("video"), M = D.includes("audio");
82
+ if (F && M) {
83
+ m = !0, a.copyFileSync(k, r);
84
+ break;
85
+ }
86
+ }
87
+ if (!m)
88
+ throw new Error("無法下載影音正常的影片");
89
+ i.log(`下載完成 ${r}`), d([null, !0]);
90
+ } catch (m) {
91
+ i.error(`下載失敗: ${m.message}`), d([m, null]);
53
92
  }
54
93
  });
55
- }, k = async ({
56
- videoId: i,
94
+ }, E = async ({
95
+ debug: e = !1,
96
+ ytdlpPath: o,
97
+ videoId: n,
57
98
  dest: r,
58
- debug: t = !1,
59
- headless: u = !0
99
+ tempDir: t,
100
+ ffmpegConfig: s
101
+ }) => {
102
+ h(e).log(`Downloading video: ${n} to: ${r}`);
103
+ const a = `https://www.youtube.com/watch?v=${n}`;
104
+ return S({
105
+ debug: e,
106
+ ytdlpPath: o,
107
+ videoUrl: a,
108
+ dest: r,
109
+ tempDir: t,
110
+ ffmpegConfig: s
111
+ });
112
+ }, K = async ({
113
+ videoId: e,
114
+ dest: o,
115
+ debug: n = !1,
116
+ headless: r = !0
60
117
  }) => {
61
118
  try {
62
- const e = d(t);
63
- e.log(`Downloading video: ${i} to: ${r}`);
64
- const w = `https://m.facebook.com/watch/?v=${i}`, c = await l("fs"), g = await l("path"), p = await l("puppeteer");
65
- c.existsSync(g.dirname(r)) || (c.mkdirSync(g.dirname(r), { recursive: !0 }, 777), e.log(`建立 ${g.dirname(r)}`));
66
- const a = {};
67
- u || (a.headless = !1);
68
- const s = await p.launch(a);
69
- e.log("啟動 puppeteer");
70
- const o = await s.newPage();
71
- await o.setUserAgent(
119
+ const t = h(n);
120
+ t.log(`Downloading video: ${e} to: ${o}`);
121
+ const s = `https://m.facebook.com/watch/?v=${e}`, i = await w("fs"), a = await w("path"), u = await w("puppeteer");
122
+ i.existsSync(a.dirname(o)) || (i.mkdirSync(a.dirname(o), { recursive: !0 }, 777), t.log(`建立 ${a.dirname(o)}`));
123
+ const g = {};
124
+ r || (g.headless = !1);
125
+ const y = await u.launch(g);
126
+ t.log("啟動 puppeteer");
127
+ const l = await y.newPage();
128
+ await l.setUserAgent(
72
129
  "'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'"
73
- ), e.log("開新分頁"), e.log(`前往 ${w}`), await Promise.race([
74
- o.goto(w, {
130
+ ), t.log("開新分頁"), t.log(`前往 ${s}`), await Promise.race([
131
+ l.goto(s, {
75
132
  waitUntil: "networkidle0"
76
133
  }),
77
- o.waitForSelector("video")
78
- ]), e.log("找到 video 元素");
79
- const n = await o.$eval("video", (m) => m.getAttribute("src"));
80
- return e.log(`取得 video url: ${n}`), await s.close(), e.log("關閉 puppeteer"), await f(n, r), e.log(`下載完成 ${n}`), [null, !0];
81
- } catch (e) {
82
- return [e, null];
134
+ l.waitForSelector("video")
135
+ ]), t.log("找到 video 元素");
136
+ const p = await l.$eval("video", (d) => d.getAttribute("src"));
137
+ return t.log(`取得 video url: ${p}`), await y.close(), t.log("關閉 puppeteer"), await b(p, o), t.log(`下載完成 ${p}`), [null, !0];
138
+ } catch (t) {
139
+ return [t, null];
83
140
  }
84
- }, v = async ({
85
- ytdlpPath: i,
86
- videoId: r,
87
- dest: t,
88
- debug: u = !1
141
+ }, _ = async ({
142
+ debug: e = !1,
143
+ ytdlpPath: o,
144
+ videoId: n,
145
+ dest: r,
146
+ tempDir: t,
147
+ ffmpegConfig: s
89
148
  }) => {
90
- const e = d(u);
91
- e.log(`Downloading video: ${r} to: ${t}`);
92
- const w = await l("fs"), c = await l("path"), { exec: g } = await l("child_process"), p = (a = "") => new Promise((s, o) => {
93
- const n = `${i} -f b -g https://vimeo.com/${a}`;
94
- console.log(`執行命令: ${n}`), g(n, (m, h, $) => {
95
- if (e.log(`yt-dlp stdout: ${h}`), !h.includes("https://")) {
96
- s("");
97
- return;
98
- }
99
- s(h);
100
- });
101
- });
102
- return w.existsSync(c.dirname(t)) || (w.mkdirSync(c.dirname(t), { recursive: !0 }, 777), e.log(`建立 ${c.dirname(t)}`)), new Promise(async (a, s) => {
103
- try {
104
- const o = await p(r);
105
- if (!o)
106
- throw new Error("無法取得 videoUrl");
107
- e.log(`取得 videoUrl ${o}`), await f(o, t).catch((n) => {
108
- throw e.error(`下載失敗: ${n.message}`), n;
109
- }), e.log(`下載完成 ${t}`), a([null, !0]);
110
- } catch (o) {
111
- e.error(`下載失敗: ${o.message}`), a([o, null]);
112
- }
149
+ h(e).log(`Downloading video: ${n} to: ${r}`);
150
+ const a = `https://vimeo.com/${n}`;
151
+ return S({
152
+ debug: e,
153
+ ytdlpPath: o,
154
+ videoUrl: a,
155
+ dest: r,
156
+ tempDir: t,
157
+ ffmpegConfig: s
113
158
  });
114
- }, S = async ({
115
- ytdlpPath: i,
116
- videoId: r,
117
- dest: t,
118
- debug: u = !1
159
+ }, C = async ({
160
+ debug: e = !1,
161
+ ytdlpPath: o,
162
+ videoId: n,
163
+ dest: r,
164
+ tempDir: t,
165
+ ffmpegConfig: s
119
166
  }) => {
120
- const e = d(u);
121
- e.log(`Downloading video: ${r} to: ${t}`);
122
- const w = await l("fs"), c = await l("path"), { exec: g } = await l("child_process"), p = (a = "") => new Promise((s, o) => {
123
- const n = `https://www.instagram.com/reel/${a}/`, m = `${i} -f b -g ${n}`;
124
- console.log(`執行命令: ${m}`), g(m, (h, $, b) => {
125
- if (e.log(`yt-dlp stdout: ${$}`), !$.includes("https://")) {
126
- s("");
127
- return;
128
- }
129
- s($);
130
- });
131
- });
132
- return w.existsSync(c.dirname(t)) || (w.mkdirSync(c.dirname(t), { recursive: !0 }, 777), e.log(`建立 ${c.dirname(t)}`)), new Promise(async (a, s) => {
133
- try {
134
- const o = await p(r);
135
- if (!o)
136
- throw new Error("無法取得 videoUrl");
137
- e.log(`取得 videoUrl ${o}`), await f(o, t).catch((n) => {
138
- throw e.error(`下載失敗: ${n.message}`), n;
139
- }), e.log(`下載完成 ${t}`), a([null, !0]);
140
- } catch (o) {
141
- e.error(`下載失敗: ${o.message}`), a([o, null]);
142
- }
167
+ h(e).log(`Downloading video: ${n} to: ${r}`);
168
+ const a = `https://www.instagram.com/reel/${n}/`;
169
+ return S({
170
+ debug: e,
171
+ ytdlpPath: o,
172
+ videoUrl: a,
173
+ dest: r,
174
+ tempDir: t,
175
+ ffmpegConfig: s
143
176
  });
144
- }, U = async ({
145
- videoLink: i,
146
- dest: r,
147
- debug: t = !1,
148
- headless: u = !0
177
+ }, H = async ({
178
+ videoLink: e,
179
+ dest: o,
180
+ debug: n = !1,
181
+ headless: r = !0
149
182
  }) => {
150
183
  try {
151
- const e = d(t);
152
- e.log(`Downloading video: ${i} to: ${r}`);
153
- const w = i, c = await l("fs"), g = await l("path"), p = await l("puppeteer");
154
- c.existsSync(g.dirname(r)) || (c.mkdirSync(g.dirname(r), { recursive: !0 }, 777), e.log(`建立 ${g.dirname(r)}`));
155
- const a = {};
156
- u || (a.headless = !1);
157
- const s = await p.launch(a);
158
- e.log("啟動 puppeteer");
159
- const o = await s.newPage();
160
- e.log("開新分頁"), e.log(`前往 ${w}`), await Promise.race([
161
- o.goto(w, {
184
+ const t = h(n);
185
+ t.log(`Downloading video: ${e} to: ${o}`);
186
+ const s = e, i = await w("fs"), a = await w("path"), u = await w("puppeteer");
187
+ i.existsSync(a.dirname(o)) || (i.mkdirSync(a.dirname(o), { recursive: !0 }, 777), t.log(`建立 ${a.dirname(o)}`));
188
+ const g = {};
189
+ r || (g.headless = !1);
190
+ const y = await u.launch(g);
191
+ t.log("啟動 puppeteer");
192
+ const l = await y.newPage();
193
+ t.log("開新分頁"), t.log(`前往 ${s}`), await Promise.race([
194
+ l.goto(s, {
162
195
  waitUntil: "networkidle0"
163
196
  }),
164
- o.waitForSelector("video")
165
- ]), e.log("找到 video 元素");
166
- const n = await o.$eval(
197
+ l.waitForSelector("video")
198
+ ]), t.log("找到 video 元素");
199
+ const p = await l.$eval(
167
200
  'video source[src^="https://www.tiktok.com/aweme/v1/play/"]',
168
- (m) => m.getAttribute("src")
201
+ (d) => d.getAttribute("src")
169
202
  );
170
- return e.log(`取得 video url: ${n}`), await s.close(), e.log("關閉 puppeteer"), await f(n, r, {
203
+ return t.log(`取得 video url: ${p}`), await y.close(), t.log("關閉 puppeteer"), await b(p, o, {
171
204
  "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",
172
205
  Referer: "https://www.tiktok.com/"
173
206
  // 設定 Referer
174
- }), e.log(`下載完成 ${n}`), [null, !0];
175
- } catch (e) {
176
- return [e, null];
207
+ }), t.log(`下載完成 ${p}`), [null, !0];
208
+ } catch (t) {
209
+ return [t, null];
177
210
  }
178
- }, P = ({ type: i }) => {
179
- switch (i) {
211
+ }, I = ({ type: e }) => {
212
+ switch (e) {
180
213
  case "youtube":
181
214
  case "yt-short":
182
- return y;
215
+ return E;
183
216
  case "facebook":
184
217
  case "fb-reel":
185
- return k;
218
+ return K;
186
219
  case "vimeo":
187
- return v;
220
+ return _;
188
221
  case "instagram":
189
222
  case "ig":
190
223
  case "ig-reel":
191
- return S;
224
+ return C;
192
225
  case "tiktok":
193
226
  case "tiktok-reel":
194
- return U;
227
+ return H;
195
228
  default:
196
- throw new Error(`Invalid video type: ${i}`);
229
+ throw new Error(`Invalid video type: ${e}`);
197
230
  }
198
231
  };
199
232
  export {
200
- P as useDownloader,
201
- k as useFacebook,
202
- S as useInstagram,
203
- U as useTiktok,
204
- v as useVimeo,
205
- y as useYoutube
233
+ I as useDownloader,
234
+ K as useFacebook,
235
+ C as useInstagram,
236
+ H as useTiktok,
237
+ _ as useVimeo,
238
+ E as useYoutube
206
239
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pieda/video-dl",
3
3
  "private": false,
4
- "version": "1.9.0",
4
+ "version": "1.10.2",
5
5
  "type": "module",
6
6
  "main": "dist/video-dl.cjs",
7
7
  "module": "dist/video-dl.js",
@@ -39,6 +39,7 @@
39
39
  "dependencies": {
40
40
  "axios": "^1.10.0",
41
41
  "puppeteer": "^22.13.1",
42
+ "uuid": "^10.0.0",
42
43
  "youtubei.js": "^14.0.0"
43
44
  },
44
45
  "devDependencies": {