@@ -60,13 +60,49 @@ async function createInnertube({ withPlayer = false, location = undefined, safet
6060 client_type : clientType ,
6161
6262 // use browser fetch
63- fetch : ( input , init ) => {
64- if ( input . url ?. startsWith ( 'https://www.youtube.com/youtubei/v1/player' ) ) {
65- init . body = init . body . replace ( '"videoId":' , '"params":"8AEB","videoId":' )
66- }
63+ fetch : ! withPlayer
64+ ? ( input , init ) => fetch ( input , init )
65+ : async ( input , init ) => {
66+ if ( input . url ?. startsWith ( 'https://www.youtube.com/youtubei/v1/player' ) && init ?. headers ?. get ( 'X-Youtube-Client-Name' ) === '2' ) {
67+ const response = await fetch ( input , init )
68+
69+ const responseText = await response . text ( )
70+
71+ const json = JSON . parse ( responseText )
72+
73+ if ( Array . isArray ( json . adSlots ) ) {
74+ let waitSeconds = 0
75+
76+ for ( const adSlot of json . adSlots ) {
77+ if ( adSlot . adSlotRenderer ?. adSlotMetadata ?. triggerEvent === 'SLOT_TRIGGER_EVENT_BEFORE_CONTENT' ) {
78+ const playerVars = adSlot . adSlotRenderer . fulfillmentContent ?. fulfilledLayout ?. playerBytesAdLayoutRenderer
79+ ?. renderingContent ?. instreamVideoAdRenderer ?. playerVars
80+
81+ if ( playerVars ) {
82+ const match = playerVars . match ( / l e n g t h _ s e c o n d s = ( [ \d . ] + ) / )
83+
84+ if ( match ) {
85+ waitSeconds += parseFloat ( match [ 1 ] )
86+ }
87+ }
88+ }
89+ }
90+
91+ if ( waitSeconds > 0 ) {
92+ await new Promise ( ( resolve ) => setTimeout ( resolve , waitSeconds * 1000 ) )
93+ }
94+ }
95+
96+ // Need to return a new response object, as you can only read the response body once.
97+ return new Response ( responseText , {
98+ status : response . status ,
99+ statusText : response . statusText ,
100+ headers : response . headers
101+ } )
102+ }
67103
68- return fetch ( input , init )
69- } ,
104+ return fetch ( input , init )
105+ } ,
70106 cache,
71107 generate_session_locally : ! ! generateSessionLocally
72108 } )
0 commit comments