@pieda/video-dl 1.10.2 → 1.10.3
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/video-dl.cjs +1 -1
- package/dist/video-dl.js +120 -150
- package/package.json +1 -1
package/dist/video-dl.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
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;
|
package/dist/video-dl.js
CHANGED
|
@@ -1,239 +1,209 @@
|
|
|
1
|
-
const
|
|
1
|
+
const d = (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
|
-
})
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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, {
|
|
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) => {
|
|
13
|
+
e.get(t, {
|
|
44
14
|
responseType: "stream",
|
|
45
15
|
headers: n
|
|
46
16
|
}).then((a) => {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
17
|
+
const g = a.data, l = r.createWriteStream(o);
|
|
18
|
+
g.pipe(l), l.on("finish", function() {
|
|
19
|
+
l.close(() => {
|
|
20
|
+
i();
|
|
51
21
|
});
|
|
52
22
|
});
|
|
53
|
-
}).catch(
|
|
23
|
+
}).catch(s);
|
|
54
24
|
});
|
|
55
|
-
},
|
|
56
|
-
debug:
|
|
25
|
+
}, v = async ({
|
|
26
|
+
debug: t = !1,
|
|
57
27
|
ytdlpPath: o,
|
|
58
28
|
videoUrl: n,
|
|
59
29
|
dest: r,
|
|
60
|
-
tempDir:
|
|
61
|
-
ffmpegConfig:
|
|
30
|
+
tempDir: e,
|
|
31
|
+
ffmpegConfig: i
|
|
62
32
|
}) => {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const a = await
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
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);
|
|
70
40
|
return;
|
|
71
41
|
}
|
|
72
|
-
|
|
42
|
+
c();
|
|
73
43
|
});
|
|
74
44
|
});
|
|
75
|
-
return a.existsSync(
|
|
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) => {
|
|
76
46
|
try {
|
|
77
|
-
await
|
|
78
|
-
let
|
|
79
|
-
const
|
|
80
|
-
for (const
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
83
|
-
|
|
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);
|
|
84
54
|
break;
|
|
85
55
|
}
|
|
86
56
|
}
|
|
87
|
-
if (!
|
|
57
|
+
if (!p)
|
|
88
58
|
throw new Error("無法下載影音正常的影片");
|
|
89
|
-
|
|
90
|
-
} catch (
|
|
91
|
-
|
|
59
|
+
s.log(`下載完成 ${r}`), c([null, !0]);
|
|
60
|
+
} catch (p) {
|
|
61
|
+
s.error(`下載失敗: ${p.message}`), c([p, null]);
|
|
92
62
|
}
|
|
93
63
|
});
|
|
94
|
-
},
|
|
95
|
-
debug:
|
|
64
|
+
}, U = async ({
|
|
65
|
+
debug: t = !1,
|
|
96
66
|
ytdlpPath: o,
|
|
97
67
|
videoId: n,
|
|
98
68
|
dest: r,
|
|
99
|
-
tempDir:
|
|
100
|
-
ffmpegConfig:
|
|
69
|
+
tempDir: e,
|
|
70
|
+
ffmpegConfig: i
|
|
101
71
|
}) => {
|
|
102
|
-
|
|
72
|
+
d(t).log(`Downloading video: ${n} to: ${r}`);
|
|
103
73
|
const a = `https://www.youtube.com/watch?v=${n}`;
|
|
104
|
-
return
|
|
105
|
-
debug:
|
|
74
|
+
return v({
|
|
75
|
+
debug: t,
|
|
106
76
|
ytdlpPath: o,
|
|
107
77
|
videoUrl: a,
|
|
108
78
|
dest: r,
|
|
109
|
-
tempDir:
|
|
110
|
-
ffmpegConfig:
|
|
79
|
+
tempDir: e,
|
|
80
|
+
ffmpegConfig: i
|
|
111
81
|
});
|
|
112
|
-
},
|
|
113
|
-
videoId:
|
|
82
|
+
}, A = async ({
|
|
83
|
+
videoId: t,
|
|
114
84
|
dest: o,
|
|
115
85
|
debug: n = !1,
|
|
116
86
|
headless: r = !0
|
|
117
87
|
}) => {
|
|
118
88
|
try {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
r || (
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
await
|
|
89
|
+
const e = d(n);
|
|
90
|
+
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);
|
|
96
|
+
e.log("啟動 puppeteer");
|
|
97
|
+
const w = await f.newPage();
|
|
98
|
+
await w.setUserAgent(
|
|
129
99
|
"'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'"
|
|
130
|
-
),
|
|
131
|
-
|
|
100
|
+
), e.log("開新分頁"), e.log(`前往 ${i}`), await Promise.race([
|
|
101
|
+
w.goto(i, {
|
|
132
102
|
waitUntil: "networkidle0"
|
|
133
103
|
}),
|
|
134
|
-
|
|
135
|
-
]),
|
|
136
|
-
const
|
|
137
|
-
return
|
|
138
|
-
} catch (
|
|
139
|
-
return [
|
|
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];
|
|
108
|
+
} catch (e) {
|
|
109
|
+
return [e, null];
|
|
140
110
|
}
|
|
141
|
-
},
|
|
142
|
-
debug:
|
|
111
|
+
}, F = async ({
|
|
112
|
+
debug: t = !1,
|
|
143
113
|
ytdlpPath: o,
|
|
144
114
|
videoId: n,
|
|
145
115
|
dest: r,
|
|
146
|
-
tempDir:
|
|
147
|
-
ffmpegConfig:
|
|
116
|
+
tempDir: e,
|
|
117
|
+
ffmpegConfig: i
|
|
148
118
|
}) => {
|
|
149
|
-
|
|
119
|
+
d(t).log(`Downloading video: ${n} to: ${r}`);
|
|
150
120
|
const a = `https://vimeo.com/${n}`;
|
|
151
|
-
return
|
|
152
|
-
debug:
|
|
121
|
+
return v({
|
|
122
|
+
debug: t,
|
|
153
123
|
ytdlpPath: o,
|
|
154
124
|
videoUrl: a,
|
|
155
125
|
dest: r,
|
|
156
|
-
tempDir:
|
|
157
|
-
ffmpegConfig:
|
|
126
|
+
tempDir: e,
|
|
127
|
+
ffmpegConfig: i
|
|
158
128
|
});
|
|
159
|
-
},
|
|
160
|
-
debug:
|
|
129
|
+
}, M = async ({
|
|
130
|
+
debug: t = !1,
|
|
161
131
|
ytdlpPath: o,
|
|
162
132
|
videoId: n,
|
|
163
133
|
dest: r,
|
|
164
|
-
tempDir:
|
|
165
|
-
ffmpegConfig:
|
|
134
|
+
tempDir: e,
|
|
135
|
+
ffmpegConfig: i
|
|
166
136
|
}) => {
|
|
167
|
-
|
|
137
|
+
d(t).log(`Downloading video: ${n} to: ${r}`);
|
|
168
138
|
const a = `https://www.instagram.com/reel/${n}/`;
|
|
169
|
-
return
|
|
170
|
-
debug:
|
|
139
|
+
return v({
|
|
140
|
+
debug: t,
|
|
171
141
|
ytdlpPath: o,
|
|
172
142
|
videoUrl: a,
|
|
173
143
|
dest: r,
|
|
174
|
-
tempDir:
|
|
175
|
-
ffmpegConfig:
|
|
144
|
+
tempDir: e,
|
|
145
|
+
ffmpegConfig: i
|
|
176
146
|
});
|
|
177
|
-
},
|
|
178
|
-
videoLink:
|
|
147
|
+
}, D = async ({
|
|
148
|
+
videoLink: t,
|
|
179
149
|
dest: o,
|
|
180
150
|
debug: n = !1,
|
|
181
151
|
headless: r = !0
|
|
182
152
|
}) => {
|
|
183
153
|
try {
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
r || (
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
154
|
+
const e = d(n);
|
|
155
|
+
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);
|
|
161
|
+
e.log("啟動 puppeteer");
|
|
162
|
+
const w = await f.newPage();
|
|
163
|
+
e.log("開新分頁"), e.log(`前往 ${i}`), await Promise.race([
|
|
164
|
+
w.goto(i, {
|
|
195
165
|
waitUntil: "networkidle0"
|
|
196
166
|
}),
|
|
197
|
-
|
|
198
|
-
]),
|
|
199
|
-
const
|
|
167
|
+
w.waitForSelector("video")
|
|
168
|
+
]), e.log("找到 video 元素");
|
|
169
|
+
const c = await w.$eval(
|
|
200
170
|
'video source[src^="https://www.tiktok.com/aweme/v1/play/"]',
|
|
201
|
-
(
|
|
171
|
+
(m) => m.getAttribute("src")
|
|
202
172
|
);
|
|
203
|
-
return
|
|
173
|
+
return e.log(`取得 video url: ${c}`), await f.close(), e.log("關閉 puppeteer"), await S(c, o, {
|
|
204
174
|
"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",
|
|
205
175
|
Referer: "https://www.tiktok.com/"
|
|
206
176
|
// 設定 Referer
|
|
207
|
-
}),
|
|
208
|
-
} catch (
|
|
209
|
-
return [
|
|
177
|
+
}), e.log(`下載完成 ${c}`), [null, !0];
|
|
178
|
+
} catch (e) {
|
|
179
|
+
return [e, null];
|
|
210
180
|
}
|
|
211
|
-
},
|
|
212
|
-
switch (
|
|
181
|
+
}, T = ({ type: t }) => {
|
|
182
|
+
switch (t) {
|
|
213
183
|
case "youtube":
|
|
214
184
|
case "yt-short":
|
|
215
|
-
return
|
|
185
|
+
return U;
|
|
216
186
|
case "facebook":
|
|
217
187
|
case "fb-reel":
|
|
218
|
-
return
|
|
188
|
+
return A;
|
|
219
189
|
case "vimeo":
|
|
220
|
-
return
|
|
190
|
+
return F;
|
|
221
191
|
case "instagram":
|
|
222
192
|
case "ig":
|
|
223
193
|
case "ig-reel":
|
|
224
|
-
return
|
|
194
|
+
return M;
|
|
225
195
|
case "tiktok":
|
|
226
196
|
case "tiktok-reel":
|
|
227
|
-
return
|
|
197
|
+
return D;
|
|
228
198
|
default:
|
|
229
|
-
throw new Error(`Invalid video type: ${
|
|
199
|
+
throw new Error(`Invalid video type: ${t}`);
|
|
230
200
|
}
|
|
231
201
|
};
|
|
232
202
|
export {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
203
|
+
T as useDownloader,
|
|
204
|
+
A as useFacebook,
|
|
205
|
+
M as useInstagram,
|
|
206
|
+
D as useTiktok,
|
|
207
|
+
F as useVimeo,
|
|
208
|
+
U as useYoutube
|
|
239
209
|
};
|