yt-dlp-bridge 0.1.4 → 0.1.6

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.
Files changed (2) hide show
  1. package/README.md +68 -165
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -2,92 +2,64 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/yt-dlp-bridge.svg)](https://www.npmjs.com/package/yt-dlp-bridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/yt-dlp-bridge.svg)](https://www.npmjs.com/package/yt-dlp-bridge)
5
+ [![CI](https://github.com/antonio-orionus/yt-dlp-bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/antonio-orionus/yt-dlp-bridge/actions/workflows/ci.yml)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
- [![Node.js >=22.13](https://img.shields.io/badge/node-%3E%3D22.13-brightgreen.svg)](package.json)
8
7
 
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.
8
+ TypeScript library for safe, no-shell `yt-dlp` integration in Node.js services: policy-aware command planning, argv generation, environment checks, process execution, output parsing, secret redaction, and structured errors.
10
9
 
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
10
+ `yt-dlp-bridge` is intentionally MCP-agnostic. It is the integration layer used by `yt-dlp-mcp-server`, but it works anywhere a Node.js service needs to plan or run `yt-dlp` without shell interpolation.
14
11
 
12
+ - [Install](#install)
15
13
  - [Features](#features)
16
- - [Quick Start](#quick-start)
17
- - [Installation](#installation)
18
14
  - [Usage](#usage)
19
- - [API Surface](#api-surface)
15
+ - [API](#api)
20
16
  - [Configuration](#configuration)
21
17
  - [Requirements](#requirements)
22
18
  - [Development](#development)
23
- - [Release](#release)
24
19
  - [Troubleshooting](#troubleshooting)
25
20
  - [License](#license)
26
21
 
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
22
+ ## Install
39
23
 
40
24
  ```bash
41
25
  npm install yt-dlp-bridge
26
+ # pnpm add yt-dlp-bridge
27
+ # yarn add yt-dlp-bridge
28
+ # bun add yt-dlp-bridge
42
29
  ```
43
30
 
31
+ Requires Node.js >= 22.13 and ESM.
32
+
44
33
  ```ts
45
- import {
46
- PlanDownloadInputSchema,
47
- loadConfig,
48
- planDownload
49
- } from "yt-dlp-bridge";
34
+ import { PlanDownloadInputSchema, loadConfig, planDownload } from "yt-dlp-bridge";
50
35
 
51
36
  const config = loadConfig();
52
37
  const input = PlanDownloadInputSchema.parse({
53
38
  url: "https://www.youtube.com/watch?v=BaW_jenozKc",
54
39
  kind: "audio",
55
- postprocess: {
56
- audioFormat: "mp3"
57
- },
58
- output: {
59
- outputRoot: "audio"
60
- }
40
+ postprocess: { audioFormat: "mp3" },
41
+ output: { outputRoot: "audio" }
61
42
  });
62
43
 
63
44
  const plan = await planDownload(input, config);
64
-
65
- console.log(plan.commandPreview.command);
66
45
  console.log(plan.commandPreview.redactedArgs);
67
46
  console.log(plan.requiredDependencies);
68
47
  ```
69
48
 
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:
49
+ ## Features
79
50
 
80
- ```bash
81
- git clone https://github.com/antonio-orionus/yt-dlp-bridge.git
82
- cd yt-dlp-bridge
83
- pnpm install
84
- pnpm run build
85
- pnpm test
86
- ```
51
+ - Source-derived option catalog generated from `yt_dlp.options.create_parser`.
52
+ - Safe argv builders that return argument arrays instead of shell command strings.
53
+ - Dependency-aware download and post-processing plans for `yt-dlp`, `ffmpeg`, `ffprobe`, external downloaders, browser impersonation, and JavaScript runtimes.
54
+ - Managed output policy for output roots, temp roots, archive files, overwrite behavior, and parent-directory traversal checks.
55
+ - Secret redaction for auth flags, cookies, signed URLs, and command previews.
56
+ - Parsers for JSON lines, format lists, subtitle lists, thumbnail lists, progress output, and final output paths.
57
+ - Structured error adaptation through [`ytdlp-errors`](https://www.npmjs.com/package/ytdlp-errors).
58
+ - ESM and TypeScript declarations.
87
59
 
88
60
  ## Usage
89
61
 
90
- ### Build Inspect Arguments
62
+ ### Inspect metadata
91
63
 
92
64
  Use the Zod schemas to fill defaults before passing inputs into the low-level builders.
93
65
 
@@ -97,69 +69,47 @@ import { InspectInputSchema, buildMetadataArgs } from "yt-dlp-bridge";
97
69
  const input = InspectInputSchema.parse({
98
70
  url: "https://www.youtube.com/watch?v=BaW_jenozKc"
99
71
  });
100
-
101
72
  const args = buildMetadataArgs(input);
102
-
103
- console.log(args);
104
73
  // ["--ignore-config", "--no-warnings", "--dump-json", "https://www.youtube.com/watch?v=BaW_jenozKc"]
105
74
  ```
106
75
 
107
- ### Plan a Download
76
+ ### Plan a download
108
77
 
109
78
  `planDownload` resolves output policy, builds the final argv, redacts secrets, checks available dependencies, and explains risks and side effects before anything is downloaded.
110
79
 
111
80
  ```ts
112
- import {
113
- PlanDownloadInputSchema,
114
- loadConfig,
115
- planDownload
116
- } from "yt-dlp-bridge";
81
+ import { PlanDownloadInputSchema, loadConfig, planDownload } from "yt-dlp-bridge";
117
82
 
118
83
  const config = loadConfig({
119
84
  YTDLP_MCP_OUTPUT_ROOT: "/srv/downloads",
120
85
  YTDLP_MCP_TEMP_ROOT: "/srv/downloads/.tmp"
121
86
  });
122
-
123
87
  const input = PlanDownloadInputSchema.parse({
124
88
  url: "https://www.youtube.com/watch?v=BaW_jenozKc",
125
89
  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
- }
90
+ selection: { downloadArchive: "archive.txt" },
91
+ format: { format: "bv*+ba/b" },
92
+ output: { outputTemplate: "%(playlist_index)s-%(title).180B [%(id)s].%(ext)s" }
135
93
  });
136
94
 
137
95
  const plan = await planDownload(input, config);
138
-
139
96
  console.log(plan.argv);
140
97
  console.log(plan.risks);
141
98
  console.log(plan.sideEffects);
142
99
  ```
143
100
 
144
- ### Run a Planned Command
101
+ ### Run a planned command
145
102
 
146
103
  The runner uses `spawn` with `shell: false`, bounded output capture, timeouts, and structured failures.
147
104
 
148
105
  ```ts
149
- import {
150
- PlanDownloadInputSchema,
151
- loadConfig,
152
- planDownload,
153
- runCommand,
154
- toStructuredError
155
- } from "yt-dlp-bridge";
106
+ import { PlanDownloadInputSchema, loadConfig, planDownload, runCommand, toStructuredError } from "yt-dlp-bridge";
156
107
 
157
108
  const config = loadConfig();
158
109
  const input = PlanDownloadInputSchema.parse({
159
110
  url: "https://www.youtube.com/watch?v=BaW_jenozKc",
160
111
  kind: "video"
161
112
  });
162
-
163
113
  const plan = await planDownload(input, config);
164
114
 
165
115
  try {
@@ -167,143 +117,96 @@ try {
167
117
  timeoutMs: config.defaultTimeoutMs,
168
118
  maxOutputBytes: config.maxOutputBytes
169
119
  });
170
-
171
120
  console.log(result.stdout);
172
121
  } catch (error) {
173
122
  console.error(toStructuredError(error));
174
123
  }
175
124
  ```
176
125
 
177
- ### Inspect the Option Catalog
126
+ ### Query the option catalog
178
127
 
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.
128
+ The bundled catalog is generated from `yt_dlp.options.create_parser` for yt-dlp `2026.03.17` and contains 323 upstream options.
180
129
 
181
130
  ```ts
182
- import {
183
- UPSTREAM_OPTION_CATALOG,
184
- findOptionByFlag,
185
- listLongFlags,
186
- optionMetadata
187
- } from "yt-dlp-bridge";
131
+ import { UPSTREAM_OPTION_CATALOG, findOptionByFlag, listLongFlags, optionMetadata } from "yt-dlp-bridge";
188
132
 
189
133
  const format = findOptionByFlag("--format");
190
-
191
- console.log(UPSTREAM_OPTION_CATALOG.optionCount);
192
- console.log(listLongFlags().includes("--dump-json"));
134
+ console.log(UPSTREAM_OPTION_CATALOG.optionCount); // 323
135
+ console.log(listLongFlags().includes("--dump-json")); // true
193
136
  console.log(format ? optionMetadata(format) : undefined);
194
137
  ```
195
138
 
196
- ## API Surface
139
+ ## API
197
140
 
198
141
  | Area | Exports |
199
142
  | --- | --- |
200
143
  | Argv builders | `ytdlpCommand`, `buildMetadataArgs`, `buildSingleJsonArgs`, `buildListArgs`, `buildSimulationArgs`, `buildDownloadArgs` |
201
144
  | Planning | `planDownload`, `planPostprocess` |
202
- | Configuration and environment | `loadConfig`, `CONFIG`, `checkEnvironment` |
145
+ | Config and environment | `loadConfig`, `CONFIG`, `checkEnvironment` |
203
146
  | Filesystem policy | `resolveOutputPolicy`, `resolveManagedPath`, `ensureWithinRoot`, `isPathInside`, `isPathInsideWith`, `hasParentTraversal`, `ensureDirectory`, `readArchive` |
204
147
  | Option catalog | `UPSTREAM_OPTION_CATALOG`, `listLongFlags`, `findOptionByFlag`, `optionMetadata` |
205
148
  | Parsers | `parseJsonLines`, `sanitizeMetadataItem`, `sanitizeMetadataItems`, `paginate`, `parseFormats`, `parseSubtitles`, `parseThumbnails`, `parseProgress`, `parseFinalPaths` |
206
149
  | Process and errors | `runCommand`, `CommandExecutionError`, `toStructuredError` |
207
150
  | Redaction | `redactArgs`, `redactText`, `excerpt` |
208
- | Schemas and types | Zod input schemas and TypeScript interfaces exported from `src/index.ts` |
151
+ | Schemas and types | Zod input schemas and TypeScript interfaces |
209
152
 
210
153
  ## Configuration
211
154
 
212
- `loadConfig()` reads environment variables and applies conservative defaults.
155
+ `loadConfig(env?)` reads environment variables and applies conservative defaults. Pass a partial `ProcessEnv` object to override specific values.
213
156
 
214
157
  | Variable | Default | Purpose |
215
158
  | --- | --- | --- |
216
- | `YTDLP_MCP_YTDLP_PATH` or `YTDLP_PATH` | `yt-dlp` | Path or command name used for `yt-dlp`. |
159
+ | `YTDLP_MCP_YTDLP_PATH` or `YTDLP_PATH` | `yt-dlp` | Path or command name for `yt-dlp`. |
217
160
  | `YTDLP_MCP_FFMPEG_PATH` or `FFMPEG_PATH` | `ffmpeg` | Optional ffmpeg override for environment checks. |
218
161
  | `YTDLP_MCP_FFPROBE_PATH` or `FFPROBE_PATH` | `ffprobe` | Optional ffprobe override for environment checks. |
219
162
  | `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. |
163
+ | `YTDLP_MCP_TEMP_ROOT` | OS temp under `yt-dlp-mcp` | Managed temp root. |
164
+ | `YTDLP_MCP_ALLOW_ARBITRARY_OUTPUT_PATHS` | `false` | Allow output paths outside the configured roots. |
165
+ | `YTDLP_MCP_ALLOW_CONFIG_FILES` | `false` | Allow user-provided cookies, netrc, and config-file inputs. |
166
+ | `YTDLP_MCP_ALLOW_PLUGIN_DIRS` | `false` | Allow user-provided plugin directory paths. |
223
167
  | `YTDLP_MCP_COOKIES_FILE` | unset | Server-level cookies file. |
224
168
  | `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. |
169
+ | `YTDLP_MCP_ENABLE_EXPERT` | `false` | Enable higher-risk expert-mode integrations. |
170
+ | `YTDLP_MCP_TIMEOUT_MS` | `900000` | Default command timeout (ms). |
171
+ | `YTDLP_MCP_MAX_OUTPUT_BYTES` | `4194304` | Maximum retained stdout/stderr bytes. |
228
172
  | `YTDLP_MCP_JS_RUNTIMES` | `deno,node,bun,quickjs` | JavaScript runtimes considered for extractor challenges. |
229
173
 
230
174
  ## Requirements
231
175
 
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.
176
+ - Node.js >= 22.13, ESM.
177
+ - `yt-dlp` installed when planning or running yt-dlp workflows.
178
+ - `ffmpeg` and `ffprobe` for audio extraction, merge, remux, recode, segment editing, subtitle/thumbnail conversion, and embedding workflows.
179
+ - Python `yt_dlp` package (or `PYTHONPATH` pointing at a yt-dlp checkout) when regenerating or verifying the option catalog.
237
180
 
238
181
  ## Development
239
182
 
183
+ ```bash
184
+ git clone https://github.com/antonio-orionus/yt-dlp-bridge.git
185
+ cd yt-dlp-bridge
186
+ pnpm install
187
+ ```
188
+
240
189
  | Command | Description |
241
190
  | --- | --- |
242
191
  | `pnpm run build` | Compile TypeScript and copy generated assets into `dist`. |
243
192
  | `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
263
- ```
264
-
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
- ```
193
+ | `pnpm run typecheck` | TypeScript check without emitting. |
194
+ | `pnpm run generate:options` | Regenerate the option catalog from Python `yt_dlp`. |
195
+ | `pnpm run verify:options` | Verify the catalog matches Python `yt_dlp`. |
196
+ | `pnpm pack --dry-run` | Preview package contents before publishing. |
284
197
 
285
198
  ## Troubleshooting
286
199
 
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.
200
+ **`yt-dlp` is missing** — Install `yt-dlp` or set `YTDLP_MCP_YTDLP_PATH`. `checkEnvironment()` reports detected command, status, version, and notes.
298
201
 
299
- ### `outputTemplate must not contain parent-directory traversal`
202
+ **`ffmpeg`/`ffprobe` missing** — Install the binary or set `YTDLP_MCP_FFMPEG_PATH` / `YTDLP_MCP_FFPROBE_PATH`. Planning still returns dependency info so callers can surface which workflow requires the missing tool.
300
203
 
301
- Relative output templates cannot contain `..` path segments unless arbitrary output paths are explicitly allowed by policy.
204
+ **`auth.cookiesFile requires YTDLP_MCP_ALLOW_CONFIG_FILES=true`** — 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 after reviewing the trust boundary.
302
205
 
303
- ## Contributing
206
+ **`outputTemplate must not contain parent-directory traversal`** — Relative templates cannot contain `..` segments unless `YTDLP_MCP_ALLOW_ARBITRARY_OUTPUT_PATHS=true`.
304
207
 
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).
208
+ Bugs and feature requests: [GitHub Issues](https://github.com/antonio-orionus/yt-dlp-bridge/issues).
306
209
 
307
210
  ## License
308
211
 
309
- [MIT](LICENSE)
212
+ [MIT](LICENSE) © 2026 Antonio Orionus
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "yt-dlp-bridge",
3
- "version": "0.1.4",
4
- "description": "TypeScript toolkit for safe yt-dlp command planning, argv generation, execution, parsing, and structured errors.",
3
+ "version": "0.1.6",
4
+ "description": "TypeScript library for safe, no-shell yt-dlp integration: command planning, argv generation, process execution, output parsing, and structured errors.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Antonio Orionus",
@@ -39,22 +39,22 @@
39
39
  },
40
40
  "keywords": [
41
41
  "yt-dlp",
42
- "yt-dlp-wrapper",
43
42
  "yt-dlp-node",
44
43
  "youtube-dl",
45
44
  "media-downloader",
46
45
  "video-downloader",
47
- "download-manager",
48
46
  "ffmpeg",
49
47
  "metadata-extraction",
50
48
  "command-builder",
51
49
  "argv",
50
+ "no-shell",
51
+ "subprocess",
52
+ "redaction",
53
+ "structured-errors",
52
54
  "typescript",
53
55
  "esm",
54
56
  "zod",
55
- "mcp",
56
- "planner",
57
- "wrapper"
57
+ "mcp"
58
58
  ],
59
59
  "dependencies": {
60
60
  "ytdlp-errors": "^1.1.0",