@koda-sl/baker-cli 0.209.0 → 0.211.0-dev.e5398b13c
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 +38 -2
- package/dist/{chunk-3E33AGNR.js → chunk-2IB3IL4K.js} +2 -2
- package/dist/{chunk-CRXSLYEX.js → chunk-3FBQKD7O.js} +3 -3
- package/dist/{chunk-FUSTYLP5.js → chunk-5I66YT7A.js} +3 -3
- package/dist/{chunk-IRNM3T6B.js → chunk-DZUVUGEP.js} +2 -1
- package/dist/{chunk-3WODSPNZ.js → chunk-P6ZNIFAQ.js} +4 -4
- package/dist/{chunk-E2WYWHJJ.js → chunk-XGIJGOKR.js} +46 -15
- package/dist/chunk-XGIJGOKR.js.map +1 -0
- package/dist/cli.js +2162 -1755
- package/dist/cli.js.map +1 -1
- package/dist/client-32DO7WEZ.js +15 -0
- package/dist/engine/index.js +3 -3
- package/dist/{env-7SCX7HAH.js → env-FWMZXMQK.js} +2 -2
- package/dist/{output-4YIOSWOG.js → output-WRHUJR74.js} +5 -5
- package/dist/{shared-EBF5DEDJ.js → shared-T66YQ6MB.js} +6 -6
- package/package.json +1 -1
- package/dist/chunk-E2WYWHJJ.js.map +0 -1
- package/dist/client-CF6ZORCO.js +0 -15
- /package/dist/{chunk-3E33AGNR.js.map → chunk-2IB3IL4K.js.map} +0 -0
- /package/dist/{chunk-CRXSLYEX.js.map → chunk-3FBQKD7O.js.map} +0 -0
- /package/dist/{chunk-FUSTYLP5.js.map → chunk-5I66YT7A.js.map} +0 -0
- /package/dist/{chunk-IRNM3T6B.js.map → chunk-DZUVUGEP.js.map} +0 -0
- /package/dist/{chunk-3WODSPNZ.js.map → chunk-P6ZNIFAQ.js.map} +0 -0
- /package/dist/{client-CF6ZORCO.js.map → client-32DO7WEZ.js.map} +0 -0
- /package/dist/{env-7SCX7HAH.js.map → env-FWMZXMQK.js.map} +0 -0
- /package/dist/{output-4YIOSWOG.js.map → output-WRHUJR74.js.map} +0 -0
- /package/dist/{shared-EBF5DEDJ.js.map → shared-T66YQ6MB.js.map} +0 -0
package/README.md
CHANGED
|
@@ -2510,6 +2510,8 @@ Re-ingesting the same link returns the existing row with `deduped: true` instead
|
|
|
2510
2510
|
| `--context` | What you know that the video cannot show — campaign, who is on camera, intended use. Feeds the analysis, exactly as on `upload`. |
|
|
2511
2511
|
| `--dry-run` | Preview the resolved route and parameters. |
|
|
2512
2512
|
|
|
2513
|
+
**The download is uncapped, and takes the best the site will release.** There is no height ceiling: Mux re-encodes every clip into its own renditions, so downscaling is already handled downstream and doing it *during* the download would throw away source pixels the one system that can use them never saw. A 1080p ceiling used to apply here on the reasoning that a 4K master is bytes we re-encode anyway — true, but it made the master permanently 1080p for everything the library is ever asked to do with that clip afterwards. Downscaling is cheap; re-acquiring a master is not. The remaining budgets are duration (3h, refused from metadata before a byte is fetched), size (16 GB), and the download window.
|
|
2514
|
+
|
|
2513
2515
|
Baker fetches directly first and only pays for a proxied connection when the site refuses it. `--country` pins those paid connections to a specific place — it does not change the first, free attempt. The result names both the exit used (`egress`) and the country, so a geo-targeted fetch is never invisible after the fact. A region failure says so and suggests the flag; other failures don't, because a different country would not fix them.
|
|
2514
2516
|
|
|
2515
2517
|
### Vimeo needs a signed-in session
|
|
@@ -2520,12 +2522,14 @@ Use an account created for this and holding nothing else — the value travels i
|
|
|
2520
2522
|
|
|
2521
2523
|
An audio-only link (a music or podcast page) is refused up front — there is no picture to store in a video library. A download is also given a time budget scaled to the video's length, capped at 15 minutes, because the turn is blocked while it runs; a video that outruns it says so and points at `upload`.
|
|
2522
2524
|
|
|
2523
|
-
The download route caps the pull at 1080p — Baker re-encodes for streaming anyway, so fetching a 4K master (what modern YouTube serves by default) only makes the download slower for pixels that get discarded.
|
|
2524
|
-
|
|
2525
2525
|
**Blocked downloads climb the egress ladder automatically.** The download route goes through the same **direct → datacenter → residential** ladder as every other outbound read (`@baker/proxy`; see [Operations](../../docs/operations.md) → Egress Proxy). There is no proxy flag on any command and nothing to opt into — the unproxied attempt always runs first, so a paid exit costs nothing until a host actually refuses us, and with no `OXYLABS_*` credentials in the environment this is a single plain download.
|
|
2526
2526
|
|
|
2527
2527
|
A rung only opens on evidence that *who we are* was the problem — a 403/429/451, a WAF connection reset, or a bot wall like YouTube's "Sign in to confirm you're not a bot". A private video, a deleted one, a 404 or an unsupported URL fails identically from every address on earth, so it stops after one attempt instead of burning a timeout per tier. That decision is `shouldEscalate`'s, shared with the capture engine and the ad-media downloaders; yt-dlp's stderr is only *parsed* into the signal it takes (`src/lib/ytDlpSignal.ts`), never allowed to judge for itself.
|
|
2528
2528
|
|
|
2529
|
+
**A YouTube refusal that no exit IP can fix gets a different player, not a different address.** yt-dlp's default client selection currently lands on `android_vr`, whose media URLs YouTube signs and then rejects: extraction succeeds, a format is chosen, and the byte fetch returns `unable to download video data: HTTP Error 403: Forbidden`. Measured from a Runtime, that failure is identical on direct, datacenter *and* residential — so the ladder spends both paid rungs reproducing it and the video never arrives. Only once the ladder has been exhausted on that exact phrase does the download retry with `--extractor-args youtube:player_client=android` (`src/lib/ytDlpPlayerClient.ts`), which resolves a progressive format the same address is allowed to fetch. **That retry repeats the rung it was refused on and opens no new one** — it is a different player, not a different address, and walking the ladder a second time would re-climb through both paid tiers on a 403, which is the spend this exists to stop. A fallback rather than the default because it currently offers only 360p: worth reaching for after the good formats have been refused, worth nothing before that. The page-level bot wall ("Sign in to confirm you're not a bot") is deliberately *not* matched here — a different IP does fix that one, and it belongs to the ladder.
|
|
2530
|
+
|
|
2531
|
+
The retry is **automatic and unasked-for; its cost is not**. There is no flag and nothing to opt into — but a download that only completed this way comes back with `reducedQuality: true` and a hint saying the clip is standard quality, for the same reason `egress` names the rung: a price the caller did not choose has to be reported, and a 360p clip is otherwise indistinguishable from a 1080p one until someone watches it. The canvas `ingest` node shares the same downloader and reports it the same way, as `reduced_quality: true` on the asset's metadata plus a line in the run log.
|
|
2532
|
+
|
|
2529
2533
|
Requires `yt-dlp` on `PATH` (present in the Baker Runtime). Private, age-restricted, or region-locked videos cannot be downloaded — the error carries a `fix` pointing at `baker videos upload <file>`.
|
|
2530
2534
|
|
|
2531
2535
|
**yt-dlp goes stale, and that looks like a broken video.** Large platforms change their players every few weeks and an out-of-date `yt-dlp` then resolves *no* formats at all, failing with "Requested format is not available" or "Only images are available" rather than anything that names the real cause. The error classifies this case separately and says the link is probably fine. The Runtime image installs `yt-dlp` unpinned at build time (`packages/e2b-template/src/template.ts`), so it ages with the image — if platform ingests start failing across the board, rebuild the template before investigating anything else. Direct file URLs don't depend on `yt-dlp` at all and keep working regardless.
|
|
@@ -2774,6 +2778,10 @@ baker scheduled-actions update <id-or-temp_sched_id> --run-at "2026-09-02T07:00:
|
|
|
2774
2778
|
baker scheduled-actions delete <id-or-temp_sched_id>
|
|
2775
2779
|
|
|
2776
2780
|
baker scheduled-actions trigger <id>
|
|
2781
|
+
|
|
2782
|
+
baker scheduled-actions templates --list # every recipe this company can run
|
|
2783
|
+
baker scheduled-actions templates --category measurement # one group only
|
|
2784
|
+
baker scheduled-actions create --template baker-ads --name "Weekly ad review" --description "..." --cron "0 8 * * MON"
|
|
2777
2785
|
```
|
|
2778
2786
|
|
|
2779
2787
|
Rules:
|
|
@@ -2787,6 +2795,34 @@ Rules:
|
|
|
2787
2795
|
- Scheduled actions spawn agents by default; create with `--no-spawn-agent` or update with `--spawn-agent false` to disable it.
|
|
2788
2796
|
- `--prompt` maps to the scheduled action's additional spawned-agent instructions (`agentPrompt`), not a replacement for Baker's automatic spawned Work Action reference.
|
|
2789
2797
|
- `--prompt` requires an agent: it is rejected alongside `--no-spawn-agent` (create) or `--spawn-agent false` (update), since a bypassed agent never reads it.
|
|
2798
|
+
- `--template <id>` binds the schedule to a marketplace recipe instead of a prompt you wrote. The row stores the id alone: name, brief and prompt resolve at fire time, so the job improves when the recipe does. `--description` carries what is true of this company. One row per recipe per company; a second `create` for the same id is refused.
|
|
2799
|
+
|
|
2800
|
+
#### Marketplace recipes (`templates`)
|
|
2801
|
+
|
|
2802
|
+
`templates` lists every recipe a company can switch on — the ones Baker maintains plus any the company wrote — and is also how one of theirs is written. Recipes we maintain take priority: a company recipe can never use one of our ids, and resolution reads ours first.
|
|
2803
|
+
|
|
2804
|
+
```bash
|
|
2805
|
+
baker scheduled-actions templates --list --drafts # include theirs not offered yet
|
|
2806
|
+
|
|
2807
|
+
# Writing one of theirs, in this order:
|
|
2808
|
+
baker scheduled-actions templates --save weekly-posthog-check \
|
|
2809
|
+
--name "Weekly PostHog check" \
|
|
2810
|
+
--tagline "What moved in the funnel, from PostHog rather than GA4." \
|
|
2811
|
+
--recipe-category measurement --frequency weekly \
|
|
2812
|
+
--brief-file ./brief.md
|
|
2813
|
+
|
|
2814
|
+
# ...schedule it with --template, trigger it, read what the run produced, then:
|
|
2815
|
+
baker scheduled-actions templates --publish weekly-posthog-check
|
|
2816
|
+
baker scheduled-actions templates --delete weekly-posthog-check
|
|
2817
|
+
```
|
|
2818
|
+
|
|
2819
|
+
- **Saving does not offer it.** A saved recipe is invisible and cannot be scheduled until `--publish`. The step between the two is running it: nothing enforces that, and it is the only way to know it produces anything worth reading.
|
|
2820
|
+
- **`--publish` refuses what it can check**: a brief too short to run unattended, a cadence or category that does not exist, an id that shadows one of Baker's, and a brief naming no source this company has connected. The problems come back as text addressed to the agent.
|
|
2821
|
+
- **Only company-wide and organization-wide connections count.** A run fires unattended, so a tool one person connected for themselves works in the chat where the recipe was written and returns nothing every run after that.
|
|
2822
|
+
- **Prefer `--brief-file`** over `--brief`: shell quoting eats apostrophes and newlines, and the brief is the whole recipe.
|
|
2823
|
+
- **Publishing stages**, like every other Session effect. The recipe reaches the marketplace when the chat is published and is listed there as a change; discarding the chat leaves the marketplace as it was. `BAKER_CHAT_ID` is required for `--save`, `--publish` and `--delete`.
|
|
2824
|
+
- **A company's own starts on Recommends** and offers every cadence. The company changes that from its Marketplace tab.
|
|
2825
|
+
- **`--delete` stops any schedule still pointing at it** — the response says how many.
|
|
2790
2826
|
|
|
2791
2827
|
---
|
|
2792
2828
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
debugLogSetting
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DZUVUGEP.js";
|
|
4
4
|
|
|
5
5
|
// src/debugLog.ts
|
|
6
6
|
import { appendFileSync, mkdirSync, renameSync, statSync } from "fs";
|
|
@@ -150,4 +150,4 @@ export {
|
|
|
150
150
|
readBodyForLog,
|
|
151
151
|
installStreamTaps
|
|
152
152
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-2IB3IL4K.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
debugLogHttp,
|
|
3
3
|
readBodyForLog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2IB3IL4K.js";
|
|
5
5
|
import {
|
|
6
6
|
getEnv
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DZUVUGEP.js";
|
|
8
8
|
|
|
9
9
|
// src/client.ts
|
|
10
10
|
var MAX_RATE_LIMIT_RETRIES = 3;
|
|
@@ -198,4 +198,4 @@ export {
|
|
|
198
198
|
apiGet,
|
|
199
199
|
apiPost
|
|
200
200
|
};
|
|
201
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-3FBQKD7O.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ApiError,
|
|
3
3
|
apiGet
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3FBQKD7O.js";
|
|
5
5
|
import {
|
|
6
6
|
getEnv
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DZUVUGEP.js";
|
|
8
8
|
|
|
9
9
|
// src/error-handler.ts
|
|
10
10
|
var REQUEST_CONNECTION_PLATFORM = {
|
|
@@ -295,4 +295,4 @@ export {
|
|
|
295
295
|
writeAdsOutput,
|
|
296
296
|
resolveCustomerId
|
|
297
297
|
};
|
|
298
|
-
//# sourceMappingURL=chunk-
|
|
298
|
+
//# sourceMappingURL=chunk-5I66YT7A.js.map
|
|
@@ -334,6 +334,7 @@ export {
|
|
|
334
334
|
shouldEscalate,
|
|
335
335
|
isPrivateAddress,
|
|
336
336
|
refuseNonPublicUrl,
|
|
337
|
+
DIRECT_ROUTE,
|
|
337
338
|
plannedRoutes,
|
|
338
339
|
getEnv,
|
|
339
340
|
debugLogSetting,
|
|
@@ -344,4 +345,4 @@ export {
|
|
|
344
345
|
captureVimeoCookie,
|
|
345
346
|
childEnvWith
|
|
346
347
|
};
|
|
347
|
-
//# sourceMappingURL=chunk-
|
|
348
|
+
//# sourceMappingURL=chunk-DZUVUGEP.js.map
|
|
@@ -2,13 +2,13 @@ import {
|
|
|
2
2
|
handleConnectionError,
|
|
3
3
|
needsConnectionFix,
|
|
4
4
|
writeAdsJson
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5I66YT7A.js";
|
|
6
6
|
import {
|
|
7
7
|
ApiError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3FBQKD7O.js";
|
|
9
9
|
import {
|
|
10
10
|
getEnv
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DZUVUGEP.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/ads/meta/shared.ts
|
|
14
14
|
var DAY_MS = 864e5;
|
|
@@ -108,4 +108,4 @@ export {
|
|
|
108
108
|
csvOrJson,
|
|
109
109
|
resolveEffectiveStatus
|
|
110
110
|
};
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-P6ZNIFAQ.js.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
debugLogHttp,
|
|
3
3
|
readBodyForLog
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2IB3IL4K.js";
|
|
5
5
|
import {
|
|
6
|
+
DIRECT_ROUTE,
|
|
6
7
|
__commonJS,
|
|
7
8
|
__toESM,
|
|
8
9
|
captureProxyCredentials,
|
|
@@ -13,11 +14,11 @@ import {
|
|
|
13
14
|
plannedRoutes,
|
|
14
15
|
refuseNonPublicUrl,
|
|
15
16
|
shouldEscalate
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-DZUVUGEP.js";
|
|
17
18
|
|
|
18
|
-
//
|
|
19
|
+
// ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
|
|
19
20
|
var require_safe_stable_stringify = __commonJS({
|
|
20
|
-
"
|
|
21
|
+
"../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js"(exports, module) {
|
|
21
22
|
"use strict";
|
|
22
23
|
var { hasOwnProperty } = Object.prototype;
|
|
23
24
|
var stringify = configure2();
|
|
@@ -1091,7 +1092,7 @@ function resolveAdaptFormats(params) {
|
|
|
1091
1092
|
return params.formats ?? [];
|
|
1092
1093
|
}
|
|
1093
1094
|
|
|
1094
|
-
//
|
|
1095
|
+
// ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/esm/wrapper.js
|
|
1095
1096
|
var import__ = __toESM(require_safe_stable_stringify(), 1);
|
|
1096
1097
|
var configure = import__.default.configure;
|
|
1097
1098
|
var wrapper_default = import__.default;
|
|
@@ -5260,6 +5261,23 @@ function isVimeoAuthFailure(detail) {
|
|
|
5260
5261
|
return VIMEO_AUTH_SIGNATURES.some((signature) => haystack.includes(signature));
|
|
5261
5262
|
}
|
|
5262
5263
|
|
|
5264
|
+
// src/lib/ytDlpPlayerClient.ts
|
|
5265
|
+
var YOUTUBE_FALLBACK_CLIENT_ARGS = ["--extractor-args", "youtube:player_client=android"];
|
|
5266
|
+
var MEDIA_FETCH_REFUSED = "unable to download video data";
|
|
5267
|
+
var YOUTUBE_HOSTS = ["youtube.com", "youtu.be"];
|
|
5268
|
+
function isYouTube(url) {
|
|
5269
|
+
let host;
|
|
5270
|
+
try {
|
|
5271
|
+
host = new URL(url).hostname.toLowerCase();
|
|
5272
|
+
} catch {
|
|
5273
|
+
return false;
|
|
5274
|
+
}
|
|
5275
|
+
return YOUTUBE_HOSTS.some((known) => host === known || host.endsWith(`.${known}`));
|
|
5276
|
+
}
|
|
5277
|
+
function needsPlayerClientRetry(url, stderr) {
|
|
5278
|
+
return isYouTube(url) && stderr.toLowerCase().includes(MEDIA_FETCH_REFUSED);
|
|
5279
|
+
}
|
|
5280
|
+
|
|
5263
5281
|
// src/lib/ytDlpSignal.ts
|
|
5264
5282
|
var HTTP_ERROR = /HTTP Error (\d{3})/i;
|
|
5265
5283
|
var CHALLENGE_PHRASES = [
|
|
@@ -5312,18 +5330,18 @@ async function runYtDlp(args) {
|
|
|
5312
5330
|
if (args.audioOnly) {
|
|
5313
5331
|
argv.push("-x", "--audio-format", "m4a");
|
|
5314
5332
|
} else {
|
|
5315
|
-
|
|
5316
|
-
argv.push("--format", format, "--merge-output-format", "mp4");
|
|
5333
|
+
argv.push("--format", "bv*+ba/b", "--merge-output-format", "mp4");
|
|
5317
5334
|
}
|
|
5318
5335
|
const cookieFile = await writeVimeoCookieFile(args.vimeoCookie, args.workDir);
|
|
5319
5336
|
if (cookieFile) argv.push("--cookies", cookieFile);
|
|
5320
5337
|
args.onLog?.(`yt-dlp: downloading ${args.audioOnly ? "audio" : "video"}`);
|
|
5321
|
-
const
|
|
5338
|
+
const timeoutMs = args.timeoutMs ?? YT_DLP_TIMEOUT_MS;
|
|
5339
|
+
const { code, stderr, tier, reducedQuality } = await downloadWithClientFallback({
|
|
5322
5340
|
url: args.url,
|
|
5323
5341
|
argv,
|
|
5324
|
-
timeoutMs: args.timeoutMs ?? YT_DLP_TIMEOUT_MS,
|
|
5325
5342
|
onLog: args.onLog,
|
|
5326
|
-
country: args.country
|
|
5343
|
+
ladder: (attemptArgv) => runViaLadder({ url: args.url, argv: attemptArgv, timeoutMs, onLog: args.onLog, country: args.country }),
|
|
5344
|
+
repeat: (attemptArgv, route) => spawnAndWait(YT_DLP_BIN, attemptArgv, timeoutMs, { extraEnv: proxyEnvFor(route) })
|
|
5327
5345
|
});
|
|
5328
5346
|
if (code !== 0) {
|
|
5329
5347
|
throw new YtDlpError(`yt-dlp exited ${code}`, tail(stderr, 40));
|
|
@@ -5339,7 +5357,7 @@ async function runYtDlp(args) {
|
|
|
5339
5357
|
info = JSON.parse(await readFile3(infoPath, "utf-8"));
|
|
5340
5358
|
} catch {
|
|
5341
5359
|
}
|
|
5342
|
-
return { filePath: path5.join(args.workDir, downloaded), info, tier };
|
|
5360
|
+
return { filePath: path5.join(args.workDir, downloaded), info, tier, reducedQuality };
|
|
5343
5361
|
}
|
|
5344
5362
|
async function probeYtDlp(args) {
|
|
5345
5363
|
const argv = [
|
|
@@ -5402,16 +5420,25 @@ function canonicalUrl(info) {
|
|
|
5402
5420
|
}
|
|
5403
5421
|
async function walkYtDlpLadder(args) {
|
|
5404
5422
|
const routes = plannedRoutes(args.url, args.credentials, args.country ? { country: args.country } : void 0);
|
|
5405
|
-
let last = { code: -1, stderr: "", tier: "direct" };
|
|
5423
|
+
let last = { code: -1, stderr: "", tier: "direct", route: DIRECT_ROUTE };
|
|
5406
5424
|
for (const route of routes) {
|
|
5407
5425
|
const tier = route.kind === "proxy" ? route.tier : "direct";
|
|
5408
5426
|
if (route.kind === "proxy") args.onLog?.(`yt-dlp: retrying via ${tier}`);
|
|
5409
|
-
last = { ...await args.attempt(route), tier };
|
|
5427
|
+
last = { ...await args.attempt(route), tier, route };
|
|
5410
5428
|
if (last.code === 0) return last;
|
|
5411
5429
|
if (!shouldEscalate(ytDlpBlockSignal(last.stderr))) return last;
|
|
5412
5430
|
}
|
|
5413
5431
|
return last;
|
|
5414
5432
|
}
|
|
5433
|
+
async function downloadWithClientFallback(args) {
|
|
5434
|
+
const first = await args.ladder(args.argv);
|
|
5435
|
+
if (first.code === 0 || !needsPlayerClientRetry(args.url, first.stderr)) {
|
|
5436
|
+
return { ...first, reducedQuality: false };
|
|
5437
|
+
}
|
|
5438
|
+
args.onLog?.("yt-dlp: retrying with the fallback player client");
|
|
5439
|
+
const again = await args.repeat([...args.argv, ...YOUTUBE_FALLBACK_CLIENT_ARGS], first.route);
|
|
5440
|
+
return { ...again, tier: first.tier, route: first.route, reducedQuality: again.code === 0 };
|
|
5441
|
+
}
|
|
5415
5442
|
function runViaLadder(args) {
|
|
5416
5443
|
return walkYtDlpLadder({
|
|
5417
5444
|
url: args.url,
|
|
@@ -6103,7 +6130,7 @@ async function execYtDlp(params, ctx) {
|
|
|
6103
6130
|
}
|
|
6104
6131
|
const workDir = await mkdtemp(path6.join(tmpdir(), "ingest-yt-"));
|
|
6105
6132
|
try {
|
|
6106
|
-
const { filePath, info } = await runYtDlpForNode({
|
|
6133
|
+
const { filePath, info, reducedQuality } = await runYtDlpForNode({
|
|
6107
6134
|
url: params.url,
|
|
6108
6135
|
audioOnly: params.expect === "audio",
|
|
6109
6136
|
workDir,
|
|
@@ -6120,6 +6147,10 @@ async function execYtDlp(params, ctx) {
|
|
|
6120
6147
|
const kind = params.expect;
|
|
6121
6148
|
const mime = YT_DLP_MIME[kind];
|
|
6122
6149
|
const metadata = buildYtDlpMetadata(params.url, info);
|
|
6150
|
+
if (reducedQuality) {
|
|
6151
|
+
metadata.reduced_quality = true;
|
|
6152
|
+
ctx.log(`ingest: ${params.url} was only available at reduced resolution`);
|
|
6153
|
+
}
|
|
6123
6154
|
return await uploadAndIngest({ bytes, kind, mime, metadata, ctx });
|
|
6124
6155
|
} finally {
|
|
6125
6156
|
await rm(workDir, { recursive: true, force: true }).catch((e) => {
|
|
@@ -8924,4 +8955,4 @@ export {
|
|
|
8924
8955
|
defaultRegistry,
|
|
8925
8956
|
createEngineFromEnv
|
|
8926
8957
|
};
|
|
8927
|
-
//# sourceMappingURL=chunk-
|
|
8958
|
+
//# sourceMappingURL=chunk-XGIJGOKR.js.map
|