@@ -47,6 +47,12 @@ export class YoutubeTranscriptNotAvailableLanguageError extends YoutubeTranscrip
4747 }
4848}
4949
50+ export class YoutubeTranscriptEmptyError extends YoutubeTranscriptError {
51+ constructor ( videoId : string , transcriptBody : string ) {
52+ super ( `Transcript response is empty for video (${ videoId } ). Response body: ${ transcriptBody } ` ) ;
53+ }
54+ }
55+
5056export interface TranscriptConfig {
5157 lang ?: string ;
5258 langs ?: string [ ] ;
@@ -92,6 +98,7 @@ export class YoutubeTranscript {
9298
9399 if ( splittedHTML . length <= 1 ) {
94100 if ( videoPageBody . includes ( 'class="g-recaptcha"' ) ) {
101+ // TODO: add a captcha solver
95102 throw new YoutubeTranscriptTooManyRequestError ( ) ;
96103 }
97104 if ( ! videoPageBody . includes ( '"playabilityStatus":' ) ) {
@@ -152,7 +159,27 @@ export class YoutubeTranscript {
152159 throw new YoutubeTranscriptNotAvailableError ( videoId ) ;
153160 }
154161 const transcriptBody = await transcriptResponse . text ( ) ;
162+
155163 const results = [ ...transcriptBody . matchAll ( RE_XML_TRANSCRIPT ) ] ;
164+
165+ if ( results . length === 0 ) {
166+ const headers : Record < string , string > = { } ;
167+ transcriptResponse . headers . forEach ( ( value , key ) => {
168+ headers [ key ] = value ;
169+ } ) ;
170+
171+ console . error ( 'YouTube Transcript Debug Info:' , {
172+ videoId,
173+ transcriptURL,
174+ transcriptLanguage,
175+ transcriptBody,
176+ timestamp : new Date ( ) . toISOString ( ) ,
177+ responseStatus : transcriptResponse . status ,
178+ responseHeaders : headers
179+ } ) ;
180+ throw new YoutubeTranscriptEmptyError ( videoId , transcriptBody ) ;
181+ }
182+
156183 return results . map ( ( result ) => ( {
157184 text : result [ 3 ] ,
158185 duration : parseFloat ( result [ 2 ] ) ,
0 commit comments