4 from . import get_suitable_downloader
5 from .fragment
import FragmentFD
6 from ..utils
import update_url_query
, urljoin
9 class DashSegmentsFD(FragmentFD
):
11 Download segments in a DASH manifest. External downloaders can take over
12 the fragment downloads by supporting the 'dash_frag_urls' protocol
15 FD_NAME
= 'dashsegments'
17 def real_download(self
, filename
, info_dict
):
18 if 'http_dash_segments_generator' in info_dict
['protocol'].split('+'):
19 real_downloader
= None # No external FD can support --live-from-start
21 if info_dict
.get('is_live'):
22 self
.report_error('Live DASH videos are not supported')
23 real_downloader
= get_suitable_downloader(
24 info_dict
, self
.params
, None, protocol
='dash_frag_urls', to_stdout
=(filename
== '-'))
26 real_start
= time
.time()
28 requested_formats
= [{**info_dict
, **fmt
} for fmt
in info_dict
.get('requested_formats', [])]
30 for fmt
in requested_formats
or [info_dict
]:
32 fragment_count
= 1 if self
.params
.get('test') else len(fmt
['fragments'])
36 'filename': fmt
.get('filepath') or filename
,
37 'live': 'is_from_start' if fmt
.get('is_from_start') else fmt
.get('is_live'),
38 'total_frags': fragment_count
,
42 self
._prepare
_external
_frag
_download
(ctx
)
44 self
._prepare
_and
_start
_frag
_download
(ctx
, fmt
)
45 ctx
['start'] = real_start
48 extra_param_to_segment_url
= info_dict
.get('extra_param_to_segment_url')
49 if extra_param_to_segment_url
:
50 extra_query
= urllib
.parse
.parse_qs(extra_param_to_segment_url
)
52 fragments_to_download
= self
._get
_fragments
(fmt
, ctx
, extra_query
)
56 f
'[{self.FD_NAME}] Fragment downloads will be delegated to {real_downloader.get_basename()}')
57 info_dict
['fragments'] = list(fragments_to_download
)
58 fd
= real_downloader(self
.ydl
, self
.params
)
59 return fd
.real_download(filename
, info_dict
)
61 args
.append([ctx
, fragments_to_download
, fmt
])
63 return self
.download_and_append_fragments_multiple(*args
, is_fatal
=lambda idx
: idx
== 0)
65 def _resolve_fragments(self
, fragments
, ctx
):
66 fragments
= fragments(ctx
) if callable(fragments
) else fragments
67 return [next(iter(fragments
))] if self
.params
.get('test') else fragments
69 def _get_fragments(self
, fmt
, ctx
, extra_query
):
70 fragment_base_url
= fmt
.get('fragment_base_url')
71 fragments
= self
._resolve
_fragments
(fmt
['fragments'], ctx
)
74 for i
, fragment
in enumerate(fragments
):
76 if frag_index
<= ctx
['fragment_index']:
78 fragment_url
= fragment
.get('url')
80 assert fragment_base_url
81 fragment_url
= urljoin(fragment_base_url
, fragment
['path'])
83 fragment_url
= update_url_query(fragment_url
, extra_query
)
86 'frag_index': frag_index
,
87 'fragment_count': fragment
.get('fragment_count'),