Skip to content

Commit

Permalink
api/youtube: use poToken, visitorData, and web client with cookies
Browse files Browse the repository at this point in the history
and also decipher media whenever needed, but only if cookies are used
  • Loading branch information
wukko committed Dec 23, 2024
1 parent 9da3ba6 commit c6d0e0b
Showing 1 changed file with 38 additions and 9 deletions.
47 changes: 38 additions & 9 deletions api/src/processing/services/youtube.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const transformSessionData = (cookie) => {
return;

const values = { ...cookie.values() };
const REQUIRED_VALUES = [ 'access_token', 'refresh_token' ];
const REQUIRED_VALUES = ['access_token', 'refresh_token'];

if (REQUIRED_VALUES.some(x => typeof values[x] !== 'string')) {
return;
Expand All @@ -66,12 +66,18 @@ const transformSessionData = (cookie) => {

const cloneInnertube = async (customFetch) => {
const shouldRefreshPlayer = lastRefreshedAt + PLAYER_REFRESH_PERIOD < new Date();
const cookie = getCookie('youtube')?.toString();

const rawCookie = getCookie('youtube');
const cookieValues = rawCookie?.values();
const cookie = rawCookie?.toString();

if (!innertube || shouldRefreshPlayer) {
innertube = await Innertube.create({
fetch: customFetch,
retrieve_player: false,
cookie
retrieve_player: !!cookie,
cookie,
po_token: cookieValues?.po_token,
visitor_data: cookieValues?.visitor_data,
});
lastRefreshedAt = +new Date();
}
Expand Down Expand Up @@ -117,7 +123,7 @@ const cloneInnertube = async (customFetch) => {
return yt;
}

export default async function(o) {
export default async function (o) {
let yt;
try {
yt = await cloneInnertube(
Expand All @@ -134,16 +140,29 @@ export default async function(o) {
} else throw e;
}

const cookie = getCookie('youtube')?.toString();

let useHLS = o.youtubeHLS;

// HLS playlists don't contain the av1 video format, at least with the iOS client
if (useHLS && o.format === "av1") {
useHLS = false;
}

let innertubeClient = "ANDROID";

if (cookie) {
useHLS = false;
innertubeClient = "WEB";
}

if (useHLS) {
innertubeClient = "IOS";
}

let info;
try {
info = await yt.getBasicInfo(o.id, useHLS ? 'IOS' : 'ANDROID');
info = await yt.getBasicInfo(o.id, innertubeClient);
} catch (e) {
if (e?.info) {
const errorInfo = JSON.parse(e?.info);
Expand All @@ -168,7 +187,7 @@ export default async function(o) {
const playability = info.playability_status;
const basicInfo = info.basic_info;

switch(playability.status) {
switch (playability.status) {
case "LOGIN_REQUIRED":
if (playability.reason.endsWith("bot")) {
return { error: "youtube.login" }
Expand Down Expand Up @@ -243,7 +262,7 @@ export default async function(o) {
} else {
throw new Error("couldn't fetch the HLS playlist");
}
}).catch(() => {});
}).catch(() => { });

if (!fetchedHlsManifest) {
return { error: "youtube.no_hls_streams" };
Expand Down Expand Up @@ -324,7 +343,7 @@ export default async function(o) {
}

const checkFormat = (format, pCodec) => format.content_length &&
(format.mime_type.includes(codecList[pCodec].videoCodec)
(format.mime_type.includes(codecList[pCodec].videoCodec)
|| format.mime_type.includes(codecList[pCodec].audioCodec));

// sort formats & weed out bad ones
Expand Down Expand Up @@ -438,6 +457,10 @@ export default async function(o) {
urls = audio.uri;
}

if (innertubeClient === "WEB" && innertube) {
urls = audio.decipher(innertube.session.player);
}

return {
type: "audio",
isAudioOnly: true,
Expand All @@ -464,11 +487,17 @@ export default async function(o) {
width: video.width,
height: video.height,
});

filenameAttributes.resolution = `${video.width}x${video.height}`;
filenameAttributes.extension = codecList[codec].container;

video = video.url;
audio = audio.url;

if (innertubeClient === "WEB" && innertube) {
video = video.decipher(innertube.session.player);
audio = audio.decipher(innertube.session.player);
}
}

filenameAttributes.qualityLabel = `${resolution}p`;
Expand Down

0 comments on commit c6d0e0b

Please sign in to comment.