From 026fa34fdb4cae3516634347677f4ce7e437eba4 Mon Sep 17 00:00:00 2001 From: absidue <48293849+absidue@users.noreply.github.com> Date: Sun, 27 Feb 2022 12:28:09 +0100 Subject: [PATCH] Fix legacy streams being closed early because they look idle --- play-dl/YouTube/utils/extractor.ts | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/play-dl/YouTube/utils/extractor.ts b/play-dl/YouTube/utils/extractor.ts index 1984d65..39ac7f3 100644 --- a/play-dl/YouTube/utils/extractor.ts +++ b/play-dl/YouTube/utils/extractor.ts @@ -274,6 +274,13 @@ export async function video_basic_info(url: string, options: InfoOptions = {}): if (!upcoming) { format.push(...(player_response.streamingData.formats ?? [])); format.push(...(player_response.streamingData.adaptiveFormats ?? [])); + + // get the formats for the android player for legacy videos + // fixes the stream being closed because not enough data + // arrived in time for ffmpeg to be able to extract audio data + if (parseAudioFormats(format).length === 0 && !options.htmldata) { + format = await getAndroidFormats(vid.videoId, cookieJar, body); + } } const LiveStreamData = { isLive: video_details.live, @@ -373,6 +380,13 @@ export async function video_stream_info(url: string, options: InfoOptions = {}): if (!upcoming) { format.push(...(player_response.streamingData.formats ?? [])); format.push(...(player_response.streamingData.adaptiveFormats ?? [])); + + // get the formats for the android player for legacy videos + // fixes the stream being closed because not enough data + // arrived in time for ffmpeg to be able to extract audio data + if (parseAudioFormats(format).length === 0 && !options.htmldata) { + format = await getAndroidFormats(player_response.videoDetails.videoId, cookieJar, body); + } } const LiveStreamData = { @@ -639,6 +653,36 @@ async function acceptViewerDiscretion( return { streamingData }; } +async function getAndroidFormats(videoId: string, cookieJar: { [key: string]: string }, body: string): Promise { + const apiKey = + body.split('INNERTUBE_API_KEY":"')[1]?.split('"')[0] ?? + body.split('innertubeApiKey":"')[1]?.split('"')[0] ?? + DEFAULT_API_KEY; + + const response = await request(`https://www.youtube.com/youtubei/v1/player?key=${apiKey}`, { + method: 'POST', + body: JSON.stringify({ + context: { + client: { + clientName: 'ANDROID', + clientVersion: '16.49', + hl: 'en', + timeZone: 'UTC', + utcOffsetMinutes: 0 + } + }, + videoId: videoId, + playbackContext: { contentPlaybackContext: { html5Preference: 'HTML5_PREF_WANTS' } }, + contentCheckOk: true, + racyCheckOk: true + }), + cookies: true, + cookieJar + }); + + return JSON.parse(response).streamingData.formats; +} + function getWatchPlaylist(response: any, body: any, url: string): YouTubePlayList { const playlist_details = response.contents.twoColumnWatchNextResults.playlist.playlist;