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 info_dict
.get('is_live') and set(info_dict
['protocol'].split('+')) != {'http_dash_segments_generator'}
:
19 self
.report_error('Live DASH videos are not supported')
21 real_start
= time
.time()
22 real_downloader
= get_suitable_downloader(
23 info_dict
, self
.params
, None, protocol
='dash_frag_urls', to_stdout
=(filename
== '-'))
25 requested_formats
= [{**info_dict, **fmt}
for fmt
in info_dict
.get('requested_formats', [])]
27 for fmt
in requested_formats
or [info_dict
]:
29 fragment_count
= 1 if self
.params
.get('test') else len(fmt
['fragments'])
33 'filename': fmt
.get('filepath') or filename
,
34 'live': 'is_from_start' if fmt
.get('is_from_start') else fmt
.get('is_live'),
35 'total_frags': fragment_count
,
39 self
._prepare
_external
_frag
_download
(ctx
)
41 self
._prepare
_and
_start
_frag
_download
(ctx
, fmt
)
42 ctx
['start'] = real_start
45 extra_param_to_segment_url
= info_dict
.get('extra_param_to_segment_url')
46 if extra_param_to_segment_url
:
47 extra_query
= urllib
.parse
.parse_qs(extra_param_to_segment_url
)
49 fragments_to_download
= self
._get
_fragments
(fmt
, ctx
, extra_query
)
53 f
'[{self.FD_NAME}] Fragment downloads will be delegated to {real_downloader.get_basename()}')
54 info_dict
['fragments'] = list(fragments_to_download
)
55 fd
= real_downloader(self
.ydl
, self
.params
)
56 return fd
.real_download(filename
, info_dict
)
58 args
.append([ctx
, fragments_to_download
, fmt
])
60 return self
.download_and_append_fragments_multiple(*args
, is_fatal
=lambda idx
: idx
== 0)
62 def _resolve_fragments(self
, fragments
, ctx
):
63 fragments
= fragments(ctx
) if callable(fragments
) else fragments
64 return [next(iter(fragments
))] if self
.params
.get('test') else fragments
66 def _get_fragments(self
, fmt
, ctx
, extra_query
):
67 fragment_base_url
= fmt
.get('fragment_base_url')
68 fragments
= self
._resolve
_fragments
(fmt
['fragments'], ctx
)
71 for i
, fragment
in enumerate(fragments
):
73 if frag_index
<= ctx
['fragment_index']:
75 fragment_url
= fragment
.get('url')
77 assert fragment_base_url
78 fragment_url
= urljoin(fragment_base_url
, fragment
['path'])
80 fragment_url
= update_url_query(fragment_url
, extra_query
)
83 'frag_index': frag_index
,
84 'fragment_count': fragment
.get('fragment_count'),