mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-12 04:50:44 +00:00
fix trailers: update user agents and innertube api key depreciation
This commit is contained in:
parent
905c59d23d
commit
ed5bb26a59
1 changed files with 18 additions and 13 deletions
|
|
@ -70,17 +70,17 @@ export interface YouTubeExtractionResult {
|
||||||
|
|
||||||
// Innertube client configs — we use Android (no cipher, direct URLs)
|
// Innertube client configs — we use Android (no cipher, direct URLs)
|
||||||
// and web as fallback (may need cipher decode)
|
// and web as fallback (may need cipher decode)
|
||||||
const INNERTUBE_API_KEY = 'AIzaSyA8ggJvXiQHQFN-YMEoM30s0s3RlxEYJuA';
|
// Note: ?key= param was deprecated by YouTube in mid-2023 and is no longer sent.
|
||||||
const INNERTUBE_URL = 'https://www.youtube.com/youtubei/v1/player';
|
const INNERTUBE_URL = 'https://www.youtube.com/youtubei/v1/player';
|
||||||
|
|
||||||
// Android client gives direct URLs without cipher obfuscation
|
// Android client gives direct URLs without cipher obfuscation
|
||||||
const ANDROID_CLIENT_CONTEXT = {
|
const ANDROID_CLIENT_CONTEXT = {
|
||||||
client: {
|
client: {
|
||||||
clientName: 'ANDROID',
|
clientName: 'ANDROID',
|
||||||
clientVersion: '19.09.37',
|
clientVersion: '19.44.41',
|
||||||
androidSdkVersion: 30,
|
androidSdkVersion: 30,
|
||||||
userAgent:
|
userAgent:
|
||||||
'com.google.android.youtube/19.09.37 (Linux; U; Android 11) gzip',
|
'com.google.android.youtube/19.44.41 (Linux; U; Android 11) gzip',
|
||||||
hl: 'en',
|
hl: 'en',
|
||||||
gl: 'US',
|
gl: 'US',
|
||||||
},
|
},
|
||||||
|
|
@ -90,10 +90,10 @@ const ANDROID_CLIENT_CONTEXT = {
|
||||||
const IOS_CLIENT_CONTEXT = {
|
const IOS_CLIENT_CONTEXT = {
|
||||||
client: {
|
client: {
|
||||||
clientName: 'IOS',
|
clientName: 'IOS',
|
||||||
clientVersion: '19.09.3',
|
clientVersion: '19.45.4',
|
||||||
deviceModel: 'iPhone14,3',
|
deviceModel: 'iPhone16,2',
|
||||||
userAgent:
|
userAgent:
|
||||||
'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iPhone OS 15_6 like Mac OS X)',
|
'com.google.ios.youtube/19.45.4 (iPhone16,2; U; CPU iOS 17_5_1 like Mac OS X)',
|
||||||
hl: 'en',
|
hl: 'en',
|
||||||
gl: 'US',
|
gl: 'US',
|
||||||
},
|
},
|
||||||
|
|
@ -359,7 +359,8 @@ async function writeDashManifestToFile(
|
||||||
async function fetchPlayerResponse(
|
async function fetchPlayerResponse(
|
||||||
videoId: string,
|
videoId: string,
|
||||||
context: object,
|
context: object,
|
||||||
userAgent: string
|
userAgent: string,
|
||||||
|
clientNameId: string = '3'
|
||||||
): Promise<InnertubePlayerResponse | null> {
|
): Promise<InnertubePlayerResponse | null> {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
||||||
|
|
@ -373,13 +374,13 @@ async function fetchPlayerResponse(
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${INNERTUBE_URL}?key=${INNERTUBE_API_KEY}&prettyPrint=false`,
|
`${INNERTUBE_URL}?prettyPrint=false`,
|
||||||
{
|
{
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'User-Agent': userAgent,
|
'User-Agent': userAgent,
|
||||||
'X-YouTube-Client-Name': '3',
|
'X-YouTube-Client-Name': clientNameId,
|
||||||
'Origin': 'https://www.youtube.com',
|
'Origin': 'https://www.youtube.com',
|
||||||
'Referer': `https://www.youtube.com/watch?v=${videoId}`,
|
'Referer': `https://www.youtube.com/watch?v=${videoId}`,
|
||||||
},
|
},
|
||||||
|
|
@ -500,24 +501,28 @@ export class YouTubeExtractor {
|
||||||
|
|
||||||
logger.info('YouTubeExtractor', `Extracting for videoId=${videoId} platform=${platform ?? 'unknown'}`);
|
logger.info('YouTubeExtractor', `Extracting for videoId=${videoId} platform=${platform ?? 'unknown'}`);
|
||||||
|
|
||||||
const clients: Array<{ context: object; userAgent: string; name: string }> = [
|
const clients: Array<{ context: object; userAgent: string; name: string; clientNameId: string }> = [
|
||||||
{
|
{
|
||||||
name: 'ANDROID',
|
name: 'ANDROID',
|
||||||
|
clientNameId: '3',
|
||||||
context: ANDROID_CLIENT_CONTEXT,
|
context: ANDROID_CLIENT_CONTEXT,
|
||||||
userAgent: 'com.google.android.youtube/19.09.37 (Linux; U; Android 11) gzip',
|
userAgent: 'com.google.android.youtube/19.44.41 (Linux; U; Android 11) gzip',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'IOS',
|
name: 'IOS',
|
||||||
|
clientNameId: '5',
|
||||||
context: IOS_CLIENT_CONTEXT,
|
context: IOS_CLIENT_CONTEXT,
|
||||||
userAgent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iPhone OS 15_6 like Mac OS X)',
|
userAgent: 'com.google.ios.youtube/19.45.4 (iPhone16,2; U; CPU iOS 17_5_1 like Mac OS X)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'TVHTML5_EMBEDDED',
|
name: 'TVHTML5_EMBEDDED',
|
||||||
|
clientNameId: '85',
|
||||||
context: TVHTML5_EMBEDDED_CONTEXT,
|
context: TVHTML5_EMBEDDED_CONTEXT,
|
||||||
userAgent: 'Mozilla/5.0 (SMART-TV; Linux; Tizen 6.0)',
|
userAgent: 'Mozilla/5.0 (SMART-TV; Linux; Tizen 6.0)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'WEB_EMBEDDED',
|
name: 'WEB_EMBEDDED',
|
||||||
|
clientNameId: '56',
|
||||||
context: WEB_EMBEDDED_CONTEXT,
|
context: WEB_EMBEDDED_CONTEXT,
|
||||||
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
|
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
|
||||||
},
|
},
|
||||||
|
|
@ -529,7 +534,7 @@ export class YouTubeExtractor {
|
||||||
|
|
||||||
for (const client of clients) {
|
for (const client of clients) {
|
||||||
logger.info('YouTubeExtractor', `Trying ${client.name} client...`);
|
logger.info('YouTubeExtractor', `Trying ${client.name} client...`);
|
||||||
const resp = await fetchPlayerResponse(videoId, client.context, client.userAgent);
|
const resp = await fetchPlayerResponse(videoId, client.context, client.userAgent, client.clientNameId);
|
||||||
if (!resp) continue;
|
if (!resp) continue;
|
||||||
|
|
||||||
const status = resp.playabilityStatus?.status;
|
const status = resp.playabilityStatus?.status;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue