yt-dlp-bridge 0.1.0 → 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 +298 -8
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -1,19 +1,309 @@
|
|
|
1
1
|
# yt-dlp-bridge
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/yt-dlp-bridge)
|
|
4
|
+
[](https://www.npmjs.com/package/yt-dlp-bridge)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](package.json)
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
TypeScript primitives for building safe, policy-aware integrations on top of `yt-dlp`: command planning, argv generation, environment checks, process execution, output parsing, redaction, and structured errors.
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
`yt-dlp-bridge` is intentionally MCP-agnostic. It is the integration layer used by `yt-dlp-mcp-server`, but it can be used anywhere a Node.js service needs to plan or run `yt-dlp` without shell interpolation.
|
|
12
|
+
|
|
13
|
+
## Contents
|
|
14
|
+
|
|
15
|
+
- [Features](#features)
|
|
16
|
+
- [Quick Start](#quick-start)
|
|
17
|
+
- [Installation](#installation)
|
|
18
|
+
- [Usage](#usage)
|
|
19
|
+
- [API Surface](#api-surface)
|
|
20
|
+
- [Configuration](#configuration)
|
|
21
|
+
- [Requirements](#requirements)
|
|
22
|
+
- [Development](#development)
|
|
23
|
+
- [Release](#release)
|
|
24
|
+
- [Troubleshooting](#troubleshooting)
|
|
25
|
+
- [License](#license)
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Source-derived option catalog generated from `yt_dlp.options.create_parser`.
|
|
30
|
+
- Safe argv builders that return argument arrays instead of shell command strings.
|
|
31
|
+
- Dependency-aware download and post-processing plans for `yt-dlp`, `ffmpeg`, `ffprobe`, external downloaders, browser impersonation, and JavaScript runtimes.
|
|
32
|
+
- Managed output policy for output roots, temp roots, archive files, overwrite behavior, and parent-directory traversal checks.
|
|
33
|
+
- Secret redaction for auth flags, cookies, signed URLs, and command previews.
|
|
34
|
+
- Parsers for JSON lines, format lists, subtitle lists, thumbnail lists, progress output, and final output paths.
|
|
35
|
+
- Structured error adaptation through [`ytdlp-errors`](https://www.npmjs.com/package/ytdlp-errors).
|
|
36
|
+
- ESM and TypeScript declarations out of the box.
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
8
39
|
|
|
9
40
|
```bash
|
|
10
|
-
|
|
41
|
+
npm install yt-dlp-bridge
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import {
|
|
46
|
+
PlanDownloadInputSchema,
|
|
47
|
+
loadConfig,
|
|
48
|
+
planDownload
|
|
49
|
+
} from "yt-dlp-bridge";
|
|
50
|
+
|
|
51
|
+
const config = loadConfig();
|
|
52
|
+
const input = PlanDownloadInputSchema.parse({
|
|
53
|
+
url: "https://www.youtube.com/watch?v=BaW_jenozKc",
|
|
54
|
+
kind: "audio",
|
|
55
|
+
postprocess: {
|
|
56
|
+
audioFormat: "mp3"
|
|
57
|
+
},
|
|
58
|
+
output: {
|
|
59
|
+
outputRoot: "audio"
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const plan = await planDownload(input, config);
|
|
64
|
+
|
|
65
|
+
console.log(plan.commandPreview.command);
|
|
66
|
+
console.log(plan.commandPreview.redactedArgs);
|
|
67
|
+
console.log(plan.requiredDependencies);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
For package consumers:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm install yt-dlp-bridge
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For source development, this repository uses pnpm:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
git clone https://github.com/antonio-orionus/yt-dlp-bridge.git
|
|
82
|
+
cd yt-dlp-bridge
|
|
11
83
|
pnpm install
|
|
12
|
-
pnpm test
|
|
13
|
-
pnpm run typecheck
|
|
14
84
|
pnpm run build
|
|
85
|
+
pnpm test
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Usage
|
|
89
|
+
|
|
90
|
+
### Build Inspect Arguments
|
|
91
|
+
|
|
92
|
+
Use the Zod schemas to fill defaults before passing inputs into the low-level builders.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { InspectInputSchema, buildMetadataArgs } from "yt-dlp-bridge";
|
|
96
|
+
|
|
97
|
+
const input = InspectInputSchema.parse({
|
|
98
|
+
url: "https://www.youtube.com/watch?v=BaW_jenozKc"
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const args = buildMetadataArgs(input);
|
|
102
|
+
|
|
103
|
+
console.log(args);
|
|
104
|
+
// ["--ignore-config", "--no-warnings", "--dump-json", "https://www.youtube.com/watch?v=BaW_jenozKc"]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Plan a Download
|
|
108
|
+
|
|
109
|
+
`planDownload` resolves output policy, builds the final argv, redacts secrets, checks available dependencies, and explains risks and side effects before anything is downloaded.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import {
|
|
113
|
+
PlanDownloadInputSchema,
|
|
114
|
+
loadConfig,
|
|
115
|
+
planDownload
|
|
116
|
+
} from "yt-dlp-bridge";
|
|
117
|
+
|
|
118
|
+
const config = loadConfig({
|
|
119
|
+
YTDLP_MCP_OUTPUT_ROOT: "/srv/downloads",
|
|
120
|
+
YTDLP_MCP_TEMP_ROOT: "/srv/downloads/.tmp"
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const input = PlanDownloadInputSchema.parse({
|
|
124
|
+
url: "https://www.youtube.com/watch?v=BaW_jenozKc",
|
|
125
|
+
kind: "video",
|
|
126
|
+
selection: {
|
|
127
|
+
downloadArchive: "archive.txt"
|
|
128
|
+
},
|
|
129
|
+
format: {
|
|
130
|
+
format: "bv*+ba/b"
|
|
131
|
+
},
|
|
132
|
+
output: {
|
|
133
|
+
outputTemplate: "%(playlist_index)s-%(title).180B [%(id)s].%(ext)s"
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const plan = await planDownload(input, config);
|
|
138
|
+
|
|
139
|
+
console.log(plan.argv);
|
|
140
|
+
console.log(plan.risks);
|
|
141
|
+
console.log(plan.sideEffects);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Run a Planned Command
|
|
145
|
+
|
|
146
|
+
The runner uses `spawn` with `shell: false`, bounded output capture, timeouts, and structured failures.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import {
|
|
150
|
+
PlanDownloadInputSchema,
|
|
151
|
+
loadConfig,
|
|
152
|
+
planDownload,
|
|
153
|
+
runCommand,
|
|
154
|
+
toStructuredError
|
|
155
|
+
} from "yt-dlp-bridge";
|
|
156
|
+
|
|
157
|
+
const config = loadConfig();
|
|
158
|
+
const input = PlanDownloadInputSchema.parse({
|
|
159
|
+
url: "https://www.youtube.com/watch?v=BaW_jenozKc",
|
|
160
|
+
kind: "video"
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const plan = await planDownload(input, config);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const result = await runCommand(plan.commandPreview.command, plan.commandPreview.args, {
|
|
167
|
+
timeoutMs: config.defaultTimeoutMs,
|
|
168
|
+
maxOutputBytes: config.maxOutputBytes
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
console.log(result.stdout);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.error(toStructuredError(error));
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Inspect the Option Catalog
|
|
178
|
+
|
|
179
|
+
The bundled catalog in this release is generated from `yt_dlp.options.create_parser` for yt-dlp `2026.03.17` and contains 323 upstream options.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import {
|
|
183
|
+
UPSTREAM_OPTION_CATALOG,
|
|
184
|
+
findOptionByFlag,
|
|
185
|
+
listLongFlags,
|
|
186
|
+
optionMetadata
|
|
187
|
+
} from "yt-dlp-bridge";
|
|
188
|
+
|
|
189
|
+
const format = findOptionByFlag("--format");
|
|
190
|
+
|
|
191
|
+
console.log(UPSTREAM_OPTION_CATALOG.optionCount);
|
|
192
|
+
console.log(listLongFlags().includes("--dump-json"));
|
|
193
|
+
console.log(format ? optionMetadata(format) : undefined);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## API Surface
|
|
197
|
+
|
|
198
|
+
| Area | Exports |
|
|
199
|
+
| --- | --- |
|
|
200
|
+
| Argv builders | `ytdlpCommand`, `buildMetadataArgs`, `buildSingleJsonArgs`, `buildListArgs`, `buildSimulationArgs`, `buildDownloadArgs` |
|
|
201
|
+
| Planning | `planDownload`, `planPostprocess` |
|
|
202
|
+
| Configuration and environment | `loadConfig`, `CONFIG`, `checkEnvironment` |
|
|
203
|
+
| Filesystem policy | `resolveOutputPolicy`, `resolveManagedPath`, `ensureWithinRoot`, `isPathInside`, `isPathInsideWith`, `hasParentTraversal`, `ensureDirectory`, `readArchive` |
|
|
204
|
+
| Option catalog | `UPSTREAM_OPTION_CATALOG`, `listLongFlags`, `findOptionByFlag`, `optionMetadata` |
|
|
205
|
+
| Parsers | `parseJsonLines`, `sanitizeMetadataItem`, `sanitizeMetadataItems`, `paginate`, `parseFormats`, `parseSubtitles`, `parseThumbnails`, `parseProgress`, `parseFinalPaths` |
|
|
206
|
+
| Process and errors | `runCommand`, `CommandExecutionError`, `toStructuredError` |
|
|
207
|
+
| Redaction | `redactArgs`, `redactText`, `excerpt` |
|
|
208
|
+
| Schemas and types | Zod input schemas and TypeScript interfaces exported from `src/index.ts` |
|
|
209
|
+
|
|
210
|
+
## Configuration
|
|
211
|
+
|
|
212
|
+
`loadConfig()` reads environment variables and applies conservative defaults.
|
|
213
|
+
|
|
214
|
+
| Variable | Default | Purpose |
|
|
215
|
+
| --- | --- | --- |
|
|
216
|
+
| `YTDLP_MCP_YTDLP_PATH` or `YTDLP_PATH` | `yt-dlp` | Path or command name used for `yt-dlp`. |
|
|
217
|
+
| `YTDLP_MCP_FFMPEG_PATH` or `FFMPEG_PATH` | `ffmpeg` | Optional ffmpeg override for environment checks. |
|
|
218
|
+
| `YTDLP_MCP_FFPROBE_PATH` or `FFPROBE_PATH` | `ffprobe` | Optional ffprobe override for environment checks. |
|
|
219
|
+
| `YTDLP_MCP_OUTPUT_ROOT` | `~/Downloads/yt-dlp-mcp` | Managed output root. |
|
|
220
|
+
| `YTDLP_MCP_TEMP_ROOT` | OS temp directory under `yt-dlp-mcp` | Managed temp root. |
|
|
221
|
+
| `YTDLP_MCP_ALLOW_ARBITRARY_OUTPUT_PATHS` | `false` | Allows output and temp paths outside the configured roots. |
|
|
222
|
+
| `YTDLP_MCP_ALLOW_CONFIG_FILES` | `false` | Allows user-provided cookies, netrc, and related config-file inputs unless they match server-level settings. |
|
|
223
|
+
| `YTDLP_MCP_COOKIES_FILE` | unset | Server-level cookies file. |
|
|
224
|
+
| `YTDLP_MCP_COOKIES_FROM_BROWSER` | unset | Server-level browser cookie source for `--cookies-from-browser`. |
|
|
225
|
+
| `YTDLP_MCP_ENABLE_EXPERT` | `false` | Enables higher-risk expert-mode integrations in callers that expose them. |
|
|
226
|
+
| `YTDLP_MCP_TIMEOUT_MS` | `900000` | Default command timeout. |
|
|
227
|
+
| `YTDLP_MCP_MAX_OUTPUT_BYTES` | `4194304` | Maximum retained stdout or stderr bytes. |
|
|
228
|
+
| `YTDLP_MCP_JS_RUNTIMES` | `deno,node,bun,quickjs` | JavaScript runtimes considered for extractor challenges. |
|
|
229
|
+
|
|
230
|
+
## Requirements
|
|
231
|
+
|
|
232
|
+
- Node.js >= 22.13.
|
|
233
|
+
- ESM import support.
|
|
234
|
+
- `yt-dlp` installed when planning or running real yt-dlp workflows.
|
|
235
|
+
- `ffmpeg` and `ffprobe` for audio extraction, audio/video merge, remuxing, recoding, segment editing, subtitle conversion, thumbnail conversion, and embedding workflows.
|
|
236
|
+
- Python `yt_dlp` package, or `PYTHONPATH` pointed at a yt-dlp source checkout, when regenerating or verifying the option catalog.
|
|
237
|
+
|
|
238
|
+
## Development
|
|
239
|
+
|
|
240
|
+
| Command | Description |
|
|
241
|
+
| --- | --- |
|
|
242
|
+
| `pnpm run build` | Compile TypeScript and copy generated assets into `dist`. |
|
|
243
|
+
| `pnpm test` | Run Vitest tests. |
|
|
244
|
+
| `pnpm run typecheck` | Run TypeScript without emitting files. |
|
|
245
|
+
| `pnpm run generate:options` | Regenerate the source-derived yt-dlp option catalog from Python `yt_dlp`. |
|
|
246
|
+
| `pnpm run verify:options` | Verify that the generated option catalog matches Python `yt_dlp`. |
|
|
247
|
+
| `pnpm pack --dry-run` | Preview the package contents before publishing. |
|
|
248
|
+
|
|
249
|
+
## Release
|
|
250
|
+
|
|
251
|
+
GitHub Actions handles CI and npm publishing:
|
|
252
|
+
|
|
253
|
+
- `.github/workflows/ci.yml` runs typecheck, tests, build, and package dry-run on pull requests and pushes to `main`.
|
|
254
|
+
- `.github/workflows/release.yml` publishes to npm when a `vX.Y.Z` tag is pushed and the tag matches `package.json`.
|
|
255
|
+
- Publishing uses npm trusted publishing with GitHub Actions OIDC and `npm publish --access public`; no `NPM_TOKEN` secret is required when the trusted publisher is configured. npm automatically generates provenance for trusted publishes from GitHub Actions.
|
|
256
|
+
|
|
257
|
+
The npm trusted publisher should point at:
|
|
258
|
+
|
|
259
|
+
```text
|
|
260
|
+
repository: antonio-orionus/yt-dlp-bridge
|
|
261
|
+
workflow file: release.yml
|
|
262
|
+
environment: npm
|
|
15
263
|
```
|
|
16
264
|
|
|
17
|
-
|
|
265
|
+
Release flow:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
pnpm version patch
|
|
269
|
+
git push origin main --follow-tags
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Project Structure
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
yt-dlp-bridge/
|
|
276
|
+
├── .github/workflows/ # CI and npm publish automation
|
|
277
|
+
├── src/ # TypeScript source and generated option catalog
|
|
278
|
+
├── tests/ # Vitest coverage for argv, policy, parsers, planning, and errors
|
|
279
|
+
├── scripts/ # Option catalog generation and package asset scripts
|
|
280
|
+
├── dist/ # Built package output
|
|
281
|
+
├── package.json # Package metadata, exports, scripts, and npm keywords
|
|
282
|
+
└── README.md # Package and repository documentation
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Troubleshooting
|
|
286
|
+
|
|
287
|
+
### `yt-dlp` is missing
|
|
288
|
+
|
|
289
|
+
Install `yt-dlp` or set `YTDLP_MCP_YTDLP_PATH` to the executable path. `checkEnvironment()` reports the detected command, status, version, and notes.
|
|
290
|
+
|
|
291
|
+
### `ffmpeg` or `ffprobe` is missing
|
|
292
|
+
|
|
293
|
+
Install the missing binary or set `YTDLP_MCP_FFMPEG_PATH` and `YTDLP_MCP_FFPROBE_PATH`. Planning still returns dependency information so callers can explain which workflow requires the missing tool.
|
|
294
|
+
|
|
295
|
+
### `auth.cookiesFile requires YTDLP_MCP_ALLOW_CONFIG_FILES=true`
|
|
296
|
+
|
|
297
|
+
User-provided config-file paths are blocked by default. Prefer server-level `YTDLP_MCP_COOKIES_FILE` or enable `YTDLP_MCP_ALLOW_CONFIG_FILES=true` only when the caller has reviewed the trust boundary.
|
|
298
|
+
|
|
299
|
+
### `outputTemplate must not contain parent-directory traversal`
|
|
300
|
+
|
|
301
|
+
Relative output templates cannot contain `..` path segments unless arbitrary output paths are explicitly allowed by policy.
|
|
302
|
+
|
|
303
|
+
## Contributing
|
|
304
|
+
|
|
305
|
+
Use the development commands above before opening a pull request. Bugs and feature requests can be reported through [GitHub Issues](https://github.com/antonio-orionus/yt-dlp-bridge/issues).
|
|
306
|
+
|
|
307
|
+
## License
|
|
18
308
|
|
|
19
|
-
|
|
309
|
+
[MIT](LICENSE)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yt-dlp-bridge",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "TypeScript toolkit for safe yt-dlp command planning, argv generation, execution, parsing, and structured errors.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Antonio Orionus",
|
|
@@ -39,11 +39,20 @@
|
|
|
39
39
|
},
|
|
40
40
|
"keywords": [
|
|
41
41
|
"yt-dlp",
|
|
42
|
+
"yt-dlp-wrapper",
|
|
43
|
+
"yt-dlp-node",
|
|
42
44
|
"youtube-dl",
|
|
45
|
+
"media-downloader",
|
|
46
|
+
"video-downloader",
|
|
47
|
+
"download-manager",
|
|
43
48
|
"ffmpeg",
|
|
49
|
+
"metadata-extraction",
|
|
44
50
|
"command-builder",
|
|
51
|
+
"argv",
|
|
45
52
|
"typescript",
|
|
46
|
-
"
|
|
53
|
+
"esm",
|
|
54
|
+
"zod",
|
|
55
|
+
"mcp",
|
|
47
56
|
"planner",
|
|
48
57
|
"wrapper"
|
|
49
58
|
],
|
|
@@ -57,7 +66,7 @@
|
|
|
57
66
|
"vitest": "^4.0.15"
|
|
58
67
|
},
|
|
59
68
|
"engines": {
|
|
60
|
-
"node": ">=
|
|
69
|
+
"node": ">=22.13"
|
|
61
70
|
},
|
|
62
71
|
"publishConfig": {
|
|
63
72
|
"access": "public"
|