@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.
- package/dist/types/composables/useInstagram.d.ts +1 -0
- package/dist/types/composables/useVimeo.d.ts +1 -0
- package/dist/types/composables/useYoutube.d.ts +1 -0
- package/dist/types/composables/useYtdlp.d.ts +3 -3
- package/dist/video-dl.cjs +5 -1
- package/dist/video-dl.js +175 -123
- package/package.json +1 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
type TUseYtdlp = {
|
|
2
2
|
debug?: boolean;
|
|
3
|
-
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
9
|
-
import(t).then((
|
|
10
|
-
}),
|
|
11
|
-
const
|
|
12
|
-
return console.log(`Downloading ${t} to ${o}`), new Promise((
|
|
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:
|
|
16
|
-
}).then((
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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(
|
|
23
|
+
}).catch(c);
|
|
24
24
|
});
|
|
25
|
-
},
|
|
25
|
+
}, x = async ({
|
|
26
26
|
debug: t = !1,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ffmpegConfig: i
|
|
27
|
+
command: o,
|
|
28
|
+
dest: a,
|
|
29
|
+
tempDir: i,
|
|
30
|
+
ffmpegConfig: e
|
|
32
31
|
}) => {
|
|
33
|
-
const s =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
38
|
+
r();
|
|
43
39
|
});
|
|
44
40
|
});
|
|
45
|
-
return
|
|
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
|
|
48
|
-
let
|
|
49
|
-
const
|
|
50
|
-
for (const
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
|
|
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 (!
|
|
53
|
+
if (!w)
|
|
58
54
|
throw new Error("無法下載影音正常的影片");
|
|
59
|
-
s.log(`下載完成 ${
|
|
60
|
-
} catch (
|
|
61
|
-
s.error(`下載失敗: ${
|
|
55
|
+
s.log(`下載完成 ${a}`), r([null, !0]);
|
|
56
|
+
} catch (w) {
|
|
57
|
+
s.error(`下載失敗: ${w.message}`), r([w, null]);
|
|
62
58
|
}
|
|
63
59
|
});
|
|
64
|
-
},
|
|
60
|
+
}, D = async ({
|
|
65
61
|
debug: t = !1,
|
|
66
62
|
ytdlpPath: o,
|
|
67
|
-
videoId:
|
|
68
|
-
dest:
|
|
63
|
+
videoId: a,
|
|
64
|
+
dest: i,
|
|
69
65
|
tempDir: e,
|
|
70
|
-
ffmpegConfig:
|
|
66
|
+
ffmpegConfig: s
|
|
71
67
|
}) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
dest: r,
|
|
120
|
+
command: b.join(" "),
|
|
121
|
+
dest: i,
|
|
79
122
|
tempDir: e,
|
|
80
|
-
ffmpegConfig:
|
|
123
|
+
ffmpegConfig: s
|
|
81
124
|
});
|
|
82
|
-
},
|
|
125
|
+
}, F = async ({
|
|
83
126
|
videoId: t,
|
|
84
127
|
dest: o,
|
|
85
|
-
debug:
|
|
86
|
-
headless:
|
|
128
|
+
debug: a = !1,
|
|
129
|
+
headless: i = !0
|
|
87
130
|
}) => {
|
|
88
131
|
try {
|
|
89
|
-
const e =
|
|
132
|
+
const e = v(a);
|
|
90
133
|
e.log(`Downloading video: ${t} to: ${o}`);
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
const
|
|
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
|
|
98
|
-
await
|
|
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(`前往 ${
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
},
|
|
151
|
+
}, M = async ({
|
|
112
152
|
debug: t = !1,
|
|
113
153
|
ytdlpPath: o,
|
|
114
|
-
videoId:
|
|
115
|
-
dest:
|
|
154
|
+
videoId: a,
|
|
155
|
+
dest: i,
|
|
116
156
|
tempDir: e,
|
|
117
|
-
ffmpegConfig:
|
|
157
|
+
ffmpegConfig: s
|
|
118
158
|
}) => {
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
dest: r,
|
|
169
|
+
command: l.join(" "),
|
|
170
|
+
dest: i,
|
|
126
171
|
tempDir: e,
|
|
127
|
-
ffmpegConfig:
|
|
172
|
+
ffmpegConfig: s
|
|
128
173
|
});
|
|
129
|
-
},
|
|
174
|
+
}, E = async ({
|
|
130
175
|
debug: t = !1,
|
|
131
176
|
ytdlpPath: o,
|
|
132
|
-
videoId:
|
|
133
|
-
dest:
|
|
177
|
+
videoId: a,
|
|
178
|
+
dest: i,
|
|
134
179
|
tempDir: e,
|
|
135
|
-
ffmpegConfig:
|
|
180
|
+
ffmpegConfig: s
|
|
136
181
|
}) => {
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
dest: r,
|
|
197
|
+
command: l.join(" "),
|
|
198
|
+
dest: i,
|
|
144
199
|
tempDir: e,
|
|
145
|
-
ffmpegConfig:
|
|
200
|
+
ffmpegConfig: s
|
|
146
201
|
});
|
|
147
|
-
},
|
|
202
|
+
}, _ = async ({
|
|
148
203
|
videoLink: t,
|
|
149
204
|
dest: o,
|
|
150
|
-
debug:
|
|
151
|
-
headless:
|
|
205
|
+
debug: a = !1,
|
|
206
|
+
headless: i = !0
|
|
152
207
|
}) => {
|
|
153
208
|
try {
|
|
154
|
-
const e =
|
|
209
|
+
const e = v(a);
|
|
155
210
|
e.log(`Downloading video: ${t} to: ${o}`);
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
const
|
|
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
|
|
163
|
-
e.log("開新分頁"), e.log(`前往 ${
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
(
|
|
223
|
+
(w) => w.getAttribute("src")
|
|
172
224
|
);
|
|
173
|
-
return e.log(`取得 video url: ${
|
|
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(`下載完成 ${
|
|
229
|
+
}), e.log(`下載完成 ${m}`), [null, !0];
|
|
178
230
|
} catch (e) {
|
|
179
231
|
return [e, null];
|
|
180
232
|
}
|
|
181
|
-
},
|
|
233
|
+
}, W = ({ type: t }) => {
|
|
182
234
|
switch (t) {
|
|
183
235
|
case "youtube":
|
|
184
236
|
case "yt-short":
|
|
185
|
-
return
|
|
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
|
|
246
|
+
return E;
|
|
195
247
|
case "tiktok":
|
|
196
248
|
case "tiktok-reel":
|
|
197
|
-
return
|
|
249
|
+
return _;
|
|
198
250
|
default:
|
|
199
251
|
throw new Error(`Invalid video type: ${t}`);
|
|
200
252
|
}
|
|
201
253
|
};
|
|
202
254
|
export {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
};
|