@echovisionlab/youtube-audio 0.1.3 → 0.1.5
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 +13 -0
- package/dist/youtube-js.d.ts +2 -0
- package/dist/youtube-js.d.ts.map +1 -1
- package/dist/youtube-js.js +91 -21
- package/dist/youtube-js.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -34,6 +34,18 @@ copying. See [DISCLOSURE.md](DISCLOSURE.md).
|
|
|
34
34
|
YouTube and its private APIs can change independently. Keep failures observable
|
|
35
35
|
and review YouTube's terms and applicable law for your integration.
|
|
36
36
|
|
|
37
|
+
`createYoutubeJsAudioProvider()` is exported separately so browser bundles do
|
|
38
|
+
not accidentally pull the unofficial InnerTube client into application code.
|
|
39
|
+
It rejects live/upcoming video and any source without a finite audio-only byte
|
|
40
|
+
length. The adapter tries the `VISIONOS` and `YTKIDS` YouTube.js clients in
|
|
41
|
+
order, accepting a source only after exact one-byte reads succeed at the
|
|
42
|
+
beginning, middle, and end of the file. This keeps source preparation bounded
|
|
43
|
+
for long public videos while rejecting URLs that resolve but later fail random
|
|
44
|
+
access. Callers may override `client` when required. YouTube.js and the upstream
|
|
45
|
+
private API can change independently; keep
|
|
46
|
+
resolution failures observable and update this package rather than adding
|
|
47
|
+
fallback scraping to the web application.
|
|
48
|
+
|
|
37
49
|
## Development
|
|
38
50
|
|
|
39
51
|
```sh
|
|
@@ -44,6 +56,7 @@ pnpm test:coverage
|
|
|
44
56
|
pnpm build
|
|
45
57
|
pnpm package:verify
|
|
46
58
|
pnpm package:pack
|
|
59
|
+
YOUTUBE_VIDEO_ID=<authorized-video-id> pnpm smoke:youtube-range
|
|
47
60
|
```
|
|
48
61
|
|
|
49
62
|
## Release
|
package/dist/youtube-js.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface CreateYoutubeJsAudioProviderOptions {
|
|
|
7
7
|
readonly innertubeConfig?: Types.InnerTubeConfig;
|
|
8
8
|
/** Optional YouTube client override. */
|
|
9
9
|
readonly client?: Types.InnerTubeClient;
|
|
10
|
+
/** Test seam for validating random-access media reads. */
|
|
11
|
+
readonly fetcher?: typeof fetch;
|
|
10
12
|
/** Optional container preference such as `m4a` or `webm`. */
|
|
11
13
|
readonly format?: string;
|
|
12
14
|
}
|
package/dist/youtube-js.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-js.d.ts","sourceRoot":"","sources":["../src/youtube-js.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"youtube-js.d.ts","sourceRoot":"","sources":["../src/youtube-js.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAY,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EACV,oBAAoB,EAGrB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,mCAAmC;IAClD,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC;IACjD,wCAAwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC;IACxC,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IAChC,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,wBAAgB,4BAA4B,CAC1C,OAAO,GAAE,mCAAwC,GAChD,oBAAoB,CAwEtB"}
|
package/dist/youtube-js.js
CHANGED
|
@@ -1,40 +1,110 @@
|
|
|
1
|
-
import { Innertube } from 'youtubei.js';
|
|
1
|
+
import { Innertube, Platform } from 'youtubei.js';
|
|
2
2
|
import { YoutubeAudioError } from './errors.js';
|
|
3
|
+
const DEFAULT_CLIENT_TYPES = [
|
|
4
|
+
'VISIONOS',
|
|
5
|
+
'YTKIDS',
|
|
6
|
+
];
|
|
3
7
|
export function createYoutubeJsAudioProvider(options = {}) {
|
|
4
8
|
let clientPromise;
|
|
5
|
-
const
|
|
9
|
+
const clientTypes = options.client === undefined
|
|
10
|
+
? DEFAULT_CLIENT_TYPES
|
|
11
|
+
: [options.client];
|
|
12
|
+
const fetcher = options.fetcher ?? fetch;
|
|
6
13
|
return {
|
|
7
14
|
async resolve(video, signal) {
|
|
8
15
|
throwIfAborted(signal);
|
|
9
|
-
|
|
10
|
-
throwIfAborted(signal);
|
|
16
|
+
let innertube;
|
|
11
17
|
try {
|
|
12
|
-
|
|
13
|
-
throwIfAborted(signal);
|
|
14
|
-
if (info.basic_info.is_live || info.basic_info.is_upcoming) {
|
|
15
|
-
throw new YoutubeAudioError('UNSUPPORTED_VIDEO', 'Live and upcoming YouTube videos are not supported.');
|
|
16
|
-
}
|
|
17
|
-
const format = info.chooseFormat({
|
|
18
|
-
...videoInfoOptions(clientType),
|
|
19
|
-
format: options.format ?? 'any',
|
|
20
|
-
quality: 'best',
|
|
21
|
-
type: 'audio',
|
|
22
|
-
});
|
|
23
|
-
format.url = await format.decipher(innertube.session.player);
|
|
24
|
-
throwIfAborted(signal);
|
|
25
|
-
return toUpstreamSource(video, info.basic_info.title, format);
|
|
18
|
+
innertube = await getInnertube();
|
|
26
19
|
}
|
|
27
20
|
catch (error) {
|
|
28
21
|
rethrowYoutubeJsError(error, signal);
|
|
29
22
|
}
|
|
23
|
+
throwIfAborted(signal);
|
|
24
|
+
let lastError;
|
|
25
|
+
for (const clientType of clientTypes) {
|
|
26
|
+
try {
|
|
27
|
+
return await resolveWithClient(innertube, video, clientType, signal);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throwIfAborted(signal);
|
|
31
|
+
lastError = error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
rethrowYoutubeJsError(lastError, signal);
|
|
30
35
|
},
|
|
31
36
|
};
|
|
32
37
|
function getInnertube() {
|
|
33
|
-
clientPromise
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
if (clientPromise === undefined) {
|
|
39
|
+
const creating = options.innertube === undefined
|
|
40
|
+
? Innertube.create(options.innertubeConfig)
|
|
41
|
+
: Promise.resolve(options.innertube);
|
|
42
|
+
clientPromise = creating.catch((error) => {
|
|
43
|
+
// A transient initialization failure must not poison this provider for
|
|
44
|
+
// every later request or retain the rejected promise indefinitely.
|
|
45
|
+
clientPromise = undefined;
|
|
46
|
+
throw error;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
36
49
|
return clientPromise;
|
|
37
50
|
}
|
|
51
|
+
async function resolveWithClient(innertube, video, clientType, signal) {
|
|
52
|
+
const infoOptions = videoInfoOptions(clientType);
|
|
53
|
+
const info = await innertube.getBasicInfo(video.videoId, infoOptions);
|
|
54
|
+
throwIfAborted(signal);
|
|
55
|
+
if (info.basic_info.is_live || info.basic_info.is_upcoming) {
|
|
56
|
+
throw new YoutubeAudioError('UNSUPPORTED_VIDEO', 'Live and upcoming YouTube videos are not supported.');
|
|
57
|
+
}
|
|
58
|
+
const format = info.chooseFormat({
|
|
59
|
+
...infoOptions,
|
|
60
|
+
format: options.format ?? 'any',
|
|
61
|
+
quality: 'best',
|
|
62
|
+
type: 'audio',
|
|
63
|
+
});
|
|
64
|
+
format.url = await decipherFormat(format, innertube);
|
|
65
|
+
throwIfAborted(signal);
|
|
66
|
+
const source = toUpstreamSource(video, info.basic_info.title, format);
|
|
67
|
+
await validateRandomAccessSource(source, fetcher, signal);
|
|
68
|
+
return source;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function decipherFormat(format, innertube) {
|
|
72
|
+
try {
|
|
73
|
+
return await format.decipher(innertube.session.player);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (!isMissingJavascriptEvaluator(error)) {
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
Platform.shim.eval = async (data) => new Function(data.output)();
|
|
80
|
+
return format.decipher(innertube.session.player);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function validateRandomAccessSource(source, fetcher, signal) {
|
|
84
|
+
const positions = new Set([
|
|
85
|
+
0,
|
|
86
|
+
Math.floor((source.size - 1) / 2),
|
|
87
|
+
source.size - 1,
|
|
88
|
+
]);
|
|
89
|
+
for (const position of positions) {
|
|
90
|
+
throwIfAborted(signal);
|
|
91
|
+
const response = await fetcher(source.url, {
|
|
92
|
+
headers: { Range: `bytes=${position}-${position}` },
|
|
93
|
+
...(signal === undefined ? {} : { signal }),
|
|
94
|
+
});
|
|
95
|
+
const expectedRange = `bytes ${position}-${position}/${source.size}`;
|
|
96
|
+
const valid = response.status === 206 &&
|
|
97
|
+
response.headers.get('content-range') === expectedRange;
|
|
98
|
+
// The probe needs headers only; cancelling promptly avoids retaining an
|
|
99
|
+
// upstream response stream when clients return more than the requested byte.
|
|
100
|
+
await response.body?.cancel().catch(() => undefined);
|
|
101
|
+
if (!valid) {
|
|
102
|
+
throw new YoutubeAudioError('UPSTREAM_FAILURE', 'YouTube did not provide a stable random-access audio source.');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function isMissingJavascriptEvaluator(error) {
|
|
107
|
+
return error instanceof Error && error.message.includes('provide your own JavaScript evaluator');
|
|
38
108
|
}
|
|
39
109
|
function toUpstreamSource(video, title, format) {
|
|
40
110
|
if (typeof title !== 'string' ||
|
package/dist/youtube-js.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-js.js","sourceRoot":"","sources":["../src/youtube-js.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAc,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"youtube-js.js","sourceRoot":"","sources":["../src/youtube-js.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@echovisionlab/youtube-audio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Authenticated server-side YouTube audio resolution and byte-range proxying.",
|
|
5
5
|
"author": "state303 <state303@dsub.io>",
|
|
6
6
|
"keywords": [
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"build:clean": "node ./scripts/clean-dist.mjs",
|
|
41
41
|
"package:verify": "node ./scripts/verify-package.mjs",
|
|
42
42
|
"package:pack": "npm pack --dry-run",
|
|
43
|
+
"smoke:youtube-range": "node ./scripts/smoke-youtube-range.mjs",
|
|
43
44
|
"test": "vitest run",
|
|
44
45
|
"test:coverage": "vitest run --coverage",
|
|
45
46
|
"typecheck": "tsc --noEmit"
|