]>
Commit | Line | Data |
---|---|---|
6800d337 | 1 | from __future__ import unicode_literals |
6800d337 | 2 | |
c43fe026 | 3 | from .fragment import FragmentFD |
e33baba0 | 4 | from ..compat import compat_urllib_error |
453a1617 | 5 | |
6800d337 | 6 | |
c43fe026 | 7 | class DashSegmentsFD(FragmentFD): |
6800d337 YCH |
8 | """ |
9 | Download segments in a DASH manifest | |
10 | """ | |
6800d337 | 11 | |
c43fe026 | 12 | FD_NAME = 'dashsegments' |
5bf3276e | 13 | |
c43fe026 | 14 | def real_download(self, filename, info_dict): |
86f4d14f S |
15 | segments = info_dict['fragments'][:1] if self.params.get( |
16 | 'test', False) else info_dict['fragments'] | |
5bf3276e | 17 | |
c43fe026 | 18 | ctx = { |
19 | 'filename': filename, | |
86f4d14f | 20 | 'total_frags': len(segments), |
c43fe026 | 21 | } |
5bf3276e | 22 | |
c43fe026 | 23 | self._prepare_and_start_frag_download(ctx) |
6800d337 | 24 | |
e33baba0 | 25 | fragment_retries = self.params.get('fragment_retries', 0) |
25afc2a7 | 26 | skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True) |
e33baba0 | 27 | |
75a24854 RA |
28 | frag_index = 0 |
29 | for i, segment in enumerate(segments): | |
30 | frag_index += 1 | |
3e0304fe | 31 | if frag_index <= ctx['fragment_index']: |
75a24854 | 32 | continue |
86f4d14f S |
33 | # In DASH, the first segment contains necessary headers to |
34 | # generate a valid MP4 file, so always abort for the first segment | |
75a24854 | 35 | fatal = i == 0 or not skip_unavailable_fragments |
e33baba0 S |
36 | count = 0 |
37 | while count <= fragment_retries: | |
38 | try: | |
75a24854 | 39 | success, frag_content = self._download_fragment(ctx, segment['url'], info_dict) |
e33baba0 S |
40 | if not success: |
41 | return False | |
75a24854 | 42 | self._append_fragment(ctx, frag_content) |
e33baba0 | 43 | break |
2e99cd30 | 44 | except compat_urllib_error.HTTPError as err: |
e33baba0 S |
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. | |
25afc2a7 S |
49 | # To be future-proof we will retry all fragments that fail with any |
50 | # HTTP error. | |
e33baba0 S |
51 | count += 1 |
52 | if count <= fragment_retries: | |
75a24854 | 53 | self.report_retry_fragment(err, frag_index, count, fragment_retries) |
e33baba0 | 54 | if count > fragment_retries: |
919cf1a6 | 55 | if not fatal: |
75a24854 RA |
56 | self.report_skip_fragment(frag_index) |
57 | continue | |
e33baba0 | 58 | self.report_error('giving up after %s fragment retries' % fragment_retries) |
c43fe026 | 59 | return False |
c43fe026 | 60 | |
61 | self._finish_frag_download(ctx) | |
62 | ||
6800d337 | 63 | return True |