@blagoja/ts-dlp 0.1.3 → 0.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/README.md +105 -74
- package/dist/index.cjs +79 -14
- package/dist/index.d.cts +36 -7
- package/dist/index.d.ts +36 -7
- package/dist/index.js +77 -14
- package/package.json +53 -51
- package/dist/download.d.ts +0 -43
- package/dist/download.d.ts.map +0 -1
- package/dist/download.js +0 -55
- package/dist/download.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal/runner.d.ts +0 -3
- package/dist/internal/runner.d.ts.map +0 -1
- package/dist/internal/runner.js +0 -13
- package/dist/internal/runner.js.map +0 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -2
- package/dist/version.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
[](#readme)
|
|
4
|
+
|
|
5
|
+
</div>
|
|
6
|
+
|
|
1
7
|
# ts-dlp
|
|
2
8
|
|
|
3
|
-
A lightweight, fluent TypeScript wrapper for yt-dlp made for humans.
|
|
9
|
+
A lightweight, fluent TypeScript wrapper for [yt-dlp](https://github.com/yt-dlp/yt-dlp) made for humans.
|
|
10
|
+
|
|
11
|
+
`ts-dlp` makes using yt-dlp feel natural in Node.js and TypeScript projects through a chainable, strongly-typed API.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Why ts-dlp?
|
|
16
|
+
|
|
17
|
+
yt-dlp is extremely powerful, but constructing CLI arguments manually from Node.js can become difficult to maintain and hard to type safely.
|
|
4
18
|
|
|
5
|
-
`ts-dlp`
|
|
19
|
+
`ts-dlp` provides a fluent TypeScript API that keeps you close to native yt-dlp functionality while improving developer experience.
|
|
6
20
|
|
|
7
21
|
---
|
|
8
22
|
|
|
@@ -11,9 +25,9 @@ A lightweight, fluent TypeScript wrapper for yt-dlp made for humans.
|
|
|
11
25
|
- Fluent builder-style API
|
|
12
26
|
- Fully typed with TypeScript
|
|
13
27
|
- Uses your local yt-dlp installation
|
|
14
|
-
- Promise-based
|
|
28
|
+
- Promise-based
|
|
15
29
|
- Easy process handling
|
|
16
|
-
- Cross-platform
|
|
30
|
+
- Cross-platform
|
|
17
31
|
|
|
18
32
|
---
|
|
19
33
|
|
|
@@ -21,79 +35,111 @@ A lightweight, fluent TypeScript wrapper for yt-dlp made for humans.
|
|
|
21
35
|
|
|
22
36
|
> Early development / proof of concept
|
|
23
37
|
|
|
24
|
-
Current functionality:
|
|
25
|
-
|
|
26
|
-
- Detects whether `yt-dlp` is installed and available in PATH
|
|
27
|
-
|
|
28
38
|
---
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
## Installation
|
|
31
41
|
|
|
32
42
|
```bash
|
|
33
43
|
npm install ts-dlp
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
`ts-dlp` requires a local yt-dlp installation available in your system PATH.
|
|
37
47
|
|
|
38
|
-
|
|
48
|
+
### Install yt-dlp
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
**Windows**
|
|
41
51
|
|
|
42
52
|
```bash
|
|
43
53
|
winget install yt-dlp.yt-dlp
|
|
44
54
|
```
|
|
45
55
|
|
|
46
|
-
|
|
56
|
+
**macOS**
|
|
47
57
|
|
|
48
58
|
```bash
|
|
49
59
|
brew install yt-dlp
|
|
50
60
|
```
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
**Linux**
|
|
53
63
|
|
|
54
64
|
```bash
|
|
55
65
|
pip install -U yt-dlp
|
|
56
66
|
```
|
|
57
67
|
|
|
58
|
-
Official project:
|
|
59
|
-
|
|
60
|
-
https://www.npmjs.com/package/@blagoja/ts-dlp
|
|
68
|
+
Official yt-dlp project: [https://github.com/yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp)
|
|
61
69
|
|
|
62
70
|
---
|
|
63
71
|
|
|
64
|
-
|
|
72
|
+
## Quick Start
|
|
65
73
|
|
|
66
74
|
Instead of writing:
|
|
67
75
|
|
|
68
76
|
```bash
|
|
69
|
-
yt-dlp -f "bestvideo[height<=1080]+bestaudio" URL
|
|
77
|
+
yt-dlp -f "bestvideo[height<=1080]+bestaudio" -o "downloads/%(title)s.%(ext)s" URL
|
|
70
78
|
```
|
|
71
79
|
|
|
72
80
|
You write:
|
|
73
81
|
|
|
74
82
|
```ts
|
|
75
|
-
|
|
83
|
+
import {download} from "ts-dlp";
|
|
84
|
+
|
|
85
|
+
await download(url).resolution("1080p").output("downloads").run();
|
|
76
86
|
```
|
|
77
87
|
|
|
78
88
|
---
|
|
79
89
|
|
|
80
|
-
|
|
90
|
+
## API
|
|
81
91
|
|
|
82
92
|
```ts
|
|
83
|
-
import {
|
|
93
|
+
import {download} from "ts-dlp";
|
|
84
94
|
|
|
85
|
-
await
|
|
86
|
-
.download("https://youtube.com/watch?v=...")
|
|
95
|
+
await download(url)
|
|
87
96
|
.resolution("1080p")
|
|
88
97
|
.fps(60)
|
|
89
98
|
.format("mp4")
|
|
99
|
+
.audio("aac")
|
|
90
100
|
.output("./downloads")
|
|
101
|
+
.filename(({title, ext}) => `${title}.${ext}`)
|
|
102
|
+
.run();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Methods
|
|
106
|
+
|
|
107
|
+
| Method | Description |
|
|
108
|
+
| --------------------- | -------------------------------------------------- |
|
|
109
|
+
| `.resolution(res)` | Max video resolution (e.g. `"1080p"`, `"720p"`) |
|
|
110
|
+
| `.format(ext)` | Preferred video container (e.g. `"mp4"`, `"webm"`) |
|
|
111
|
+
| `.fps(fps)` | Max frame rate (e.g. `60`) |
|
|
112
|
+
| `.audio(codec?)` | Audio codec preference (e.g. `"aac"`, `"mp3"`) |
|
|
113
|
+
| `.output(dir)` | Output directory |
|
|
114
|
+
| `.filename(template)` | Filename template string or callback |
|
|
115
|
+
| `.run()` | Execute the download |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Philosophy
|
|
120
|
+
|
|
121
|
+
`ts-dlp` aims to stay thin and predictable.
|
|
122
|
+
|
|
123
|
+
The project does not attempt to hide yt-dlp or replace its ecosystem. Instead, it focuses on:
|
|
124
|
+
|
|
125
|
+
- Better TypeScript ergonomics
|
|
126
|
+
- Safer command construction
|
|
127
|
+
- Cleaner process handling
|
|
128
|
+
- Fluent APIs
|
|
129
|
+
|
|
130
|
+
`ts-dlp` will not try to model every yt-dlp flag as a typed method. Instead, future versions will expose escape hatches for advanced usage:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
// Planned
|
|
134
|
+
await download(url)
|
|
135
|
+
.customFormat("bestvideo[height<=1080][vcodec^=avc]+bestaudio[ext=m4a]")
|
|
136
|
+
.args(["--no-playlist", "--write-subs"])
|
|
91
137
|
.run();
|
|
92
138
|
```
|
|
93
139
|
|
|
94
140
|
---
|
|
95
141
|
|
|
96
|
-
|
|
142
|
+
## Goals
|
|
97
143
|
|
|
98
144
|
- Make yt-dlp easier to use from Node.js
|
|
99
145
|
- Avoid manually constructing CLI arguments
|
|
@@ -103,94 +149,79 @@ await ytdlp
|
|
|
103
149
|
|
|
104
150
|
---
|
|
105
151
|
|
|
106
|
-
|
|
152
|
+
## Roadmap
|
|
107
153
|
|
|
108
|
-
|
|
154
|
+
### v0.1.0 - Foundation
|
|
109
155
|
|
|
110
156
|
- [x] Detect yt-dlp installation
|
|
111
|
-
- [x] Execute
|
|
112
|
-
- [
|
|
113
|
-
- [ ] Error handling
|
|
114
|
-
- [ ] Capture stdout/stderr
|
|
115
|
-
- [ ] TypeScript support
|
|
116
|
-
- [ ] Unit test setup
|
|
117
|
-
- [x] `.download(url)`
|
|
118
|
-
- [x] `.run()`
|
|
157
|
+
- [x] Execute yt-dlp commands
|
|
158
|
+
- [x] `.download(url)` / `.run()`
|
|
119
159
|
- [x] `.output(path)`
|
|
120
|
-
- [x] `.format(
|
|
121
|
-
- [x] `.audio()`
|
|
122
|
-
- [
|
|
123
|
-
- [x] `.
|
|
124
|
-
- [x] `.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
## v0.2.0 - Metadata & Information
|
|
135
|
-
|
|
136
|
-
- [ ] `.info()`
|
|
137
|
-
- [ ] Video metadata parsing
|
|
160
|
+
- [x] `.format(ext)`
|
|
161
|
+
- [x] `.audio(codec?)`
|
|
162
|
+
- [x] `.resolution(res)`
|
|
163
|
+
- [x] `.fps(fps)`
|
|
164
|
+
- [x] `.filename(template)`
|
|
165
|
+
- [x] Error handling
|
|
166
|
+
- [x] Capture stdout/stderr
|
|
167
|
+
- [x] Unit test setup
|
|
168
|
+
|
|
169
|
+
### v0.2.0 - Metadata & Information
|
|
170
|
+
|
|
171
|
+
- [ ] `.info(url)` - fetch video metadata
|
|
138
172
|
- [ ] JSON output support
|
|
139
173
|
- [ ] Playlist support
|
|
140
174
|
- [ ] Progress events
|
|
141
175
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
```ts
|
|
145
|
-
const info = await ytdlp.info(url);
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## v0.3.0 - Advanced Features
|
|
176
|
+
### v0.3.0 - Advanced Features
|
|
151
177
|
|
|
152
178
|
- [ ] Subtitle support
|
|
153
179
|
- [ ] Thumbnail downloads
|
|
154
180
|
- [ ] Playlist filtering
|
|
155
181
|
- [ ] Cookies support
|
|
156
182
|
- [ ] Proxy support
|
|
157
|
-
- [ ]
|
|
158
|
-
|
|
159
|
-
---
|
|
183
|
+
- [ ] `.customFormat(selector)` escape hatch
|
|
184
|
+
- [ ] `.args(flags[])` escape hatch
|
|
160
185
|
|
|
161
|
-
|
|
186
|
+
### v0.4.0 - Developer Experience
|
|
162
187
|
|
|
163
|
-
- [ ] Better typed builders
|
|
164
188
|
- [ ] Presets
|
|
165
|
-
- [ ] Config
|
|
189
|
+
- [ ] Config file support
|
|
166
190
|
- [ ] Improved documentation
|
|
167
|
-
- [ ] More examples
|
|
168
191
|
- [ ] CI/CD pipeline
|
|
169
192
|
- [ ] Automated tests
|
|
170
193
|
|
|
171
194
|
---
|
|
172
195
|
|
|
173
|
-
|
|
196
|
+
## Non-Goals
|
|
174
197
|
|
|
175
198
|
At least for now, `ts-dlp` will NOT:
|
|
176
199
|
|
|
177
200
|
- Bundle yt-dlp binaries
|
|
178
201
|
- Replace yt-dlp functionality
|
|
179
|
-
- Abstract every yt-dlp flag
|
|
202
|
+
- Abstract every yt-dlp flag into typed methods
|
|
180
203
|
- Become a GUI application
|
|
181
204
|
|
|
182
205
|
The goal is to remain a lightweight developer wrapper.
|
|
183
206
|
|
|
184
207
|
---
|
|
185
208
|
|
|
186
|
-
|
|
209
|
+
## Contributing
|
|
187
210
|
|
|
188
211
|
Contributions, suggestions, and issue reports are welcome.
|
|
189
212
|
|
|
190
|
-
If you have
|
|
213
|
+
If you have ideas for the API design or developer experience, feel free to open an issue.
|
|
214
|
+
|
|
215
|
+
This project follows [Conventional Commits](https://www.conventionalcommits.org/) and maintains a [CHANGELOG](./CHANGELOG.md).
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Disclaimer
|
|
220
|
+
|
|
221
|
+
`ts-dlp` is a developer wrapper around yt-dlp. Users are responsible for complying with the terms of service and applicable laws of the media sources they access.
|
|
191
222
|
|
|
192
223
|
---
|
|
193
224
|
|
|
194
|
-
|
|
225
|
+
## License
|
|
195
226
|
|
|
196
227
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -20,21 +20,56 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
YtDlpError: () => YtDlpError,
|
|
24
|
+
YtDlpNotFoundError: () => YtDlpNotFoundError,
|
|
23
25
|
download: () => download
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(index_exports);
|
|
26
28
|
|
|
27
29
|
// src/internal/runner.ts
|
|
28
30
|
var import_execa = require("execa");
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
// src/errors.ts
|
|
33
|
+
var YtDlpNotFoundError = class extends Error {
|
|
34
|
+
constructor() {
|
|
35
|
+
super(
|
|
36
|
+
"yt-dlp is not installed or not in PATH. Refer to https://github.com/yt-dlp/yt-dlp#installation"
|
|
37
|
+
);
|
|
38
|
+
this.name = "YtDlpNotFoundError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var YtDlpError = class extends Error {
|
|
42
|
+
constructor(message, exitCode, stderr) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.exitCode = exitCode;
|
|
45
|
+
this.stderr = stderr;
|
|
46
|
+
this.name = "YtDlpError";
|
|
47
|
+
}
|
|
48
|
+
exitCode;
|
|
49
|
+
stderr;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/internal/runner.ts
|
|
53
|
+
async function runYtDlp(args, pipe = false) {
|
|
54
|
+
const result = await (0, import_execa.execa)(
|
|
55
|
+
"yt-dlp",
|
|
56
|
+
["--js-runtimes", "node", ...args],
|
|
57
|
+
{ stdio: pipe ? "pipe" : "inherit" }
|
|
58
|
+
).catch(handleError);
|
|
59
|
+
return {
|
|
60
|
+
stdout: result.stdout ?? "",
|
|
61
|
+
stderr: result.stderr ?? ""
|
|
62
|
+
};
|
|
33
63
|
}
|
|
34
|
-
function
|
|
35
|
-
if (error instanceof import_execa.ExecaError
|
|
36
|
-
|
|
37
|
-
|
|
64
|
+
function handleError(error) {
|
|
65
|
+
if (error instanceof import_execa.ExecaError) {
|
|
66
|
+
if (error.code === "ENOENT") {
|
|
67
|
+
throw new YtDlpNotFoundError();
|
|
68
|
+
}
|
|
69
|
+
throw new YtDlpError(
|
|
70
|
+
`yt-dlp exited with code ${error.exitCode}`,
|
|
71
|
+
error.exitCode ?? 1,
|
|
72
|
+
error.stderr ?? ""
|
|
38
73
|
);
|
|
39
74
|
}
|
|
40
75
|
throw error;
|
|
@@ -44,6 +79,11 @@ function handleEnoent(error) {
|
|
|
44
79
|
var DownloadBuilder = class {
|
|
45
80
|
constructor(url) {
|
|
46
81
|
this.url = url;
|
|
82
|
+
try {
|
|
83
|
+
new URL(url);
|
|
84
|
+
} catch {
|
|
85
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
86
|
+
}
|
|
47
87
|
}
|
|
48
88
|
url;
|
|
49
89
|
args = [];
|
|
@@ -54,6 +94,12 @@ var DownloadBuilder = class {
|
|
|
54
94
|
videoExt;
|
|
55
95
|
videoFps;
|
|
56
96
|
videoHeight;
|
|
97
|
+
/**
|
|
98
|
+
* A private method to build the command-line arguments for yt-dlp based on the options set by the user.
|
|
99
|
+
* This method constructs the appropriate format filters and output template arguments according to the options set by the user.
|
|
100
|
+
*
|
|
101
|
+
* @returns The command-line arguments to be passed to yt-dlp based on the specified options.
|
|
102
|
+
*/
|
|
57
103
|
buildArgs() {
|
|
58
104
|
const args = [...this.args];
|
|
59
105
|
if (this.videoHeight || this.videoFps || this.videoExt || this.audioFormat) {
|
|
@@ -88,7 +134,7 @@ var DownloadBuilder = class {
|
|
|
88
134
|
* If not specified, the file will be saved in the current working directory.
|
|
89
135
|
*
|
|
90
136
|
* @example
|
|
91
|
-
* download("https://www.
|
|
137
|
+
* download("https://www.example.com/video")
|
|
92
138
|
* .output("downloads")
|
|
93
139
|
* .run();
|
|
94
140
|
*
|
|
@@ -106,7 +152,7 @@ var DownloadBuilder = class {
|
|
|
106
152
|
* If no codec is specified, it will select the best available audio format regardless of codec.
|
|
107
153
|
*
|
|
108
154
|
* @example // Specifying an audio codec
|
|
109
|
-
* download("https://www.
|
|
155
|
+
* download("https://www.example.com/video")
|
|
110
156
|
* .audio("mp3")
|
|
111
157
|
* .run();
|
|
112
158
|
*
|
|
@@ -123,7 +169,7 @@ var DownloadBuilder = class {
|
|
|
123
169
|
* If not specified, it will select the best available video format regardless of extension.
|
|
124
170
|
*
|
|
125
171
|
* @example
|
|
126
|
-
* download("https://www.
|
|
172
|
+
* download("https://www.example.com/video")
|
|
127
173
|
* .format("mp4")
|
|
128
174
|
* .run();
|
|
129
175
|
*
|
|
@@ -134,7 +180,20 @@ var DownloadBuilder = class {
|
|
|
134
180
|
this.videoExt = ext;
|
|
135
181
|
return this;
|
|
136
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Set the desired frames per second (FPS) for the video download. You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
185
|
+
* The method will select the best available video format that has an FPS less than or equal to the specified value.
|
|
186
|
+
*
|
|
187
|
+
* @param fps The desired frames per second (FPS) for the video download.
|
|
188
|
+
* You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
189
|
+
* @returns The current instance of DownloadBuilder for method chaining.
|
|
190
|
+
*/
|
|
137
191
|
fps(fps) {
|
|
192
|
+
if (!Number.isInteger(fps) || fps <= 0) {
|
|
193
|
+
throw new RangeError(
|
|
194
|
+
`Invalid FPS value: ${fps}. FPS must be a positive integer.`
|
|
195
|
+
);
|
|
196
|
+
}
|
|
138
197
|
this.videoFps = fps;
|
|
139
198
|
return this;
|
|
140
199
|
}
|
|
@@ -144,12 +203,12 @@ var DownloadBuilder = class {
|
|
|
144
203
|
* automatically mapped to their values at download time.
|
|
145
204
|
*
|
|
146
205
|
* @example // Using a string template
|
|
147
|
-
* download("https://www.
|
|
206
|
+
* download("https://www.example.com/video")
|
|
148
207
|
* .output("downloads")
|
|
149
208
|
* .filename("%(title)s.%(ext)s")
|
|
150
209
|
*
|
|
151
210
|
* @example // Using a callback to specify a custom filename template
|
|
152
|
-
* download("https://www.
|
|
211
|
+
* download("https://www.example.com/video")
|
|
153
212
|
* .output("downloads")
|
|
154
213
|
* .filename(({ title, ext }) => `${title}.${ext}`)
|
|
155
214
|
* .run();
|
|
@@ -178,7 +237,7 @@ var DownloadBuilder = class {
|
|
|
178
237
|
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
179
238
|
*
|
|
180
239
|
* @example
|
|
181
|
-
* download("https://www.
|
|
240
|
+
* download("https://www.example.com/video")
|
|
182
241
|
* .resolution("720p")
|
|
183
242
|
* .output("downloads/%(title)s.%(ext)s")
|
|
184
243
|
* .run();
|
|
@@ -188,6 +247,10 @@ var DownloadBuilder = class {
|
|
|
188
247
|
const args = this.buildArgs();
|
|
189
248
|
await runYtDlp([...args, this.url]);
|
|
190
249
|
}
|
|
250
|
+
async capture() {
|
|
251
|
+
const args = this.buildArgs();
|
|
252
|
+
return runYtDlp([...args, this.url], true);
|
|
253
|
+
}
|
|
191
254
|
};
|
|
192
255
|
|
|
193
256
|
// src/index.ts
|
|
@@ -196,5 +259,7 @@ function download(url) {
|
|
|
196
259
|
}
|
|
197
260
|
// Annotate the CommonJS export names for ESM import in node:
|
|
198
261
|
0 && (module.exports = {
|
|
262
|
+
YtDlpError,
|
|
263
|
+
YtDlpNotFoundError,
|
|
199
264
|
download
|
|
200
265
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
interface RunResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
type LiteralUnion<T extends string> = T | (string & {});
|
|
2
7
|
type Resolution = LiteralUnion<"144p" | "240p" | "360p" | "480p" | "720p" | "1080p" | "1440p" | "2160p">;
|
|
3
8
|
type AudioCodec = LiteralUnion<"opus" | "aac" | "m4a" | "mp3" | "flac" | "wav">;
|
|
@@ -35,6 +40,12 @@ declare class DownloadBuilder {
|
|
|
35
40
|
private videoFps?;
|
|
36
41
|
private videoHeight?;
|
|
37
42
|
constructor(url: string);
|
|
43
|
+
/**
|
|
44
|
+
* A private method to build the command-line arguments for yt-dlp based on the options set by the user.
|
|
45
|
+
* This method constructs the appropriate format filters and output template arguments according to the options set by the user.
|
|
46
|
+
*
|
|
47
|
+
* @returns The command-line arguments to be passed to yt-dlp based on the specified options.
|
|
48
|
+
*/
|
|
38
49
|
private buildArgs;
|
|
39
50
|
/**
|
|
40
51
|
* Set the desired resolution for the video download.
|
|
@@ -50,7 +61,7 @@ declare class DownloadBuilder {
|
|
|
50
61
|
* If not specified, the file will be saved in the current working directory.
|
|
51
62
|
*
|
|
52
63
|
* @example
|
|
53
|
-
* download("https://www.
|
|
64
|
+
* download("https://www.example.com/video")
|
|
54
65
|
* .output("downloads")
|
|
55
66
|
* .run();
|
|
56
67
|
*
|
|
@@ -65,7 +76,7 @@ declare class DownloadBuilder {
|
|
|
65
76
|
* If no codec is specified, it will select the best available audio format regardless of codec.
|
|
66
77
|
*
|
|
67
78
|
* @example // Specifying an audio codec
|
|
68
|
-
* download("https://www.
|
|
79
|
+
* download("https://www.example.com/video")
|
|
69
80
|
* .audio("mp3")
|
|
70
81
|
* .run();
|
|
71
82
|
*
|
|
@@ -79,7 +90,7 @@ declare class DownloadBuilder {
|
|
|
79
90
|
* If not specified, it will select the best available video format regardless of extension.
|
|
80
91
|
*
|
|
81
92
|
* @example
|
|
82
|
-
* download("https://www.
|
|
93
|
+
* download("https://www.example.com/video")
|
|
83
94
|
* .format("mp4")
|
|
84
95
|
* .run();
|
|
85
96
|
*
|
|
@@ -87,6 +98,14 @@ declare class DownloadBuilder {
|
|
|
87
98
|
* @returns The current instance of DownloadBuilder for method chaining.
|
|
88
99
|
*/
|
|
89
100
|
format(ext: VideoExt): this;
|
|
101
|
+
/**
|
|
102
|
+
* Set the desired frames per second (FPS) for the video download. You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
103
|
+
* The method will select the best available video format that has an FPS less than or equal to the specified value.
|
|
104
|
+
*
|
|
105
|
+
* @param fps The desired frames per second (FPS) for the video download.
|
|
106
|
+
* You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
107
|
+
* @returns The current instance of DownloadBuilder for method chaining.
|
|
108
|
+
*/
|
|
90
109
|
fps(fps: number): this;
|
|
91
110
|
/**
|
|
92
111
|
* Set the filename template for the downloaded file.
|
|
@@ -94,12 +113,12 @@ declare class DownloadBuilder {
|
|
|
94
113
|
* automatically mapped to their values at download time.
|
|
95
114
|
*
|
|
96
115
|
* @example // Using a string template
|
|
97
|
-
* download("https://www.
|
|
116
|
+
* download("https://www.example.com/video")
|
|
98
117
|
* .output("downloads")
|
|
99
118
|
* .filename("%(title)s.%(ext)s")
|
|
100
119
|
*
|
|
101
120
|
* @example // Using a callback to specify a custom filename template
|
|
102
|
-
* download("https://www.
|
|
121
|
+
* download("https://www.example.com/video")
|
|
103
122
|
* .output("downloads")
|
|
104
123
|
* .filename(({ title, ext }) => `${title}.${ext}`)
|
|
105
124
|
* .run();
|
|
@@ -116,15 +135,25 @@ declare class DownloadBuilder {
|
|
|
116
135
|
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
117
136
|
*
|
|
118
137
|
* @example
|
|
119
|
-
* download("https://www.
|
|
138
|
+
* download("https://www.example.com/video")
|
|
120
139
|
* .resolution("720p")
|
|
121
140
|
* .output("downloads/%(title)s.%(ext)s")
|
|
122
141
|
* .run();
|
|
123
142
|
*
|
|
124
143
|
*/
|
|
125
144
|
run(): Promise<void>;
|
|
145
|
+
capture(): Promise<RunResult>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare class YtDlpNotFoundError extends Error {
|
|
149
|
+
constructor();
|
|
150
|
+
}
|
|
151
|
+
declare class YtDlpError extends Error {
|
|
152
|
+
readonly exitCode: number;
|
|
153
|
+
readonly stderr: string;
|
|
154
|
+
constructor(message: string, exitCode: number, stderr: string);
|
|
126
155
|
}
|
|
127
156
|
|
|
128
157
|
declare function download(url: string): DownloadBuilder;
|
|
129
158
|
|
|
130
|
-
export { download };
|
|
159
|
+
export { type AudioCodec, type OutputFields, type Resolution, type RunResult, type VideoExt, YtDlpError, YtDlpNotFoundError, download };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
interface RunResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
type LiteralUnion<T extends string> = T | (string & {});
|
|
2
7
|
type Resolution = LiteralUnion<"144p" | "240p" | "360p" | "480p" | "720p" | "1080p" | "1440p" | "2160p">;
|
|
3
8
|
type AudioCodec = LiteralUnion<"opus" | "aac" | "m4a" | "mp3" | "flac" | "wav">;
|
|
@@ -35,6 +40,12 @@ declare class DownloadBuilder {
|
|
|
35
40
|
private videoFps?;
|
|
36
41
|
private videoHeight?;
|
|
37
42
|
constructor(url: string);
|
|
43
|
+
/**
|
|
44
|
+
* A private method to build the command-line arguments for yt-dlp based on the options set by the user.
|
|
45
|
+
* This method constructs the appropriate format filters and output template arguments according to the options set by the user.
|
|
46
|
+
*
|
|
47
|
+
* @returns The command-line arguments to be passed to yt-dlp based on the specified options.
|
|
48
|
+
*/
|
|
38
49
|
private buildArgs;
|
|
39
50
|
/**
|
|
40
51
|
* Set the desired resolution for the video download.
|
|
@@ -50,7 +61,7 @@ declare class DownloadBuilder {
|
|
|
50
61
|
* If not specified, the file will be saved in the current working directory.
|
|
51
62
|
*
|
|
52
63
|
* @example
|
|
53
|
-
* download("https://www.
|
|
64
|
+
* download("https://www.example.com/video")
|
|
54
65
|
* .output("downloads")
|
|
55
66
|
* .run();
|
|
56
67
|
*
|
|
@@ -65,7 +76,7 @@ declare class DownloadBuilder {
|
|
|
65
76
|
* If no codec is specified, it will select the best available audio format regardless of codec.
|
|
66
77
|
*
|
|
67
78
|
* @example // Specifying an audio codec
|
|
68
|
-
* download("https://www.
|
|
79
|
+
* download("https://www.example.com/video")
|
|
69
80
|
* .audio("mp3")
|
|
70
81
|
* .run();
|
|
71
82
|
*
|
|
@@ -79,7 +90,7 @@ declare class DownloadBuilder {
|
|
|
79
90
|
* If not specified, it will select the best available video format regardless of extension.
|
|
80
91
|
*
|
|
81
92
|
* @example
|
|
82
|
-
* download("https://www.
|
|
93
|
+
* download("https://www.example.com/video")
|
|
83
94
|
* .format("mp4")
|
|
84
95
|
* .run();
|
|
85
96
|
*
|
|
@@ -87,6 +98,14 @@ declare class DownloadBuilder {
|
|
|
87
98
|
* @returns The current instance of DownloadBuilder for method chaining.
|
|
88
99
|
*/
|
|
89
100
|
format(ext: VideoExt): this;
|
|
101
|
+
/**
|
|
102
|
+
* Set the desired frames per second (FPS) for the video download. You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
103
|
+
* The method will select the best available video format that has an FPS less than or equal to the specified value.
|
|
104
|
+
*
|
|
105
|
+
* @param fps The desired frames per second (FPS) for the video download.
|
|
106
|
+
* You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
107
|
+
* @returns The current instance of DownloadBuilder for method chaining.
|
|
108
|
+
*/
|
|
90
109
|
fps(fps: number): this;
|
|
91
110
|
/**
|
|
92
111
|
* Set the filename template for the downloaded file.
|
|
@@ -94,12 +113,12 @@ declare class DownloadBuilder {
|
|
|
94
113
|
* automatically mapped to their values at download time.
|
|
95
114
|
*
|
|
96
115
|
* @example // Using a string template
|
|
97
|
-
* download("https://www.
|
|
116
|
+
* download("https://www.example.com/video")
|
|
98
117
|
* .output("downloads")
|
|
99
118
|
* .filename("%(title)s.%(ext)s")
|
|
100
119
|
*
|
|
101
120
|
* @example // Using a callback to specify a custom filename template
|
|
102
|
-
* download("https://www.
|
|
121
|
+
* download("https://www.example.com/video")
|
|
103
122
|
* .output("downloads")
|
|
104
123
|
* .filename(({ title, ext }) => `${title}.${ext}`)
|
|
105
124
|
* .run();
|
|
@@ -116,15 +135,25 @@ declare class DownloadBuilder {
|
|
|
116
135
|
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
117
136
|
*
|
|
118
137
|
* @example
|
|
119
|
-
* download("https://www.
|
|
138
|
+
* download("https://www.example.com/video")
|
|
120
139
|
* .resolution("720p")
|
|
121
140
|
* .output("downloads/%(title)s.%(ext)s")
|
|
122
141
|
* .run();
|
|
123
142
|
*
|
|
124
143
|
*/
|
|
125
144
|
run(): Promise<void>;
|
|
145
|
+
capture(): Promise<RunResult>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare class YtDlpNotFoundError extends Error {
|
|
149
|
+
constructor();
|
|
150
|
+
}
|
|
151
|
+
declare class YtDlpError extends Error {
|
|
152
|
+
readonly exitCode: number;
|
|
153
|
+
readonly stderr: string;
|
|
154
|
+
constructor(message: string, exitCode: number, stderr: string);
|
|
126
155
|
}
|
|
127
156
|
|
|
128
157
|
declare function download(url: string): DownloadBuilder;
|
|
129
158
|
|
|
130
|
-
export { download };
|
|
159
|
+
export { type AudioCodec, type OutputFields, type Resolution, type RunResult, type VideoExt, YtDlpError, YtDlpNotFoundError, download };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,47 @@
|
|
|
1
1
|
// src/internal/runner.ts
|
|
2
2
|
import { execa, ExecaError } from "execa";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
|
|
4
|
+
// src/errors.ts
|
|
5
|
+
var YtDlpNotFoundError = class extends Error {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(
|
|
8
|
+
"yt-dlp is not installed or not in PATH. Refer to https://github.com/yt-dlp/yt-dlp#installation"
|
|
9
|
+
);
|
|
10
|
+
this.name = "YtDlpNotFoundError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var YtDlpError = class extends Error {
|
|
14
|
+
constructor(message, exitCode, stderr) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.exitCode = exitCode;
|
|
17
|
+
this.stderr = stderr;
|
|
18
|
+
this.name = "YtDlpError";
|
|
19
|
+
}
|
|
20
|
+
exitCode;
|
|
21
|
+
stderr;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// src/internal/runner.ts
|
|
25
|
+
async function runYtDlp(args, pipe = false) {
|
|
26
|
+
const result = await execa(
|
|
27
|
+
"yt-dlp",
|
|
28
|
+
["--js-runtimes", "node", ...args],
|
|
29
|
+
{ stdio: pipe ? "pipe" : "inherit" }
|
|
30
|
+
).catch(handleError);
|
|
31
|
+
return {
|
|
32
|
+
stdout: result.stdout ?? "",
|
|
33
|
+
stderr: result.stderr ?? ""
|
|
34
|
+
};
|
|
7
35
|
}
|
|
8
|
-
function
|
|
9
|
-
if (error instanceof ExecaError
|
|
10
|
-
|
|
11
|
-
|
|
36
|
+
function handleError(error) {
|
|
37
|
+
if (error instanceof ExecaError) {
|
|
38
|
+
if (error.code === "ENOENT") {
|
|
39
|
+
throw new YtDlpNotFoundError();
|
|
40
|
+
}
|
|
41
|
+
throw new YtDlpError(
|
|
42
|
+
`yt-dlp exited with code ${error.exitCode}`,
|
|
43
|
+
error.exitCode ?? 1,
|
|
44
|
+
error.stderr ?? ""
|
|
12
45
|
);
|
|
13
46
|
}
|
|
14
47
|
throw error;
|
|
@@ -18,6 +51,11 @@ function handleEnoent(error) {
|
|
|
18
51
|
var DownloadBuilder = class {
|
|
19
52
|
constructor(url) {
|
|
20
53
|
this.url = url;
|
|
54
|
+
try {
|
|
55
|
+
new URL(url);
|
|
56
|
+
} catch {
|
|
57
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
58
|
+
}
|
|
21
59
|
}
|
|
22
60
|
url;
|
|
23
61
|
args = [];
|
|
@@ -28,6 +66,12 @@ var DownloadBuilder = class {
|
|
|
28
66
|
videoExt;
|
|
29
67
|
videoFps;
|
|
30
68
|
videoHeight;
|
|
69
|
+
/**
|
|
70
|
+
* A private method to build the command-line arguments for yt-dlp based on the options set by the user.
|
|
71
|
+
* This method constructs the appropriate format filters and output template arguments according to the options set by the user.
|
|
72
|
+
*
|
|
73
|
+
* @returns The command-line arguments to be passed to yt-dlp based on the specified options.
|
|
74
|
+
*/
|
|
31
75
|
buildArgs() {
|
|
32
76
|
const args = [...this.args];
|
|
33
77
|
if (this.videoHeight || this.videoFps || this.videoExt || this.audioFormat) {
|
|
@@ -62,7 +106,7 @@ var DownloadBuilder = class {
|
|
|
62
106
|
* If not specified, the file will be saved in the current working directory.
|
|
63
107
|
*
|
|
64
108
|
* @example
|
|
65
|
-
* download("https://www.
|
|
109
|
+
* download("https://www.example.com/video")
|
|
66
110
|
* .output("downloads")
|
|
67
111
|
* .run();
|
|
68
112
|
*
|
|
@@ -80,7 +124,7 @@ var DownloadBuilder = class {
|
|
|
80
124
|
* If no codec is specified, it will select the best available audio format regardless of codec.
|
|
81
125
|
*
|
|
82
126
|
* @example // Specifying an audio codec
|
|
83
|
-
* download("https://www.
|
|
127
|
+
* download("https://www.example.com/video")
|
|
84
128
|
* .audio("mp3")
|
|
85
129
|
* .run();
|
|
86
130
|
*
|
|
@@ -97,7 +141,7 @@ var DownloadBuilder = class {
|
|
|
97
141
|
* If not specified, it will select the best available video format regardless of extension.
|
|
98
142
|
*
|
|
99
143
|
* @example
|
|
100
|
-
* download("https://www.
|
|
144
|
+
* download("https://www.example.com/video")
|
|
101
145
|
* .format("mp4")
|
|
102
146
|
* .run();
|
|
103
147
|
*
|
|
@@ -108,7 +152,20 @@ var DownloadBuilder = class {
|
|
|
108
152
|
this.videoExt = ext;
|
|
109
153
|
return this;
|
|
110
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Set the desired frames per second (FPS) for the video download. You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
157
|
+
* The method will select the best available video format that has an FPS less than or equal to the specified value.
|
|
158
|
+
*
|
|
159
|
+
* @param fps The desired frames per second (FPS) for the video download.
|
|
160
|
+
* You can specify a positive integer value for FPS, such as 30, 60, etc.
|
|
161
|
+
* @returns The current instance of DownloadBuilder for method chaining.
|
|
162
|
+
*/
|
|
111
163
|
fps(fps) {
|
|
164
|
+
if (!Number.isInteger(fps) || fps <= 0) {
|
|
165
|
+
throw new RangeError(
|
|
166
|
+
`Invalid FPS value: ${fps}. FPS must be a positive integer.`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
112
169
|
this.videoFps = fps;
|
|
113
170
|
return this;
|
|
114
171
|
}
|
|
@@ -118,12 +175,12 @@ var DownloadBuilder = class {
|
|
|
118
175
|
* automatically mapped to their values at download time.
|
|
119
176
|
*
|
|
120
177
|
* @example // Using a string template
|
|
121
|
-
* download("https://www.
|
|
178
|
+
* download("https://www.example.com/video")
|
|
122
179
|
* .output("downloads")
|
|
123
180
|
* .filename("%(title)s.%(ext)s")
|
|
124
181
|
*
|
|
125
182
|
* @example // Using a callback to specify a custom filename template
|
|
126
|
-
* download("https://www.
|
|
183
|
+
* download("https://www.example.com/video")
|
|
127
184
|
* .output("downloads")
|
|
128
185
|
* .filename(({ title, ext }) => `${title}.${ext}`)
|
|
129
186
|
* .run();
|
|
@@ -152,7 +209,7 @@ var DownloadBuilder = class {
|
|
|
152
209
|
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
153
210
|
*
|
|
154
211
|
* @example
|
|
155
|
-
* download("https://www.
|
|
212
|
+
* download("https://www.example.com/video")
|
|
156
213
|
* .resolution("720p")
|
|
157
214
|
* .output("downloads/%(title)s.%(ext)s")
|
|
158
215
|
* .run();
|
|
@@ -162,6 +219,10 @@ var DownloadBuilder = class {
|
|
|
162
219
|
const args = this.buildArgs();
|
|
163
220
|
await runYtDlp([...args, this.url]);
|
|
164
221
|
}
|
|
222
|
+
async capture() {
|
|
223
|
+
const args = this.buildArgs();
|
|
224
|
+
return runYtDlp([...args, this.url], true);
|
|
225
|
+
}
|
|
165
226
|
};
|
|
166
227
|
|
|
167
228
|
// src/index.ts
|
|
@@ -169,5 +230,7 @@ function download(url) {
|
|
|
169
230
|
return new DownloadBuilder(url);
|
|
170
231
|
}
|
|
171
232
|
export {
|
|
233
|
+
YtDlpError,
|
|
234
|
+
YtDlpNotFoundError,
|
|
172
235
|
download
|
|
173
236
|
};
|
package/package.json
CHANGED
|
@@ -1,51 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@blagoja/ts-dlp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "A human readable TypeScript wrapper for yt-dlp",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/index.js",
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"require": "./dist/index.cjs"
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
16
|
-
"dev": "tsx src/index.ts",
|
|
17
|
-
"lint": "eslint src",
|
|
18
|
-
"prepublishOnly": "npm run build"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"typescript
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@blagoja/ts-dlp",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "A human readable TypeScript wrapper for yt-dlp",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.cjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"lint": "eslint src",
|
|
18
|
+
"prepublishOnly": "npm run build",
|
|
19
|
+
"test": "vitest run"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"yt-dlp",
|
|
23
|
+
"youtube-dl",
|
|
24
|
+
"downloader",
|
|
25
|
+
"wrapper"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/blagojablazhevski/ts-dlp.git"
|
|
30
|
+
},
|
|
31
|
+
"author": "Blagoja Blazhevski",
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.9.1",
|
|
42
|
+
"eslint": "^10.4.0",
|
|
43
|
+
"jiti": "^2.7.0",
|
|
44
|
+
"tsup": "^8.5.1",
|
|
45
|
+
"tsx": "^4.22.3",
|
|
46
|
+
"typescript": "^6.0.3",
|
|
47
|
+
"typescript-eslint": "^8.60.0",
|
|
48
|
+
"vitest": "^4.1.7"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"execa": "^9.6.1"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/dist/download.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export declare class DownloadBuilder {
|
|
2
|
-
private readonly url;
|
|
3
|
-
private readonly args;
|
|
4
|
-
constructor(url: string);
|
|
5
|
-
/**
|
|
6
|
-
* Set the desired resolution for the video to be downloaded.
|
|
7
|
-
* This will instruct yt-dlp to download the best video and audio streams that are less than or equal to the specified height.
|
|
8
|
-
* For example, if you specify "720p", yt-dlp will download the best video and audio streams that are 720 pixels in height or less.
|
|
9
|
-
* If you want to download the best available quality regardless of resolution, you can omit this option or set it to a very high value like "9999p".
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* download("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
|
|
13
|
-
* .resolution("720p")
|
|
14
|
-
* .output("downloads/%(title)s.%(ext)s")
|
|
15
|
-
*
|
|
16
|
-
* @param res The desired resolution for the video. For example: "720p", "1080p", etc. This will tell yt-dlp to download the best video and audio streams that are less than or equal to the specified height. If you want to download the best available quality, you can omit this option or set it to a very high value like "9999p".
|
|
17
|
-
* @returns The current instance of DownloadBuilder for method chaining.
|
|
18
|
-
*/
|
|
19
|
-
resolution(res: string): this;
|
|
20
|
-
/**
|
|
21
|
-
* Set the output directory and filename template for the downloaded file.
|
|
22
|
-
*
|
|
23
|
-
* @param template The output template for the downloaded file. You can use placeholders like %(title)s, %(ext)s, etc. For example: "downloads/%(title)s.%(ext)s"
|
|
24
|
-
* @returns The current instance of DownloadBuilder for method chaining.
|
|
25
|
-
*/
|
|
26
|
-
output(template: string): this;
|
|
27
|
-
/**
|
|
28
|
-
* Execute the download with the specified options.
|
|
29
|
-
* This will run yt-dlp with the accumulated arguments and the provided URL.
|
|
30
|
-
* The output will be displayed in the console.
|
|
31
|
-
*
|
|
32
|
-
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* download("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
|
|
36
|
-
* .resolution("720p")
|
|
37
|
-
* .output("downloads/%(title)s.%(ext)s")
|
|
38
|
-
* .run();
|
|
39
|
-
*
|
|
40
|
-
*/
|
|
41
|
-
run(): Promise<void>;
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=download.d.ts.map
|
package/dist/download.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;IAGf,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;gBAER,GAAG,EAAE,MAAM;IAExC;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAS7B;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK9B;;;;;;;;;;;;;OAaG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAG1B"}
|
package/dist/download.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { runYtDlp } from "./internal/runner.js";
|
|
2
|
-
export class DownloadBuilder {
|
|
3
|
-
url;
|
|
4
|
-
args = [];
|
|
5
|
-
constructor(url) {
|
|
6
|
-
this.url = url;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Set the desired resolution for the video to be downloaded.
|
|
10
|
-
* This will instruct yt-dlp to download the best video and audio streams that are less than or equal to the specified height.
|
|
11
|
-
* For example, if you specify "720p", yt-dlp will download the best video and audio streams that are 720 pixels in height or less.
|
|
12
|
-
* If you want to download the best available quality regardless of resolution, you can omit this option or set it to a very high value like "9999p".
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* download("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
|
|
16
|
-
* .resolution("720p")
|
|
17
|
-
* .output("downloads/%(title)s.%(ext)s")
|
|
18
|
-
*
|
|
19
|
-
* @param res The desired resolution for the video. For example: "720p", "1080p", etc. This will tell yt-dlp to download the best video and audio streams that are less than or equal to the specified height. If you want to download the best available quality, you can omit this option or set it to a very high value like "9999p".
|
|
20
|
-
* @returns The current instance of DownloadBuilder for method chaining.
|
|
21
|
-
*/
|
|
22
|
-
resolution(res) {
|
|
23
|
-
const height = res.replace("p", "");
|
|
24
|
-
this.args.push("-f", `bestvideo[height<=${height}]+bestaudio/best[height<=${height}]`);
|
|
25
|
-
return this;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Set the output directory and filename template for the downloaded file.
|
|
29
|
-
*
|
|
30
|
-
* @param template The output template for the downloaded file. You can use placeholders like %(title)s, %(ext)s, etc. For example: "downloads/%(title)s.%(ext)s"
|
|
31
|
-
* @returns The current instance of DownloadBuilder for method chaining.
|
|
32
|
-
*/
|
|
33
|
-
output(template) {
|
|
34
|
-
this.args.push("-o", template);
|
|
35
|
-
return this;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Execute the download with the specified options.
|
|
39
|
-
* This will run yt-dlp with the accumulated arguments and the provided URL.
|
|
40
|
-
* The output will be displayed in the console.
|
|
41
|
-
*
|
|
42
|
-
* @throws Will throw an error if yt-dlp is not installed or not in PATH, or if any other error occurs during the execution of yt-dlp.
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* download("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
|
|
46
|
-
* .resolution("720p")
|
|
47
|
-
* .output("downloads/%(title)s.%(ext)s")
|
|
48
|
-
* .run();
|
|
49
|
-
*
|
|
50
|
-
*/
|
|
51
|
-
async run() {
|
|
52
|
-
await runYtDlp([...this.args, this.url]);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=download.js.map
|
package/dist/download.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAE9C,MAAM,OAAO,eAAe;IAGE;IAFZ,IAAI,GAAa,EAAE,CAAC;IAErC,YAA6B,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IAAG,CAAC;IAE5C;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,GAAW;QACrB,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CACb,IAAI,EACJ,qBAAqB,MAAM,4BAA4B,MAAM,GAAG,CAChE,CAAC;QACF,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAgB;QACtB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,GAAG;QACR,MAAM,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,CAAC;CACD"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAE9C,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAErD"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,QAAQ,CAAC,GAAW;IACnC,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/internal/runner.ts"],"names":[],"mappings":"AAEA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,CAOlD"}
|
package/dist/internal/runner.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { execa, ExecaError } from "execa";
|
|
2
|
-
export async function runYtDlp(args) {
|
|
3
|
-
await execa("yt-dlp", ["--js-runtimes", "node", ...args], {
|
|
4
|
-
stdio: "inherit",
|
|
5
|
-
}).catch(handleEnoent);
|
|
6
|
-
}
|
|
7
|
-
export function handleEnoent(error) {
|
|
8
|
-
if (error instanceof ExecaError && error.code === "ENOENT") {
|
|
9
|
-
throw new Error("yt-dlp is not installed or not in PATH. Please refer to https://github.com/yt-dlp/yt-dlp#installation");
|
|
10
|
-
}
|
|
11
|
-
throw error;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=runner.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/internal/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAE,UAAU,EAAC,MAAM,OAAO,CAAC;AAExC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAc;IAC5C,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE;QACzD,KAAK,EAAE,SAAS;KAChB,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc;IAC1C,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CACd,uGAAuG,CACvG,CAAC;IACH,CAAC;IACD,MAAM,KAAK,CAAC;AACb,CAAC"}
|
package/dist/types.d.ts
DELETED
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/dist/version.d.ts
DELETED
package/dist/version.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/dist/version.js
DELETED
package/dist/version.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|