mirror of
https://github.com/imputnet/cobalt.git
synced 2025-06-28 09:28:29 +00:00
api/youtube: use both ios & web_embedded client depending on request
this ensures better reliability & reduces rate limiting of either clients
This commit is contained in:
parent
e779506d9e
commit
24ce19d09f
@ -57,6 +57,7 @@ const env = {
|
|||||||
customInnertubeClient: process.env.CUSTOM_INNERTUBE_CLIENT,
|
customInnertubeClient: process.env.CUSTOM_INNERTUBE_CLIENT,
|
||||||
ytSessionServer: process.env.YOUTUBE_SESSION_SERVER,
|
ytSessionServer: process.env.YOUTUBE_SESSION_SERVER,
|
||||||
ytSessionReloadInterval: 300,
|
ytSessionReloadInterval: 300,
|
||||||
|
ytSessionInnertubeClient: process.env.YOUTUBE_SESSION_INNERTUBE_CLIENT,
|
||||||
}
|
}
|
||||||
|
|
||||||
const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
|
const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
|
||||||
|
@ -46,7 +46,7 @@ const clientsWithNoCipher = ['IOS', 'ANDROID', 'YTSTUDIO_ANDROID', 'YTMUSIC_ANDR
|
|||||||
|
|
||||||
const videoQualities = [144, 240, 360, 480, 720, 1080, 1440, 2160, 4320];
|
const videoQualities = [144, 240, 360, 480, 720, 1080, 1440, 2160, 4320];
|
||||||
|
|
||||||
const cloneInnertube = async (customFetch) => {
|
const cloneInnertube = async (customFetch, useSession) => {
|
||||||
const shouldRefreshPlayer = lastRefreshedAt + PLAYER_REFRESH_PERIOD < new Date();
|
const shouldRefreshPlayer = lastRefreshedAt + PLAYER_REFRESH_PERIOD < new Date();
|
||||||
|
|
||||||
const rawCookie = getCookie('youtube');
|
const rawCookie = getCookie('youtube');
|
||||||
@ -55,7 +55,7 @@ const cloneInnertube = async (customFetch) => {
|
|||||||
const sessionTokens = getYouTubeSession();
|
const sessionTokens = getYouTubeSession();
|
||||||
const retrieve_player = Boolean(sessionTokens || cookie);
|
const retrieve_player = Boolean(sessionTokens || cookie);
|
||||||
|
|
||||||
if (env.ytSessionServer && !sessionTokens?.potoken) {
|
if (useSession && env.ytSessionServer && !sessionTokens?.potoken) {
|
||||||
throw "no_session_tokens";
|
throw "no_session_tokens";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ const cloneInnertube = async (customFetch) => {
|
|||||||
fetch: customFetch,
|
fetch: customFetch,
|
||||||
retrieve_player,
|
retrieve_player,
|
||||||
cookie,
|
cookie,
|
||||||
po_token: sessionTokens?.potoken,
|
po_token: useSession ? sessionTokens?.potoken : undefined,
|
||||||
visitor_data: sessionTokens?.visitor_data,
|
visitor_data: useSession ? sessionTokens?.visitor_data : undefined,
|
||||||
});
|
});
|
||||||
lastRefreshedAt = +new Date();
|
lastRefreshedAt = +new Date();
|
||||||
}
|
}
|
||||||
@ -86,13 +86,46 @@ const cloneInnertube = async (customFetch) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function (o) {
|
export default async function (o) {
|
||||||
|
const quality = o.quality === "max" ? 9000 : Number(o.quality);
|
||||||
|
|
||||||
|
let useHLS = o.youtubeHLS;
|
||||||
|
let innertubeClient = o.innertubeClient || env.customInnertubeClient || "IOS";
|
||||||
|
|
||||||
|
// HLS playlists from the iOS client don't contain the av1 video format.
|
||||||
|
if (useHLS && o.format === "av1") {
|
||||||
|
useHLS = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useHLS) {
|
||||||
|
innertubeClient = "IOS";
|
||||||
|
}
|
||||||
|
|
||||||
|
// iOS client doesn't have adaptive formats of resolution >1080p,
|
||||||
|
// so we use the WEB_EMBEDDED client instead for those cases
|
||||||
|
const useSession =
|
||||||
|
env.ytSessionServer && (
|
||||||
|
(
|
||||||
|
!useHLS
|
||||||
|
&& innertubeClient === "IOS"
|
||||||
|
&& (
|
||||||
|
(quality > 1080 && o.format !== "h264")
|
||||||
|
|| o.format === "vp9"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (useSession) {
|
||||||
|
innertubeClient = env.ytSessionInnertubeClient || "WEB_EMBEDDED";
|
||||||
|
}
|
||||||
|
|
||||||
let yt;
|
let yt;
|
||||||
try {
|
try {
|
||||||
yt = await cloneInnertube(
|
yt = await cloneInnertube(
|
||||||
(input, init) => fetch(input, {
|
(input, init) => fetch(input, {
|
||||||
...init,
|
...init,
|
||||||
dispatcher: o.dispatcher
|
dispatcher: o.dispatcher
|
||||||
})
|
}),
|
||||||
|
useSession
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e === "no_session_tokens") {
|
if (e === "no_session_tokens") {
|
||||||
@ -104,20 +137,6 @@ export default async function (o) {
|
|||||||
} else throw e;
|
} else throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
let useHLS = o.youtubeHLS;
|
|
||||||
|
|
||||||
// HLS playlists don't contain the av1 video format.
|
|
||||||
// if the session server is used, then iOS client will not work, at least currently.
|
|
||||||
if (useHLS && (o.format === "av1" || env.ytSessionServer)) {
|
|
||||||
useHLS = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
let innertubeClient = o.innertubeClient || env.customInnertubeClient || "ANDROID";
|
|
||||||
|
|
||||||
if (useHLS) {
|
|
||||||
innertubeClient = "IOS";
|
|
||||||
}
|
|
||||||
|
|
||||||
let info;
|
let info;
|
||||||
try {
|
try {
|
||||||
info = await yt.getBasicInfo(o.id, innertubeClient);
|
info = await yt.getBasicInfo(o.id, innertubeClient);
|
||||||
@ -196,8 +215,6 @@ export default async function (o) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const quality = o.quality === "max" ? 9000 : Number(o.quality);
|
|
||||||
|
|
||||||
const normalizeQuality = res => {
|
const normalizeQuality = res => {
|
||||||
const shortestSide = Math.min(res.height, res.width);
|
const shortestSide = Math.min(res.height, res.width);
|
||||||
return videoQualities.find(qual => qual >= shortestSide);
|
return videoQualities.find(qual => qual >= shortestSide);
|
||||||
|
Loading…
Reference in New Issue
Block a user