mirror of
https://github.com/wukko/cobalt.git
synced 2025-03-26 11:14:44 +01: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
2 changed files with 39 additions and 21 deletions
|
@ -57,6 +57,7 @@ const env = {
|
|||
customInnertubeClient: process.env.CUSTOM_INNERTUBE_CLIENT,
|
||||
ytSessionServer: process.env.YOUTUBE_SESSION_SERVER,
|
||||
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";
|
||||
|
|
|
@ -46,7 +46,7 @@ const clientsWithNoCipher = ['IOS', 'ANDROID', 'YTSTUDIO_ANDROID', 'YTMUSIC_ANDR
|
|||
|
||||
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 rawCookie = getCookie('youtube');
|
||||
|
@ -55,7 +55,7 @@ const cloneInnertube = async (customFetch) => {
|
|||
const sessionTokens = getYouTubeSession();
|
||||
const retrieve_player = Boolean(sessionTokens || cookie);
|
||||
|
||||
if (env.ytSessionServer && !sessionTokens?.potoken) {
|
||||
if (useSession && env.ytSessionServer && !sessionTokens?.potoken) {
|
||||
throw "no_session_tokens";
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ const cloneInnertube = async (customFetch) => {
|
|||
fetch: customFetch,
|
||||
retrieve_player,
|
||||
cookie,
|
||||
po_token: sessionTokens?.potoken,
|
||||
visitor_data: sessionTokens?.visitor_data,
|
||||
po_token: useSession ? sessionTokens?.potoken : undefined,
|
||||
visitor_data: useSession ? sessionTokens?.visitor_data : undefined,
|
||||
});
|
||||
lastRefreshedAt = +new Date();
|
||||
}
|
||||
|
@ -86,13 +86,46 @@ const cloneInnertube = async (customFetch) => {
|
|||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
yt = await cloneInnertube(
|
||||
(input, init) => fetch(input, {
|
||||
...init,
|
||||
dispatcher: o.dispatcher
|
||||
})
|
||||
}),
|
||||
useSession
|
||||
);
|
||||
} catch (e) {
|
||||
if (e === "no_session_tokens") {
|
||||
|
@ -104,20 +137,6 @@ export default async function (o) {
|
|||
} 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;
|
||||
try {
|
||||
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 shortestSide = Math.min(res.height, res.width);
|
||||
return videoQualities.find(qual => qual >= shortestSide);
|
||||
|
|
Loading…
Add table
Reference in a new issue