1 from __future__
import unicode_literals
3 from .fragment
import FragmentFD
4 from ..compat
import compat_urllib_error
7 class DashSegmentsFD(FragmentFD
):
9 Download segments in a DASH manifest
12 FD_NAME
= 'dashsegments'
14 def real_download(self
, filename
, info_dict
):
15 segments
= info_dict
['fragments'][:1] if self
.params
.get(
16 'test', False) else info_dict
['fragments']
20 'total_frags': len(segments
),
23 self
._prepare
_and
_start
_frag
_download
(ctx
)
25 fragment_retries
= self
.params
.get('fragment_retries', 0)
26 skip_unavailable_fragments
= self
.params
.get('skip_unavailable_fragments', True)
29 for i
, segment
in enumerate(segments
):
31 if frag_index
<= ctx
['fragment_index']:
33 # In DASH, the first segment contains necessary headers to
34 # generate a valid MP4 file, so always abort for the first segment
35 fatal
= i
== 0 or not skip_unavailable_fragments
37 while count
<= fragment_retries
:
39 success
, frag_content
= self
._download
_fragment
(ctx
, segment
['url'], info_dict
)
42 self
._append
_fragment
(ctx
, frag_content
)
44 except compat_urllib_error
.HTTPError
as err
:
45 # YouTube may often return 404 HTTP error for a fragment causing the
46 # whole download to fail. However if the same fragment is immediately
47 # retried with the same request data this usually succeeds (1-2 attemps
48 # is usually enough) thus allowing to download the whole file successfully.
49 # To be future-proof we will retry all fragments that fail with any
52 if count
<= fragment_retries
:
53 self
.report_retry_fragment(err
, frag_index
, count
, fragment_retries
)
54 if count
> fragment_retries
:
56 self
.report_skip_fragment(frag_index
)
58 self
.report_error('giving up after %s fragment retries' % fragment_retries
)
61 self
._finish
_frag
_download
(ctx
)