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