diff --git a/examples/downloader/package-lock.json b/examples/downloader/package-lock.json index dccc633..ba35829 100644 --- a/examples/downloader/package-lock.json +++ b/examples/downloader/package-lock.json @@ -15,7 +15,7 @@ "googlevideo": "file:../..", "jsdom": "^25.0.1", "shaka-player": "^4.11.2", - "youtubei.js": "^15.0.0" + "youtubei.js": "^16.0.0" }, "devDependencies": { "@types/cli-progress": "^3.11.6", @@ -25,7 +25,7 @@ } }, "../..": { - "version": "4.0.1", + "version": "4.0.4", "funding": [ "https://github.com/sponsors/LuanRT" ], @@ -99,18 +99,6 @@ "dev": true, "license": "MIT" }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -520,18 +508,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/jintr": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jintr/-/jintr-3.3.1.tgz", - "integrity": "sha512-nnOzyhf0SLpbWuZ270Omwbj5LcXUkTcZkVnK8/veJXtSZOiATM5gMZMdmzN75FmTyj+NVgrGaPdH12zIJ24oIA==", - "funding": [ - "https://github.com/sponsors/LuanRT" - ], - "license": "MIT", - "dependencies": { - "acorn": "^8.8.0" - } - }, "node_modules/jsdom": { "version": "25.0.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", @@ -581,6 +557,15 @@ "node": ">= 0.4" } }, + "node_modules/meriyah": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-6.1.4.tgz", + "integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==", + "license": "ISC", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -742,11 +727,6 @@ "node": ">=18" } }, - "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -760,15 +740,6 @@ "node": ">=14.17" } }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -878,18 +849,16 @@ "license": "MIT" }, "node_modules/youtubei.js": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-15.0.0.tgz", - "integrity": "sha512-giPZREn+q0z8Jr45NUcJUXE7QA2+UD2jx5FR+ULdnexvtHg5uQZr9Am8aYcECPKzbBNe6ksBD1yT4SKNbhpRqA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-16.0.0.tgz", + "integrity": "sha512-aMx+ulnrxzsgVsxTr7gbBVnIjti2NQUlMwCoo1/MzICCJS3iMLOPUFdo7bSpwskL6ljzQ/LxmmB4WQC3FtkBlA==", "funding": [ "https://github.com/sponsors/LuanRT" ], "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", - "jintr": "^3.3.1", - "tslib": "^2.5.0", - "undici": "^6.21.3" + "meriyah": "^6.1.4" } } } diff --git a/examples/downloader/package.json b/examples/downloader/package.json index 78e2244..55c49db 100644 --- a/examples/downloader/package.json +++ b/examples/downloader/package.json @@ -18,7 +18,7 @@ "googlevideo": "file:../..", "jsdom": "^25.0.1", "shaka-player": "^4.11.2", - "youtubei.js": "^15.0.0" + "youtubei.js": "^16.0.0" }, "devDependencies": { "@types/cli-progress": "^3.11.6", diff --git a/examples/downloader/utils/sabr-stream-factory.ts b/examples/downloader/utils/sabr-stream-factory.ts index 7bc0636..6254c41 100644 --- a/examples/downloader/utils/sabr-stream-factory.ts +++ b/examples/downloader/utils/sabr-stream-factory.ts @@ -1,6 +1,7 @@ import { createWriteStream, type WriteStream } from 'node:fs'; import cliProgress from 'cli-progress'; -import { Constants, Innertube, type IPlayerResponse, UniversalCache, YTNodes } from 'youtubei.js'; +import { Constants, Innertube, type IPlayerResponse, Platform, UniversalCache, YTNodes } from 'youtubei.js'; +import type { Types } from 'youtubei.js'; import { generateWebPoToken } from './webpo-helper.js'; import type { SabrFormat } from 'googlevideo/shared-types'; @@ -23,6 +24,22 @@ export interface StreamResults { videoTitle: string; } +Platform.shim.eval = async (data: Types.BuildScriptResult, env: Record) => { + const properties = []; + + if (env.n) { + properties.push(`n: exportedVars.nFunction("${env.n}")`); + } + + if (env.sig) { + properties.push(`sig: exportedVars.sigFunction("${env.sig}")`); + } + + const code = `${data.output}\nreturn { ${properties.join(', ')} }`; + + return new Function(code)(); +}; + /** * Fetches video details and streaming information from YouTube. */ @@ -36,7 +53,7 @@ export async function makePlayerRequest(innertube: Innertube, videoId: string, r vis: 0, splay: false, lactMilliseconds: '-1', - signatureTimestamp: innertube.session.player?.sts + signatureTimestamp: innertube.session.player?.signature_timestamp } }, contentCheckOk: true, @@ -150,7 +167,7 @@ export async function createSabrStream( streamResults: StreamResults; }> { const innertube = await Innertube.create({ cache: new UniversalCache(true) }); - const webPoTokenResult = await generateWebPoToken(innertube.session.context.client.visitorData || ''); + const webPoTokenResult = await generateWebPoToken(videoId); // Get video metadata. const playerResponse = await makePlayerRequest(innertube, videoId); @@ -165,7 +182,7 @@ export async function createSabrStream( `); // Now get the streaming information. - const serverAbrStreamingUrl = innertube.session.player?.decipher(playerResponse.streaming_data?.server_abr_streaming_url); + const serverAbrStreamingUrl = await innertube.session.player?.decipher(playerResponse.streaming_data?.server_abr_streaming_url); const videoPlaybackUstreamerConfig = playerResponse.player_config?.media_common_config.media_ustreamer_request_config?.video_playback_ustreamer_config; if (!videoPlaybackUstreamerConfig) throw new Error('ustreamerConfig not found'); @@ -188,7 +205,7 @@ export async function createSabrStream( serverAbrStream.on('reloadPlayerResponse', async (reloadPlaybackContext) => { const playerResponse = await makePlayerRequest(innertube, videoId, reloadPlaybackContext); - const serverAbrStreamingUrl = innertube.session.player?.decipher(playerResponse.streaming_data?.server_abr_streaming_url); + const serverAbrStreamingUrl = await innertube.session.player?.decipher(playerResponse.streaming_data?.server_abr_streaming_url); const videoPlaybackUstreamerConfig = playerResponse.player_config?.media_common_config.media_ustreamer_request_config?.video_playback_ustreamer_config; if (serverAbrStreamingUrl && videoPlaybackUstreamerConfig) { diff --git a/examples/downloader/utils/webpo-helper.ts b/examples/downloader/utils/webpo-helper.ts index 5bd9c2c..eabfb56 100644 --- a/examples/downloader/utils/webpo-helper.ts +++ b/examples/downloader/utils/webpo-helper.ts @@ -1,10 +1,10 @@ import { BG, type BgConfig } from 'bgutils-js'; import { JSDOM } from 'jsdom'; -export async function generateWebPoToken(visitorData: string) { +export async function generateWebPoToken(contentBinding: string) { const requestKey = 'O43z0dpjhgX20SCx4KAo'; - if (!visitorData) + if (!contentBinding) throw new Error('Could not get visitor data'); const dom = new JSDOM(); @@ -17,7 +17,7 @@ export async function generateWebPoToken(visitorData: string) { const bgConfig: BgConfig = { fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => fetch(input, init), globalObj: globalThis, - identifier: visitorData, + identifier: contentBinding, requestKey }; @@ -38,10 +38,10 @@ export async function generateWebPoToken(visitorData: string) { bgConfig }); - const placeholderPoToken = BG.PoToken.generatePlaceholder(visitorData); + const placeholderPoToken = BG.PoToken.generatePlaceholder(contentBinding); return { - visitorData, + visitorData: contentBinding, placeholderPoToken, poToken: poTokenResult.poToken, }; diff --git a/examples/onesie-request/main.ts b/examples/onesie-request/main.ts index c695ee6..01466fc 100644 --- a/examples/onesie-request/main.ts +++ b/examples/onesie-request/main.ts @@ -1,4 +1,5 @@ -import Innertube, { Constants, type Context, UniversalCache, YT } from 'youtubei.js'; +import type { Types } from 'youtubei.js'; +import Innertube, { Constants, type Context, Platform, UniversalCache, YT } from 'youtubei.js'; import { UmpReader, CompositeBuffer } from 'googlevideo/ump'; import { @@ -26,6 +27,22 @@ type ClientConfig = { type UmpPartHandler = (part: Part) => void; +Platform.shim.eval = async (data: Types.BuildScriptResult, env: Record) => { + const properties = []; + + if (env.n) { + properties.push(`n: exportedVars.nFunction("${env.n}")`); + } + + if (env.sig) { + properties.push(`sig: exportedVars.sigFunction("${env.sig}")`); + } + + const code = `${data.output}\nreturn { ${properties.join(', ')} }`; + + return new Function(code)(); +}; + const enableCompression = true; /** @@ -87,7 +104,7 @@ async function prepareOnesieRequest(args: OnesieRequestArgs) { vis: 0, splay: false, lactMilliseconds: '-1', - signatureTimestamp: innertube.session.player?.sts + signatureTimestamp: innertube.session.player?.signature_timestamp } }, videoId @@ -302,7 +319,7 @@ const innertube = await Innertube.create({ cache: new UniversalCache(true), retr const videoInfo = await getBasicInfo(innertube, 'JAs6WyK-Kr0'); console.log('Basic info:', videoInfo); console.log('Deciphered audio URL:'); -console.log(videoInfo.chooseFormat({ +console.log(await videoInfo.chooseFormat({ format: 'mp4', quality: 'best', type: 'audio' diff --git a/examples/onesie-request/package-lock.json b/examples/onesie-request/package-lock.json index 64ca3be..526ef06 100644 --- a/examples/onesie-request/package-lock.json +++ b/examples/onesie-request/package-lock.json @@ -10,11 +10,11 @@ "license": "ISC", "dependencies": { "googlevideo": "file:../..", - "youtubei.js": "^15.0.0" + "youtubei.js": "^16.0.0" } }, "../..": { - "version": "4.0.1", + "version": "4.0.4", "funding": [ "https://github.com/sponsors/LuanRT" ], @@ -42,61 +42,30 @@ "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.3.tgz", "integrity": "sha512-tFQoXHJdkEOSwj5tRIZSPNUuXK3RaR7T1nUrPgbYX1pUbvqqaaZAsfo+NXBPsz5rZMSKVFrgK1WL8Q/MSLvprg==" }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/googlevideo": { "resolved": "../..", "link": true }, - "node_modules/jintr": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jintr/-/jintr-3.3.1.tgz", - "integrity": "sha512-nnOzyhf0SLpbWuZ270Omwbj5LcXUkTcZkVnK8/veJXtSZOiATM5gMZMdmzN75FmTyj+NVgrGaPdH12zIJ24oIA==", - "funding": [ - "https://github.com/sponsors/LuanRT" - ], - "license": "MIT", - "dependencies": { - "acorn": "^8.8.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", - "license": "MIT", + "node_modules/meriyah": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-6.1.4.tgz", + "integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==", + "license": "ISC", "engines": { - "node": ">=18.17" + "node": ">=18.0.0" } }, "node_modules/youtubei.js": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-15.0.0.tgz", - "integrity": "sha512-giPZREn+q0z8Jr45NUcJUXE7QA2+UD2jx5FR+ULdnexvtHg5uQZr9Am8aYcECPKzbBNe6ksBD1yT4SKNbhpRqA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-16.0.0.tgz", + "integrity": "sha512-aMx+ulnrxzsgVsxTr7gbBVnIjti2NQUlMwCoo1/MzICCJS3iMLOPUFdo7bSpwskL6ljzQ/LxmmB4WQC3FtkBlA==", "funding": [ "https://github.com/sponsors/LuanRT" ], "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", - "jintr": "^3.3.1", - "tslib": "^2.5.0", - "undici": "^6.21.3" + "meriyah": "^6.1.4" } } } diff --git a/examples/onesie-request/package.json b/examples/onesie-request/package.json index cf53c97..51b3ecb 100644 --- a/examples/onesie-request/package.json +++ b/examples/onesie-request/package.json @@ -13,6 +13,6 @@ "license": "ISC", "dependencies": { "googlevideo": "file:../..", - "youtubei.js": "^15.0.0" + "youtubei.js": "^16.0.0" } } diff --git a/examples/sabr-shaka-example/package-lock.json b/examples/sabr-shaka-example/package-lock.json index c3176d0..6bd8ec7 100644 --- a/examples/sabr-shaka-example/package-lock.json +++ b/examples/sabr-shaka-example/package-lock.json @@ -12,7 +12,7 @@ "bgutils-js": "^3.2.0", "googlevideo": "^4.0.4", "shaka-player": "^4.16.2", - "youtubei.js": "^15.1.1" + "youtubei.js": "^16.0.0" }, "devDependencies": { "typescript": "^5.4.5", @@ -482,18 +482,6 @@ "dev": true, "license": "MIT" }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/bgutils-js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/bgutils-js/-/bgutils-js-3.2.0.tgz", @@ -575,16 +563,13 @@ "@bufbuild/protobuf": "^2.0.0" } }, - "node_modules/jintr": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jintr/-/jintr-3.3.1.tgz", - "integrity": "sha512-nnOzyhf0SLpbWuZ270Omwbj5LcXUkTcZkVnK8/veJXtSZOiATM5gMZMdmzN75FmTyj+NVgrGaPdH12zIJ24oIA==", - "funding": [ - "https://github.com/sponsors/LuanRT" - ], - "license": "MIT", - "dependencies": { - "acorn": "^8.8.0" + "node_modules/meriyah": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/meriyah/-/meriyah-6.1.4.tgz", + "integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==", + "license": "ISC", + "engines": { + "node": ">=18.0.0" } }, "node_modules/nanoid": { @@ -1031,15 +1016,6 @@ "node": ">=14.17" } }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, "node_modules/vite": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", @@ -1131,17 +1107,16 @@ } }, "node_modules/youtubei.js": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-15.1.1.tgz", - "integrity": "sha512-fuEDj9Ky6cAQg93BrRVCbr+GTYNZQAIFZrx/a3oDRuGc3Mf5bS0dQfoYwwgjtSV7sgAKQEEdGtzRdBzOc8g72Q==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-16.0.0.tgz", + "integrity": "sha512-aMx+ulnrxzsgVsxTr7gbBVnIjti2NQUlMwCoo1/MzICCJS3iMLOPUFdo7bSpwskL6ljzQ/LxmmB4WQC3FtkBlA==", "funding": [ "https://github.com/sponsors/LuanRT" ], "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", - "jintr": "^3.3.1", - "undici": "^6.21.3" + "meriyah": "^6.1.4" } } } diff --git a/examples/sabr-shaka-example/package.json b/examples/sabr-shaka-example/package.json index dd904e6..9b8e20c 100644 --- a/examples/sabr-shaka-example/package.json +++ b/examples/sabr-shaka-example/package.json @@ -12,7 +12,7 @@ "bgutils-js": "^3.2.0", "googlevideo": "^4.0.4", "shaka-player": "^4.16.2", - "youtubei.js": "^15.1.1" + "youtubei.js": "^16.0.0" }, "devDependencies": { "typescript": "^5.4.5", diff --git a/examples/sabr-shaka-example/src/main.ts b/examples/sabr-shaka-example/src/main.ts index 16d4113..48a22d5 100644 --- a/examples/sabr-shaka-example/src/main.ts +++ b/examples/sabr-shaka-example/src/main.ts @@ -1,5 +1,6 @@ import shaka from 'shaka-player/dist/shaka-player.ui.js'; -import { Innertube, UniversalCache, YT, Utils, Constants } from 'youtubei.js'; +import type { Types } from 'youtubei.js/web'; +import { Constants, Innertube, Platform, UniversalCache, Utils, YT } from 'youtubei.js/web'; import { SabrStreamingAdapter } from 'googlevideo/sabr-streaming-adapter'; import { buildSabrFormat } from 'googlevideo/utils'; import { ShakaPlayerAdapter } from './ShakaPlayerAdapter.js'; @@ -16,11 +17,27 @@ const statusElement = document.getElementById('status') as HTMLDivElement; let player: shaka.Player; let sabrAdapter: SabrStreamingAdapter; let innertube: Innertube; -let sessionPoTokenContentBinding: string | undefined; -let sessionPoTokenCreationLock = false; -let sessionPoToken: string | undefined; +let playbackWebPoTokenContentBinding: string | undefined; +let playbackWebPoTokenCreationLock = false; +let playbackWebPoToken: string | undefined; let coldStartToken: string | undefined; +Platform.shim.eval = async (data: Types.BuildScriptResult, env: Record) => { + const properties = []; + + if (env.n) { + properties.push(`n: exportedVars.nFunction("${env.n}")`); + } + + if (env.sig) { + properties.push(`sig: exportedVars.sigFunction("${env.sig}")`); + } + + const code = `${data.output}\nreturn { ${properties.join(', ')} }`; + + return new Function(code)(); +}; + async function main() { shaka.polyfill.installAll(); @@ -38,8 +55,6 @@ async function main() { botguardService.init().then(() => console.info('[Main]', 'BotGuard client initialized')); - sessionPoTokenContentBinding = innertube.session.context.client.visitorData; - console.log('[Main] Innertube initialized'); // Now init the player. @@ -77,8 +92,7 @@ async function main() { volumeContainer[0].addEventListener('mousewheel', (event) => { event.preventDefault(); const delta = Math.sign((event as any).deltaY); - const newVolume = Math.max(0, Math.min(1, videoElement.volume - delta * 0.05)); - videoElement.volume = newVolume; + videoElement.volume = Math.max(0, Math.min(1, videoElement.volume - delta * 0.05)); }); console.log('[Main] Shaka Player initialized'); @@ -94,6 +108,9 @@ async function loadVideo(videoId: string) { alert('Please enter a video ID.'); return; } + + playbackWebPoToken = undefined; + playbackWebPoTokenContentBinding = videoId; statusElement.textContent = `Loading video: ${videoId}...`; console.log('[Player]', `Loading video: ${videoId}`); @@ -116,7 +133,7 @@ async function loadVideo(videoId: string) { pyv: true }, contentPlaybackContext: { - signatureTimestamp: innertube.session.player?.sts + signatureTimestamp: innertube.session.player?.signature_timestamp } } }); @@ -144,18 +161,18 @@ async function loadVideo(videoId: string) { }); sabrAdapter.onMintPoToken(async () => { - if (!sessionPoToken) { + if (!playbackWebPoToken) { // For live streams, we must block and wait for the PO token as it's sometimes required for playback to start. // For VODs, we can mint the token in the background to avoid delaying playback, as it's not immediately required. // While BotGuard is pretty darn fast, it still makes a difference in user experience (from my own testing). if (isLive) { - await mintSessionPoToken(); + await mintContentWebPO(); } else { - mintSessionPoToken().then(); + mintContentWebPO().then(); } } - return sessionPoToken || coldStartToken || ''; + return playbackWebPoToken || coldStartToken || ''; }); sabrAdapter.onReloadPlayerResponse(async (reloadContext) => { @@ -170,21 +187,21 @@ async function loadVideo(videoId: string) { pyv: true }, contentPlaybackContext: { - signatureTimestamp: innertube.session.player?.sts + signatureTimestamp: innertube.session.player?.signature_timestamp }, reloadPlaybackContext: reloadContext } }); const parsedInfo = new YT.VideoInfo([ reloadedInfo ], innertube.actions, cpn); - sabrAdapter.setStreamingURL(innertube.session.player!.decipher(parsedInfo.streaming_data?.server_abr_streaming_url)); + sabrAdapter.setStreamingURL(await innertube.session.player!.decipher(parsedInfo.streaming_data?.server_abr_streaming_url)); sabrAdapter.setUstreamerConfig(videoInfo.player_config?.media_common_config.media_ustreamer_request_config?.video_playback_ustreamer_config); }); sabrAdapter.attach(player); if (videoInfo.streaming_data && !isPostLiveDVR && !isLive) { - sabrAdapter.setStreamingURL(innertube.session.player!.decipher(videoInfo.streaming_data?.server_abr_streaming_url)); + sabrAdapter.setStreamingURL(await innertube.session.player!.decipher(videoInfo.streaming_data?.server_abr_streaming_url)); sabrAdapter.setUstreamerConfig(videoInfo.player_config?.media_common_config.media_ustreamer_request_config?.video_playback_ustreamer_config); sabrAdapter.setServerAbrFormats(videoInfo.streaming_data.adaptive_formats.map(buildSabrFormat)); } @@ -219,24 +236,24 @@ async function loadVideo(videoId: string) { } } -async function mintSessionPoToken() { - if (!sessionPoTokenContentBinding || sessionPoTokenCreationLock) return; +async function mintContentWebPO() { + if (!playbackWebPoTokenContentBinding || playbackWebPoTokenCreationLock) return; - sessionPoTokenCreationLock = true; + playbackWebPoTokenCreationLock = true; try { - coldStartToken = botguardService.mintColdStartToken(sessionPoTokenContentBinding); - console.info('[Player]', `Cold start token created (Content binding: ${decodeURIComponent(sessionPoTokenContentBinding)})`); + coldStartToken = botguardService.mintColdStartToken(playbackWebPoTokenContentBinding); + console.info('[Player]', `Cold start token created (Content binding: ${decodeURIComponent(playbackWebPoTokenContentBinding)})`); if (!botguardService.isInitialized()) await botguardService.reinit(); if (botguardService.integrityTokenBasedMinter) { - sessionPoToken = await botguardService.integrityTokenBasedMinter.mintAsWebsafeString(decodeURIComponent(sessionPoTokenContentBinding)); - console.info('[Player]', `Session PO token created (Content binding: ${decodeURIComponent(sessionPoTokenContentBinding)})`); + playbackWebPoToken = await botguardService.integrityTokenBasedMinter.mintAsWebsafeString(decodeURIComponent(playbackWebPoTokenContentBinding)); + console.info('[Player]', `WebPO token created (Content binding: ${decodeURIComponent(playbackWebPoTokenContentBinding)})`); } } catch (err) { - console.error('[Player]', 'Error minting session PO token', err); + console.error('[Player]', 'Error minting WebPO token', err); } finally { - sessionPoTokenCreationLock = false; + playbackWebPoTokenCreationLock = false; } }