mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2024-10-31 22:55:26 +00:00
[downloader/dash] Add fragment retry capability
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 is usually enough) thus allowing to download the whole file successfully. So, we will retry all fragments that fail with 404 HTTP error for now.
This commit is contained in:
parent
721f26b821
commit
e33baba0dd
1 changed files with 32 additions and 10 deletions
|
@ -4,6 +4,7 @@ import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from .fragment import FragmentFD
|
from .fragment import FragmentFD
|
||||||
|
from ..compat import compat_urllib_error
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
sanitize_open,
|
sanitize_open,
|
||||||
encodeFilename,
|
encodeFilename,
|
||||||
|
@ -36,7 +37,13 @@ class DashSegmentsFD(FragmentFD):
|
||||||
|
|
||||||
segments_filenames = []
|
segments_filenames = []
|
||||||
|
|
||||||
def append_url_to_file(target_url, target_filename):
|
fragment_retries = self.params.get('fragment_retries', 0)
|
||||||
|
|
||||||
|
def append_url_to_file(target_url, tmp_filename, segment_name):
|
||||||
|
target_filename = '%s-%s' % (tmp_filename, segment_name)
|
||||||
|
count = 0
|
||||||
|
while count <= fragment_retries:
|
||||||
|
try:
|
||||||
success = ctx['dl'].download(target_filename, {'url': combine_url(base_url, target_url)})
|
success = ctx['dl'].download(target_filename, {'url': combine_url(base_url, target_url)})
|
||||||
if not success:
|
if not success:
|
||||||
return False
|
return False
|
||||||
|
@ -44,12 +51,27 @@ class DashSegmentsFD(FragmentFD):
|
||||||
ctx['dest_stream'].write(down.read())
|
ctx['dest_stream'].write(down.read())
|
||||||
down.close()
|
down.close()
|
||||||
segments_filenames.append(target_sanitized)
|
segments_filenames.append(target_sanitized)
|
||||||
|
break
|
||||||
|
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
|
||||||
|
# is usually enough) thus allowing to download the whole file successfully.
|
||||||
|
# So, we will retry all fragments that fail with 404 HTTP error for now.
|
||||||
|
if err.code != 404:
|
||||||
|
raise
|
||||||
|
# Retry fragment
|
||||||
|
count += 1
|
||||||
|
if count <= fragment_retries:
|
||||||
|
self.report_retry_fragment(segment_name, count, fragment_retries)
|
||||||
|
if count > fragment_retries:
|
||||||
|
self.report_error('giving up after %s fragment retries' % fragment_retries)
|
||||||
|
return False
|
||||||
|
|
||||||
if initialization_url:
|
if initialization_url:
|
||||||
append_url_to_file(initialization_url, ctx['tmpfilename'] + '-Init')
|
append_url_to_file(initialization_url, ctx['tmpfilename'], 'Init')
|
||||||
for i, segment_url in enumerate(segment_urls):
|
for i, segment_url in enumerate(segment_urls):
|
||||||
segment_filename = '%s-Seg%d' % (ctx['tmpfilename'], i)
|
append_url_to_file(segment_url, ctx['tmpfilename'], 'Seg%d' % i)
|
||||||
append_url_to_file(segment_url, segment_filename)
|
|
||||||
|
|
||||||
self._finish_frag_download(ctx)
|
self._finish_frag_download(ctx)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue