chore: Update examples

This commit is contained in:
Luan
2025-10-12 17:55:33 -03:00
parent 69db60c491
commit f2b87517c5
10 changed files with 131 additions and 167 deletions

View File

@@ -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"
}
}
}

View File

@@ -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",

View File

@@ -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<string, Types.VMPrimative>) => {
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) {

View File

@@ -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,
};

View File

@@ -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<string, Types.VMPrimative>) => {
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'

View File

@@ -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"
}
}
}

View File

@@ -13,6 +13,6 @@
"license": "ISC",
"dependencies": {
"googlevideo": "file:../..",
"youtubei.js": "^15.0.0"
"youtubei.js": "^16.0.0"
}
}

View File

@@ -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"
}
}
}

View File

@@ -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",

View File

@@ -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<string, Types.VMPrimative>) => {
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;
}
}