Merge branch 'bilibili' of https://github.com/PeterDing/youtube-dl into PeterDing...
[youtube-dl] / youtube_dl / downloader / dash.py
index cbcee324df957c36cdcd00ef7e49a4c30bf0d949..41fc9cfc2b6b301bc09261c4b79668ca2395d544 100644 (file)
@@ -40,7 +40,8 @@ class DashSegmentsFD(FragmentFD):
         fragment_retries = self.params.get('fragment_retries', 0)
         skip_unavailable_fragments = self.params.get('skip_unavailable_fragments', True)
 
-        def append_url_to_file(target_url, tmp_filename, segment_name):
+        def process_segment(segment, tmp_filename, fatal):
+            target_url, segment_name = segment
             target_filename = '%s-%s' % (tmp_filename, segment_name)
             count = 0
             while count <= fragment_retries:
@@ -53,7 +54,7 @@ class DashSegmentsFD(FragmentFD):
                     down.close()
                     segments_filenames.append(target_sanitized)
                     break
-                except compat_urllib_error.HTTPError:
+                except compat_urllib_error.HTTPError as err:
                     # YouTube may often return 404 HTTP error for a fragment causing the
                     # whole download to fail. However if the same fragment is immediately
                     # retried with the same request data this usually succeeds (1-2 attemps
@@ -62,18 +63,26 @@ class DashSegmentsFD(FragmentFD):
                     # HTTP error.
                     count += 1
                     if count <= fragment_retries:
-                        self.report_retry_fragment(segment_name, count, fragment_retries)
+                        self.report_retry_fragment(err, segment_name, count, fragment_retries)
             if count > fragment_retries:
-                if skip_unavailable_fragments:
+                if not fatal:
                     self.report_skip_fragment(segment_name)
-                    return
+                    return True
                 self.report_error('giving up after %s fragment retries' % fragment_retries)
                 return False
-
-        if initialization_url:
-            append_url_to_file(initialization_url, ctx['tmpfilename'], 'Init')
-        for i, segment_url in enumerate(segment_urls):
-            append_url_to_file(segment_url, ctx['tmpfilename'], 'Seg%d' % i)
+            return True
+
+        segments_to_download = [(initialization_url, 'Init')] if initialization_url else []
+        segments_to_download.extend([
+            (segment_url, 'Seg%d' % i)
+            for i, segment_url in enumerate(segment_urls)])
+
+        for i, segment in enumerate(segments_to_download):
+            # In DASH, the first segment contains necessary headers to
+            # generate a valid MP4 file, so always abort for the first segment
+            fatal = i == 0 or not skip_unavailable_fragments
+            if not process_segment(segment, ctx['tmpfilename'], fatal):
+                return False
 
         self._finish_frag_download(ctx)