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