@@ -330,6 +330,7 @@ def get_stream(self, uuid: str, content_type: str) -> ResolvedStream:
330330
331331 manifest_urls = data .get ('manifestUrls' ) or {}
332332 manifest_url = None
333+ subtitle_url = None
333334 stream_type = None
334335
335336 # Manifest URLs (DASH or HLS)
@@ -344,11 +345,12 @@ def get_stream(self, uuid: str, content_type: str) -> ResolvedStream:
344345 elif data .get ('adType' ) == 'SSAI' and data .get ('ssai' ):
345346 ssai = data ['ssai' ]
346347 ssai_url = (
347- f" https://pubads.g.doubleclick.net/ondemand/dash/content/"
348- f" { ssai .get ('contentSourceID' )} /vid/{ ssai .get ('videoID' )} /streams"
348+ f' https://pubads.g.doubleclick.net/ondemand/dash/content/'
349+ f' { ssai .get ('contentSourceID' )} /vid/{ ssai .get ('videoID' )} /streams'
349350 )
350351 ad_data = json .loads (utils .post_url (ssai_url , data = '' ))
351352 manifest_url = ad_data .get ('stream_manifest' )
353+ subtitle_url = self .extract_subtitle_from_manifest (manifest_url )
352354 stream_type = STREAM_DASH
353355
354356 if not manifest_url or not stream_type :
@@ -380,8 +382,47 @@ def get_stream(self, uuid: str, content_type: str) -> ResolvedStream:
380382 license_url = self .LICENSE_URL ,
381383 license_headers = license_headers ,
382384 license_keys = license_keys ,
385+ subtitles = [subtitle_url ],
383386 )
384387
388+ def extract_subtitle_from_manifest (self , manifest_url ):
389+ """Extract subtitle URL from a DASH manifest"""
390+ from xml .etree .ElementTree import fromstring
391+
392+ manifest_data = utils .get_url (manifest_url )
393+ manifest = fromstring (manifest_data )
394+
395+ ns = {'mpd' : 'urn:mpeg:dash:schema:mpd:2011' }
396+
397+ base_url_el = manifest .find ('mpd:BaseURL' , ns )
398+ if base_url_el is None or not base_url_el .text :
399+ return None
400+
401+ base_url = base_url_el .text
402+
403+ for adaption in manifest .iterfind (
404+ './/mpd:AdaptationSet[@contentType="text"]' , ns
405+ ):
406+ rep = adaption .find ('mpd:Representation' , ns )
407+ if rep is None :
408+ continue
409+
410+ sub_base = rep .find ('mpd:BaseURL' , ns )
411+ if sub_base is None or not sub_base .text :
412+ continue
413+
414+ sub_path = sub_base .text
415+ if 'T888' not in sub_path :
416+ continue
417+
418+ # Strip period-specific suffix safely
419+ name , _ , ext = sub_path .rpartition ('.' )
420+ clean_path = name .rsplit ('_' , 1 )[0 ] + '.' + ext
421+
422+ return base_url + clean_path
423+
424+ return None
425+
385426 def get_program_tree (self ):
386427 """ Get a content tree with information about all the programs.
387428 :rtype list[Program]
0 commit comments