@jnzlab/easy-ytdlp 1.1.2 → 1.1.4
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/CHANGELOG.md +20 -0
- package/dist/cli.js +209 -134
- package/package.json +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.4 - 2026-09-08
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Interactive mode no longer fails with "Failed to fetch metadata for any of
|
|
8
|
+
the provided URLs" on videos that have no pre-merged format. `yt-dlp-wrap`
|
|
9
|
+
silently added `-f best` to the metadata call, which YouTube now rejects for
|
|
10
|
+
many videos; the metadata fetch passes `--ignore-no-formats-error` and its
|
|
11
|
+
own format flag instead. When every URL fails, the underlying yt-dlp error is
|
|
12
|
+
now shown instead of a generic message.
|
|
13
|
+
- `--version` now reads the version from `package.json` instead of a
|
|
14
|
+
hardcoded constant that had drifted from the published version.
|
|
15
|
+
- Removed an accidental dependency of the package on itself.
|
|
16
|
+
- Pasting a bare YouTube playlist link no longer fails/hangs at startup. The
|
|
17
|
+
metadata fetch now uses `--flat-playlist` for playlist URLs (fast, one small
|
|
18
|
+
line per video) and shows the playlist title + video count instead of dumping
|
|
19
|
+
full metadata for every video. "Just this video" on a bare playlist URL now
|
|
20
|
+
downloads only the first entry (`--playlist-items 1`) instead of the whole
|
|
21
|
+
playlist.
|
|
22
|
+
|
|
3
23
|
## 1.1.0 - 2026-07-27
|
|
4
24
|
|
|
5
25
|
### Added
|
package/dist/cli.js
CHANGED
|
@@ -179,129 +179,6 @@ async function createYtDlp(options = {}) {
|
|
|
179
179
|
return new YTDlpWrap(binPath);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
// src/builder.ts
|
|
183
|
-
var FILENAME_TEMPLATES = {
|
|
184
|
-
title: "%(title)s.%(ext)s",
|
|
185
|
-
"title-channel": "%(title)s [%(uploader)s].%(ext)s",
|
|
186
|
-
"title-date": "%(upload_date)s - %(title)s.%(ext)s"
|
|
187
|
-
};
|
|
188
|
-
function audioQualityValue(q) {
|
|
189
|
-
return q === "good" ? "5" : "0";
|
|
190
|
-
}
|
|
191
|
-
function videoQualityFlags(quality) {
|
|
192
|
-
if (!quality || quality === "best") {
|
|
193
|
-
return ["-f", "bv*+ba/b"];
|
|
194
|
-
}
|
|
195
|
-
if (typeof quality === "object" && "height" in quality) {
|
|
196
|
-
const h = quality.height;
|
|
197
|
-
return ["-f", `bv*[height=${h}]+ba/b`];
|
|
198
|
-
}
|
|
199
|
-
return ["-S", `res:${quality}`, "-f", "bv*+ba/b"];
|
|
200
|
-
}
|
|
201
|
-
function containerFlags(container) {
|
|
202
|
-
if (!container || container === "best") return [];
|
|
203
|
-
return ["--merge-output-format", container];
|
|
204
|
-
}
|
|
205
|
-
function buildFlags(answers) {
|
|
206
|
-
const flags = [];
|
|
207
|
-
switch (answers.mode) {
|
|
208
|
-
case "video":
|
|
209
|
-
flags.push(...videoQualityFlags(answers.videoQuality));
|
|
210
|
-
flags.push(...containerFlags(answers.container));
|
|
211
|
-
break;
|
|
212
|
-
case "video-only":
|
|
213
|
-
if (answers.videoQuality && answers.videoQuality !== "best" && typeof answers.videoQuality !== "object") {
|
|
214
|
-
flags.push("-S", `res:${answers.videoQuality}`, "-f", "bv");
|
|
215
|
-
} else if (typeof answers.videoQuality === "object" && answers.videoQuality?.height) {
|
|
216
|
-
flags.push("-f", `bv[height=${answers.videoQuality.height}]`);
|
|
217
|
-
} else {
|
|
218
|
-
flags.push("-f", "bv");
|
|
219
|
-
}
|
|
220
|
-
flags.push(...containerFlags(answers.container));
|
|
221
|
-
break;
|
|
222
|
-
case "audio":
|
|
223
|
-
flags.push(
|
|
224
|
-
"-x",
|
|
225
|
-
"--audio-format",
|
|
226
|
-
answers.audioFormat ?? "best",
|
|
227
|
-
"--audio-quality",
|
|
228
|
-
audioQualityValue(answers.audioQuality)
|
|
229
|
-
);
|
|
230
|
-
break;
|
|
231
|
-
case "subs-only":
|
|
232
|
-
flags.push("--skip-download", "--write-subs");
|
|
233
|
-
break;
|
|
234
|
-
case "thumbnail-only":
|
|
235
|
-
flags.push("--skip-download", "--write-thumbnail");
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
if (answers.mode === "subs-only") {
|
|
239
|
-
const langs = answers.subtitles.languages.length > 0 ? answers.subtitles.languages.join(",") : "all";
|
|
240
|
-
flags.push("--sub-langs", langs);
|
|
241
|
-
} else if (answers.subtitles.mode !== "none" && answers.mode !== "thumbnail-only") {
|
|
242
|
-
const langs = answers.subtitles.languages.length > 0 ? answers.subtitles.languages.join(",") : "all";
|
|
243
|
-
flags.push("--sub-langs", langs);
|
|
244
|
-
if (answers.subtitles.mode === "write" || answers.subtitles.mode === "both") {
|
|
245
|
-
flags.push("--write-subs");
|
|
246
|
-
}
|
|
247
|
-
if (answers.subtitles.mode === "embed" || answers.subtitles.mode === "both") {
|
|
248
|
-
flags.push("--embed-subs");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
switch (answers.playlist.kind) {
|
|
252
|
-
case "single":
|
|
253
|
-
flags.push("--no-playlist");
|
|
254
|
-
break;
|
|
255
|
-
case "all":
|
|
256
|
-
flags.push("--yes-playlist");
|
|
257
|
-
break;
|
|
258
|
-
case "range":
|
|
259
|
-
flags.push(
|
|
260
|
-
"--yes-playlist",
|
|
261
|
-
"-I",
|
|
262
|
-
`${answers.playlist.start}:${answers.playlist.stop}`
|
|
263
|
-
);
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
flags.push("-P", answers.outputDir);
|
|
267
|
-
flags.push("-o", FILENAME_TEMPLATES[answers.filenamePreset]);
|
|
268
|
-
if (answers.embedThumbnail && answers.mode !== "thumbnail-only") {
|
|
269
|
-
flags.push("--embed-thumbnail");
|
|
270
|
-
}
|
|
271
|
-
if (answers.embedMetadata) {
|
|
272
|
-
flags.push("--embed-metadata");
|
|
273
|
-
}
|
|
274
|
-
if (answers.sponsorBlock) {
|
|
275
|
-
flags.push("--sponsorblock-remove", "default");
|
|
276
|
-
}
|
|
277
|
-
flags.push("--print", "after_move:filepath");
|
|
278
|
-
flags.push(...answers.urls);
|
|
279
|
-
if (answers.urls.length > 1) {
|
|
280
|
-
flags.unshift("--ignore-errors");
|
|
281
|
-
}
|
|
282
|
-
return flags;
|
|
283
|
-
}
|
|
284
|
-
function formatCommand(flags) {
|
|
285
|
-
const quoted = flags.map(
|
|
286
|
-
(f) => /[\s"'\\]/.test(f) ? JSON.stringify(f) : f
|
|
287
|
-
);
|
|
288
|
-
const parts = ["yt-dlp"];
|
|
289
|
-
for (let i = 0; i < quoted.length; i++) {
|
|
290
|
-
const cur = quoted[i];
|
|
291
|
-
const next = quoted[i + 1];
|
|
292
|
-
if (cur.startsWith("-") && next && !next.startsWith("-") && !looksLikeUrl(next)) {
|
|
293
|
-
parts.push(`${cur} ${next}`);
|
|
294
|
-
i++;
|
|
295
|
-
} else {
|
|
296
|
-
parts.push(cur);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return parts.join("\n ");
|
|
300
|
-
}
|
|
301
|
-
function looksLikeUrl(s) {
|
|
302
|
-
return /^https?:\/\//i.test(s) || s.startsWith('"http');
|
|
303
|
-
}
|
|
304
|
-
|
|
305
182
|
// src/downloader.ts
|
|
306
183
|
import cliProgress from "cli-progress";
|
|
307
184
|
|
|
@@ -492,13 +369,63 @@ yt-dlp said: ${raw.trim()}`;
|
|
|
492
369
|
}
|
|
493
370
|
return raw.trim() || "Download failed for an unknown reason.";
|
|
494
371
|
}
|
|
372
|
+
var YOUTUBE_HOST_RE = /(\.|^)youtube\.com$/i;
|
|
373
|
+
var YOUTUBE_SHORT_HOST_RE = /(\.|^)youtu\.be$/i;
|
|
374
|
+
var VIDEO_ID_RE = /^[A-Za-z0-9_-]{11}$/;
|
|
375
|
+
function isPlaylistOnlyUrl(url) {
|
|
376
|
+
let u;
|
|
377
|
+
try {
|
|
378
|
+
u = new URL(url);
|
|
379
|
+
} catch {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
const host = u.hostname.toLowerCase();
|
|
383
|
+
const isYoutube = YOUTUBE_HOST_RE.test(host) || YOUTUBE_SHORT_HOST_RE.test(host);
|
|
384
|
+
if (!isYoutube || !u.searchParams.has("list")) return false;
|
|
385
|
+
const v = u.searchParams.get("v") ?? "";
|
|
386
|
+
if (VIDEO_ID_RE.test(v)) return false;
|
|
387
|
+
if (host.endsWith("youtu.be") && u.pathname.length > 1) return false;
|
|
388
|
+
if (/^\/(?:shorts|embed|live)\/[A-Za-z0-9_-]{11}/.test(u.pathname)) {
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
function metadataArgs(url) {
|
|
394
|
+
const scopeFlags = isPlaylistOnlyUrl(url) ? ["--flat-playlist"] : ["--no-playlist"];
|
|
395
|
+
return [
|
|
396
|
+
...youtubeCompatFlags(),
|
|
397
|
+
...scopeFlags,
|
|
398
|
+
"--ignore-no-formats-error",
|
|
399
|
+
"-f",
|
|
400
|
+
"b",
|
|
401
|
+
url
|
|
402
|
+
];
|
|
403
|
+
}
|
|
404
|
+
function normalizePlaylistMeta(raw, url) {
|
|
405
|
+
const entries = Array.isArray(raw) ? raw : raw && typeof raw === "object" ? [raw] : [];
|
|
406
|
+
const first = entries[0];
|
|
407
|
+
if (!first) {
|
|
408
|
+
return { _type: "playlist", webpage_url: url, playlist_count: 0, entries: [] };
|
|
409
|
+
}
|
|
410
|
+
const count = first.playlist_count ?? first.n_entries ?? entries.length;
|
|
411
|
+
return {
|
|
412
|
+
_type: "playlist",
|
|
413
|
+
id: first.playlist_id ?? first.id,
|
|
414
|
+
title: first.playlist_title ?? first.playlist ?? first.title,
|
|
415
|
+
uploader: first.playlist_uploader,
|
|
416
|
+
playlist: first.playlist_title ?? first.playlist,
|
|
417
|
+
playlist_id: first.playlist_id,
|
|
418
|
+
playlist_count: count,
|
|
419
|
+
n_entries: count,
|
|
420
|
+
webpage_url: url,
|
|
421
|
+
entries
|
|
422
|
+
};
|
|
423
|
+
}
|
|
495
424
|
async function fetchMetadata(ytDlp, url) {
|
|
425
|
+
const playlistOnly = isPlaylistOnlyUrl(url);
|
|
496
426
|
try {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
"--no-playlist",
|
|
500
|
-
url
|
|
501
|
-
]);
|
|
427
|
+
const raw = await ytDlp.getVideoInfo(metadataArgs(url));
|
|
428
|
+
return playlistOnly ? normalizePlaylistMeta(raw, url) : raw;
|
|
502
429
|
} catch (err) {
|
|
503
430
|
const msg = err instanceof Error ? err.message : String(err);
|
|
504
431
|
throw new Error(humanizeError(msg));
|
|
@@ -694,9 +621,7 @@ async function runDownload(ytDlp, flags, options = {}) {
|
|
|
694
621
|
}
|
|
695
622
|
if (code !== 0 && code !== null) {
|
|
696
623
|
reject(
|
|
697
|
-
new Error(
|
|
698
|
-
humanizeError(lastError || `yt-dlp exited with code ${code}`)
|
|
699
|
-
)
|
|
624
|
+
new Error(humanizeError(lastError || `yt-dlp exited with code ${code}`))
|
|
700
625
|
);
|
|
701
626
|
return;
|
|
702
627
|
}
|
|
@@ -705,6 +630,135 @@ async function runDownload(ytDlp, flags, options = {}) {
|
|
|
705
630
|
});
|
|
706
631
|
}
|
|
707
632
|
|
|
633
|
+
// src/builder.ts
|
|
634
|
+
var FILENAME_TEMPLATES = {
|
|
635
|
+
title: "%(title)s.%(ext)s",
|
|
636
|
+
"title-channel": "%(title)s [%(uploader)s].%(ext)s",
|
|
637
|
+
"title-date": "%(upload_date)s - %(title)s.%(ext)s"
|
|
638
|
+
};
|
|
639
|
+
function audioQualityValue(q) {
|
|
640
|
+
return q === "good" ? "5" : "0";
|
|
641
|
+
}
|
|
642
|
+
function videoQualityFlags(quality) {
|
|
643
|
+
if (!quality || quality === "best") {
|
|
644
|
+
return ["-f", "bv*+ba/b"];
|
|
645
|
+
}
|
|
646
|
+
if (typeof quality === "object" && "height" in quality) {
|
|
647
|
+
const h = quality.height;
|
|
648
|
+
return ["-f", `bv*[height=${h}]+ba/b`];
|
|
649
|
+
}
|
|
650
|
+
return ["-S", `res:${quality}`, "-f", "bv*+ba/b"];
|
|
651
|
+
}
|
|
652
|
+
function containerFlags(container) {
|
|
653
|
+
if (!container || container === "best") return [];
|
|
654
|
+
return ["--merge-output-format", container];
|
|
655
|
+
}
|
|
656
|
+
function buildFlags(answers) {
|
|
657
|
+
const flags = [];
|
|
658
|
+
switch (answers.mode) {
|
|
659
|
+
case "video":
|
|
660
|
+
flags.push(...videoQualityFlags(answers.videoQuality));
|
|
661
|
+
flags.push(...containerFlags(answers.container));
|
|
662
|
+
break;
|
|
663
|
+
case "video-only":
|
|
664
|
+
if (answers.videoQuality && answers.videoQuality !== "best" && typeof answers.videoQuality !== "object") {
|
|
665
|
+
flags.push("-S", `res:${answers.videoQuality}`, "-f", "bv");
|
|
666
|
+
} else if (typeof answers.videoQuality === "object" && answers.videoQuality?.height) {
|
|
667
|
+
flags.push("-f", `bv[height=${answers.videoQuality.height}]`);
|
|
668
|
+
} else {
|
|
669
|
+
flags.push("-f", "bv");
|
|
670
|
+
}
|
|
671
|
+
flags.push(...containerFlags(answers.container));
|
|
672
|
+
break;
|
|
673
|
+
case "audio":
|
|
674
|
+
flags.push(
|
|
675
|
+
"-x",
|
|
676
|
+
"--audio-format",
|
|
677
|
+
answers.audioFormat ?? "best",
|
|
678
|
+
"--audio-quality",
|
|
679
|
+
audioQualityValue(answers.audioQuality)
|
|
680
|
+
);
|
|
681
|
+
break;
|
|
682
|
+
case "subs-only":
|
|
683
|
+
flags.push("--skip-download", "--write-subs");
|
|
684
|
+
break;
|
|
685
|
+
case "thumbnail-only":
|
|
686
|
+
flags.push("--skip-download", "--write-thumbnail");
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
if (answers.mode === "subs-only") {
|
|
690
|
+
const langs = answers.subtitles.languages.length > 0 ? answers.subtitles.languages.join(",") : "all";
|
|
691
|
+
flags.push("--sub-langs", langs);
|
|
692
|
+
} else if (answers.subtitles.mode !== "none" && answers.mode !== "thumbnail-only") {
|
|
693
|
+
const langs = answers.subtitles.languages.length > 0 ? answers.subtitles.languages.join(",") : "all";
|
|
694
|
+
flags.push("--sub-langs", langs);
|
|
695
|
+
if (answers.subtitles.mode === "write" || answers.subtitles.mode === "both") {
|
|
696
|
+
flags.push("--write-subs");
|
|
697
|
+
}
|
|
698
|
+
if (answers.subtitles.mode === "embed" || answers.subtitles.mode === "both") {
|
|
699
|
+
flags.push("--embed-subs");
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
switch (answers.playlist.kind) {
|
|
703
|
+
case "single": {
|
|
704
|
+
const firstUrl = answers.urls[0];
|
|
705
|
+
if (firstUrl && isPlaylistOnlyUrl(firstUrl)) {
|
|
706
|
+
flags.push("--playlist-items", "1");
|
|
707
|
+
} else {
|
|
708
|
+
flags.push("--no-playlist");
|
|
709
|
+
}
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
case "all":
|
|
713
|
+
flags.push("--yes-playlist");
|
|
714
|
+
break;
|
|
715
|
+
case "range":
|
|
716
|
+
flags.push(
|
|
717
|
+
"--yes-playlist",
|
|
718
|
+
"-I",
|
|
719
|
+
`${answers.playlist.start}:${answers.playlist.stop}`
|
|
720
|
+
);
|
|
721
|
+
break;
|
|
722
|
+
}
|
|
723
|
+
flags.push("-P", answers.outputDir);
|
|
724
|
+
flags.push("-o", FILENAME_TEMPLATES[answers.filenamePreset]);
|
|
725
|
+
if (answers.embedThumbnail && answers.mode !== "thumbnail-only") {
|
|
726
|
+
flags.push("--embed-thumbnail");
|
|
727
|
+
}
|
|
728
|
+
if (answers.embedMetadata) {
|
|
729
|
+
flags.push("--embed-metadata");
|
|
730
|
+
}
|
|
731
|
+
if (answers.sponsorBlock) {
|
|
732
|
+
flags.push("--sponsorblock-remove", "default");
|
|
733
|
+
}
|
|
734
|
+
flags.push("--print", "after_move:filepath");
|
|
735
|
+
flags.push(...answers.urls);
|
|
736
|
+
if (answers.urls.length > 1) {
|
|
737
|
+
flags.unshift("--ignore-errors");
|
|
738
|
+
}
|
|
739
|
+
return flags;
|
|
740
|
+
}
|
|
741
|
+
function formatCommand(flags) {
|
|
742
|
+
const quoted = flags.map(
|
|
743
|
+
(f) => /[\s"'\\]/.test(f) ? JSON.stringify(f) : f
|
|
744
|
+
);
|
|
745
|
+
const parts = ["yt-dlp"];
|
|
746
|
+
for (let i = 0; i < quoted.length; i++) {
|
|
747
|
+
const cur = quoted[i];
|
|
748
|
+
const next = quoted[i + 1];
|
|
749
|
+
if (cur.startsWith("-") && next && !next.startsWith("-") && !looksLikeUrl(next)) {
|
|
750
|
+
parts.push(`${cur} ${next}`);
|
|
751
|
+
i++;
|
|
752
|
+
} else {
|
|
753
|
+
parts.push(cur);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return parts.join("\n ");
|
|
757
|
+
}
|
|
758
|
+
function looksLikeUrl(s) {
|
|
759
|
+
return /^https?:\/\//i.test(s) || s.startsWith('"http');
|
|
760
|
+
}
|
|
761
|
+
|
|
708
762
|
// src/questions.ts
|
|
709
763
|
import * as p2 from "@clack/prompts";
|
|
710
764
|
import { homedir } from "os";
|
|
@@ -1174,7 +1228,17 @@ async function askQuestions(url, meta) {
|
|
|
1174
1228
|
}
|
|
1175
1229
|
|
|
1176
1230
|
// src/cli.ts
|
|
1177
|
-
|
|
1231
|
+
function readCliVersion() {
|
|
1232
|
+
try {
|
|
1233
|
+
const pkg = JSON.parse(
|
|
1234
|
+
readFileSync(new URL("../package.json", import.meta.url), "utf8")
|
|
1235
|
+
);
|
|
1236
|
+
return pkg.version ?? "0.0.0";
|
|
1237
|
+
} catch {
|
|
1238
|
+
return "0.0.0";
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
var CLI_VERSION = readCliVersion();
|
|
1178
1242
|
function fail(message) {
|
|
1179
1243
|
p3.log.error(message);
|
|
1180
1244
|
process.exit(1);
|
|
@@ -1401,12 +1465,13 @@ async function runWizard(urlsArg, opts = {}) {
|
|
|
1401
1465
|
const u = urls[i];
|
|
1402
1466
|
if (r.status === "fulfilled") {
|
|
1403
1467
|
const m = r.value;
|
|
1468
|
+
const isPlaylist = m._type === "playlist";
|
|
1404
1469
|
videoInfos.push({
|
|
1405
1470
|
url: u,
|
|
1406
1471
|
meta: m,
|
|
1407
1472
|
title: m.title ?? "Unknown title",
|
|
1408
1473
|
uploader: m.uploader ?? "Unknown uploader",
|
|
1409
|
-
duration: formatDuration(m.duration)
|
|
1474
|
+
duration: isPlaylist ? `${m.playlist_count ?? "?"} videos` : formatDuration(m.duration)
|
|
1410
1475
|
});
|
|
1411
1476
|
} else {
|
|
1412
1477
|
failedUrls.push(u);
|
|
@@ -1414,7 +1479,17 @@ async function runWizard(urlsArg, opts = {}) {
|
|
|
1414
1479
|
}
|
|
1415
1480
|
if (videoInfos.length === 0) {
|
|
1416
1481
|
spinner2.stop("Could not fetch metadata");
|
|
1417
|
-
|
|
1482
|
+
const reasons = metaResults.filter(
|
|
1483
|
+
(r) => r.status === "rejected"
|
|
1484
|
+
).map(
|
|
1485
|
+
(r) => r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
1486
|
+
);
|
|
1487
|
+
p3.log.error(
|
|
1488
|
+
[
|
|
1489
|
+
"Failed to fetch metadata for any of the provided URLs.",
|
|
1490
|
+
...new Set(reasons)
|
|
1491
|
+
].join("\n\n")
|
|
1492
|
+
);
|
|
1418
1493
|
process.exit(1);
|
|
1419
1494
|
}
|
|
1420
1495
|
spinner2.stop("Metadata loaded");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jnzlab/easy-ytdlp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "A user-friendly interactive CLI wrapper for yt-dlp — no Python or flag memorization required",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@clack/prompts": "^0.10.0",
|
|
50
|
-
"@jnzlab/easy-ytdlp": "^1.1.0",
|
|
51
50
|
"cli-progress": "^3.12.0",
|
|
52
51
|
"commander": "^13.1.0",
|
|
53
52
|
"env-paths": "^3.0.0",
|