From 5c9c231cc2f17c49da03daa8262043b985320e9a Mon Sep 17 00:00:00 2001 From: LuanRT Date: Fri, 1 Dec 2023 17:14:36 -0300 Subject: [PATCH] feat(MediaInfo): Parse player config --- src/core/mixins/MediaInfo.ts | 4 +++- src/parser/parser.ts | 22 ++++++++++++++++++++++ src/parser/types/ParsedResponse.ts | 20 ++++++++++++++++++++ src/parser/types/RawResponse.ts | 19 +++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/core/mixins/MediaInfo.ts b/src/core/mixins/MediaInfo.ts index 19a8158f..39718b08 100644 --- a/src/core/mixins/MediaInfo.ts +++ b/src/core/mixins/MediaInfo.ts @@ -5,7 +5,7 @@ import type { DownloadOptions, FormatFilter, FormatOptions, URLTransformer } fro import * as FormatUtils from '../../utils/FormatUtils.js'; import { InnertubeError } from '../../utils/Utils.js'; import type Format from '../../parser/classes/misc/Format.js'; -import type { INextResponse, IPlayerResponse } from '../../parser/index.js'; +import type { INextResponse, IPlayerConfig, IPlayerResponse } from '../../parser/index.js'; import { Parser } from '../../parser/index.js'; import type { DashOptions } from '../../types/DashOptions.js'; import PlayerStoryboardSpec from '../../parser/classes/PlayerStoryboardSpec.js'; @@ -20,6 +20,7 @@ export default class MediaInfo { #playback_tracking; streaming_data; playability_status; + player_config: IPlayerConfig; constructor(data: [ApiResponse, ApiResponse?], actions: Actions, cpn: string) { this.#actions = actions; @@ -35,6 +36,7 @@ export default class MediaInfo { this.streaming_data = info.streaming_data; this.playability_status = info.playability_status; + this.player_config = info.player_config; this.#playback_tracking = info.playback_tracking; } diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 73effdf2..e487c5d5 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -398,6 +398,28 @@ export function parseResponse(data: parsed_data.streaming_data = streaming_data; } + if (data.playerConfig) { + const player_config = { + audio_config: { + loudness_db: data.playerConfig.audioConfig.loudnessDb, + perceptual_loudness_db: data.playerConfig.audioConfig.perceptualLoudnessDb, + enable_per_format_loudness: data.playerConfig.audioConfig.enablePerFormatLoudness + }, + stream_selection_config: { + max_bitrate: data.playerConfig.streamSelectionConfig.maxBitrate + }, + media_common_config: { + dynamic_readahead_config: { + max_read_ahead_media_time_ms: data.playerConfig.mediaCommonConfig.dynamicReadaheadConfig.maxReadAheadMediaTimeMs, + min_read_ahead_media_time_ms: data.playerConfig.mediaCommonConfig.dynamicReadaheadConfig.minReadAheadMediaTimeMs, + read_ahead_growth_rate_ms: data.playerConfig.mediaCommonConfig.dynamicReadaheadConfig.readAheadGrowthRateMs + } + } + }; + + parsed_data.player_config = player_config; + } + const current_video_endpoint = data.currentVideoEndpoint ? new NavigationEndpoint(data.currentVideoEndpoint) : null; if (current_video_endpoint) { parsed_data.current_video_endpoint = current_video_endpoint; diff --git a/src/parser/types/ParsedResponse.ts b/src/parser/types/ParsedResponse.ts index c138a098..1659633c 100644 --- a/src/parser/types/ParsedResponse.ts +++ b/src/parser/types/ParsedResponse.ts @@ -56,6 +56,7 @@ export interface IParsedResponse { }; playability_status?: IPlayabilityStatus; streaming_data?: IStreamingData; + player_config?: IPlayerConfig; current_video_endpoint?: NavigationEndpoint; endpoint?: NavigationEndpoint; captions?: PlayerCaptionsTracklist; @@ -71,6 +72,24 @@ export interface IParsedResponse { continuationEndpoint?: YTNode; } +export interface IPlayerConfig { + audio_config: { + loudness_db: number; + perceptual_loudness_db: number; + enable_per_format_loudness: boolean; + }; + stream_selection_config: { + max_bitrate: string; + }; + media_common_config: { + dynamic_readahead_config: { + max_read_ahead_media_time_ms: number; + min_read_ahead_media_time_ms: number; + read_ahead_growth_rate_ms: number; + }; + }; +} + export interface IStreamingData { expires: Date; formats: Format[]; @@ -87,6 +106,7 @@ export interface IPlayerResponse { annotations?: ObservedArray; playability_status: IPlayabilityStatus; streaming_data?: IStreamingData; + player_config: IPlayerConfig; playback_tracking?: { videostats_watchtime_url: string; videostats_playback_url: string; diff --git a/src/parser/types/RawResponse.ts b/src/parser/types/RawResponse.ts index 8dd05f2e..5577393b 100644 --- a/src/parser/types/RawResponse.ts +++ b/src/parser/types/RawResponse.ts @@ -1,6 +1,24 @@ export type RawNode = Record; export type RawData = RawNode | RawNode[]; +export interface IRawPlayerConfig { + audioConfig: { + loudnessDb: number; + perceptualLoudnessDb: number; + enablePerFormatLoudness: boolean; + }; + streamSelectionConfig: { + maxBitrate: string; + }; + mediaCommonConfig: { + dynamicReadaheadConfig: { + maxReadAheadMediaTimeMs: number; + minReadAheadMediaTimeMs: number; + readAheadGrowthRateMs: number; + }; + }; +} + export interface IRawResponse { contents?: RawData; onResponseReceivedActions?: RawNode[]; @@ -41,6 +59,7 @@ export interface IRawResponse { dashManifestUrl?: string; hlsManifestUrl?: string; }; + playerConfig?: IRawPlayerConfig; currentVideoEndpoint?: RawNode; unseenCount?: number; playlistId?: string;