yt-stream
Version:
Create easily readable streams from YouTube video url's
127 lines (120 loc) • 4.73 kB
JavaScript
const androidUserAgents = [{
agent: 'com.google.android.youtube/19.28.35(Linux; U; Android 13; en_US; sdk_gphone64_x86_64 Build/UPB4.230623.005) gzip',
clientVersion: '19.28.35',
deviceModel: 'sdk_gphone64_x86_64',
sdkVersion: 33
}, {
agent: 'com.google.android.youtube/19.28.35(Linux; U; Android 13; en_US; M2103K19G Build/TP1A.220624.014) gzip',
clientVersion: '19.28.35',
deviceModel: 'M2103K19G',
sdkVersion: 33
}, {
agent: 'com.google.android.youtube/19.28.35(Linux; U; Android 14; en_US; 23073RPBFG Build/UKQ1.231003.002) gzip',
clientVersion: '19.28.35',
deviceModel: '23073RPBFG',
sdkVersion: 33
}, {
agent: 'com.google.android.youtube/19.28.35(Linux; U; Android 13; en_US; CPH2557 Build/TP1A.220905.001) gzip',
clientVersion: '19.28.35',
deviceModel: 'CPH2557',
sdkVersion: 33
}];
const iosUserAgents = [{
agent: 'com.google.ios.youtube/18.06.35 (iPhone; CPU iPhone OS 14_4 like Mac OS X; en_US)',
clientVersion: '18.06.35',
deviceModel: 'iPhone10,6'
}, {
agent: 'com.google.ios.youtube/19.09.3 (iPhone14,3; U; CPU iOS 15_6 like Mac OS X en_US)',
clientVersion: '19.09.3',
deviceModel: 'iPhone14,3'
}, {
agent: 'com.google.ios.youtube/19.28.1 (iPhone16,2; U; CPU IOS 17_5_1 like Mac OS X; en_US)',
clientVersion: '19.28.1',
deviceModel: 'iPhone16,2'
}];
function genNonce(length){
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-';
let nonce = "";
while(nonce.length < length){
nonce += chars[Math.round(Math.random() * (chars.length - 1))];
}
return nonce;
}
function genClientInfo(videoId, preferedClient){
const clientTypes = ['ANDROID', 'IOS'];
const client = preferedClient ?? clientTypes[Math.round(Math.random() * (clientTypes.length - 1))];
let headers = {
'x-youtube-client-name': '',
'x-youtube-client-version': '',
'origin': 'https://www.youtube.com',
'user-agent': '',
'content-type': 'application/json'
};
let userAgent, clientVersion;
let contextBuilder = {
context: {
client: {
cpn: genNonce(16),
clientName: client,
clientVersion: undefined,
deviceModel: undefined,
userAgent: undefined,
hl: 'en',
timeZone: 'UTC',
utcOffsetMinutes: 0,
acceptLanguage: 'en-US',
acceptRegion: 'US'
}
},
contentCheckOk: true,
racyCheckOk: true,
attestationRequest: {
omitBotguardData: true
}
};
if(typeof videoId === 'string'){
contextBuilder = {
...contextBuilder,
videoId: videoId,
playbackContext: {
contentPlaybackContext: {
html5Preference: 'HTML5_PREF_WANTS',
vis: 0,
splay: false,
referer: `https://www.youtube.com/watch?v=${videoId}`,
currentUrl: `/watch?v=${videoId}`,
autonavState: 'STATE_ON',
autoCaptionsDefaultOn: false,
lactMilliseconds: '-1'
}
}
};
}
switch(client){
case 'ANDROID':
let androidRandomAgent = androidUserAgents[Math.round(Math.random() * (androidUserAgents.length - 1))];
userAgent = androidRandomAgent.agent;
clientVersion = androidRandomAgent.clientVersion;
contextBuilder.context.client.deviceModel = androidRandomAgent.deviceModel;
contextBuilder.context.client['androidSdkVersion'] = androidRandomAgent.sdkVersion;
headers['x-youtube-client-name'] = '3';
headers['x-goog-api-format-version'] = '2';
break;
case 'IOS':
let iosRandomAgent = iosUserAgents[Math.round(Math.random() * (iosUserAgents.length - 1))];
userAgent = iosRandomAgent.agent;
clientVersion = iosRandomAgent.clientVersion;
contextBuilder.context.client.deviceModel = iosRandomAgent.deviceModel;
headers['x-youtube-client-name'] = '5';
break;
}
contextBuilder.context.client.userAgent = userAgent;
contextBuilder.context.client.clientVersion = clientVersion;
headers['user-agent'] = userAgent;
headers['x-youtube-client-version'] = clientVersion;
return {
headers,
body: contextBuilder
};
}
module.exports = genClientInfo;