1 from __future__ 
import unicode_literals
 
   3 from .fragment 
import FragmentFD
 
   4 from ..compat 
import compat_urllib_error
 
  11 class DashSegmentsFD(FragmentFD
): 
  13     Download segments in a DASH manifest 
  16     FD_NAME 
= 'dashsegments' 
  18     def real_download(self
, filename
, info_dict
): 
  19         fragment_base_url 
= info_dict
.get('fragment_base_url') 
  20         fragments 
= info_dict
['fragments'][:1] if self
.params
.get( 
  21             'test', False) else info_dict
['fragments'] 
  25             'total_frags': len(fragments
), 
  28         self
._prepare
_and
_start
_frag
_download
(ctx
) 
  30         fragment_retries 
= self
.params
.get('fragment_retries', 0) 
  31         skip_unavailable_fragments 
= self
.params
.get('skip_unavailable_fragments', True) 
  34         for i
, fragment 
in enumerate(fragments
): 
  36             if frag_index 
<= ctx
['fragment_index']: 
  38             # In DASH, the first segment contains necessary headers to 
  39             # generate a valid MP4 file, so always abort for the first segment 
  40             fatal 
= i 
== 0 or not skip_unavailable_fragments
 
  42             while count 
<= fragment_retries
: 
  44                     fragment_url 
= fragment
.get('url') 
  46                         assert fragment_base_url
 
  47                         fragment_url 
= urljoin(fragment_base_url
, fragment
['path']) 
  48                     success
, frag_content 
= self
._download
_fragment
(ctx
, fragment_url
, info_dict
) 
  51                     self
._append
_fragment
(ctx
, frag_content
) 
  53                 except compat_urllib_error
.HTTPError 
as err
: 
  54                     # YouTube may often return 404 HTTP error for a fragment causing the 
  55                     # whole download to fail. However if the same fragment is immediately 
  56                     # retried with the same request data this usually succeeds (1-2 attempts 
  57                     # is usually enough) thus allowing to download the whole file successfully. 
  58                     # To be future-proof we will retry all fragments that fail with any 
  61                     if count 
<= fragment_retries
: 
  62                         self
.report_retry_fragment(err
, frag_index
, count
, fragment_retries
) 
  64                     # Don't retry fragment if error occurred during HTTP downloading 
  65                     # itself since it has own retry settings 
  67                         self
.report_skip_fragment(frag_index
) 
  71             if count 
> fragment_retries
: 
  73                     self
.report_skip_fragment(frag_index
) 
  75                 self
.report_error('giving up after %s fragment retries' % fragment_retries
) 
  78         self
._finish
_frag
_download
(ctx
)