diff options
Diffstat (limited to 'youtube_dl/YoutubeDL.py')
| -rwxr-xr-x | youtube_dl/YoutubeDL.py | 52 | 
1 files changed, 37 insertions, 15 deletions
| diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index d65253882..50425b8d7 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -28,6 +28,7 @@ if os.name == 'nt':      import ctypes  from .compat import ( +    compat_basestring,      compat_cookiejar,      compat_expanduser,      compat_get_terminal_size, @@ -37,6 +38,7 @@ from .compat import (      compat_tokenize_tokenize,      compat_urllib_error,      compat_urllib_request, +    compat_urllib_request_DataHandler,  )  from .utils import (      ContentTooShortError, @@ -45,7 +47,9 @@ from .utils import (      DEFAULT_OUTTMPL,      determine_ext,      DownloadError, +    encode_compat_str,      encodeFilename, +    error_to_compat_str,      ExtractorError,      format_bytes,      formatSeconds, @@ -62,6 +66,7 @@ from .utils import (      SameFileError,      sanitize_filename,      sanitize_path, +    sanitized_Request,      std_headers,      subtitles_filename,      UnavailableVideoError, @@ -155,7 +160,7 @@ class YoutubeDL(object):      writethumbnail:    Write the thumbnail image to a file      write_all_thumbnails:  Write all thumbnail formats to files      writesubtitles:    Write the video subtitles to a file -    writeautomaticsub: Write the automatic subtitles to a file +    writeautomaticsub: Write the automatically generated subtitles to a file      allsubtitles:      Downloads all the subtitles of the video                         (requires writesubtitles or writeautomaticsub)      listsubtitles:     Lists all available subtitles for the video @@ -492,7 +497,7 @@ class YoutubeDL(object):                      tb = ''                      if hasattr(sys.exc_info()[1], 'exc_info') and sys.exc_info()[1].exc_info[0]:                          tb += ''.join(traceback.format_exception(*sys.exc_info()[1].exc_info)) -                    tb += compat_str(traceback.format_exc()) +                    tb += encode_compat_str(traceback.format_exc())                  else:                      tb_data = traceback.format_list(traceback.extract_stack())                      tb = ''.join(tb_data) @@ -571,7 +576,7 @@ class YoutubeDL(object):                                   if v is not None)              template_dict = collections.defaultdict(lambda: 'NA', template_dict) -            outtmpl = sanitize_path(self.params.get('outtmpl', DEFAULT_OUTTMPL)) +            outtmpl = self.params.get('outtmpl', DEFAULT_OUTTMPL)              tmpl = compat_expanduser(outtmpl)              filename = tmpl % template_dict              # Temporary fix for #4787 @@ -579,7 +584,7 @@ class YoutubeDL(object):              # to workaround encoding issues with subprocess on python2 @ Windows              if sys.version_info < (3, 0) and sys.platform == 'win32':                  filename = encodeFilename(filename, True).decode(preferredencoding()) -            return filename +            return sanitize_path(filename)          except ValueError as err:              self.report_error('Error in output template: ' + str(err) + ' (encoding: ' + repr(preferredencoding()) + ')')              return None @@ -671,14 +676,14 @@ class YoutubeDL(object):                      return self.process_ie_result(ie_result, download, extra_info)                  else:                      return ie_result -            except ExtractorError as de:  # An error we somewhat expected -                self.report_error(compat_str(de), de.format_traceback()) +            except ExtractorError as e:  # An error we somewhat expected +                self.report_error(compat_str(e), e.format_traceback())                  break              except MaxDownloadsReached:                  raise              except Exception as e:                  if self.params.get('ignoreerrors', False): -                    self.report_error(compat_str(e), tb=compat_str(traceback.format_exc())) +                    self.report_error(error_to_compat_str(e), tb=encode_compat_str(traceback.format_exc()))                      break                  else:                      raise @@ -832,6 +837,7 @@ class YoutubeDL(object):                                                        extra_info=extra)                  playlist_results.append(entry_result)              ie_result['entries'] = playlist_results +            self.to_screen('[download] Finished downloading playlist: %s' % playlist)              return ie_result          elif result_type == 'compat_list':              self.report_warning( @@ -936,7 +942,7 @@ class YoutubeDL(object):                      filter_parts.append(string)          def _remove_unused_ops(tokens): -            # Remove operators that we don't use and join them with the sourrounding strings +            # Remove operators that we don't use and join them with the surrounding strings              # for example: 'mp4' '-' 'baseline' '-' '16x9' is converted to 'mp4-baseline-16x9'              ALLOWED_OPS = ('/', '+', ',', '(', ')')              last_string, last_start, last_end, last_line = None, None, None, None @@ -1106,6 +1112,12 @@ class YoutubeDL(object):                                            'contain the video, try using '                                            '"-f %s+%s"' % (format_2, format_1))                          return +                    # Formats must be opposite (video+audio) +                    if formats_info[0].get('acodec') == 'none' and formats_info[1].get('acodec') == 'none': +                        self.report_error( +                            'Both formats %s and %s are video-only, you must specify "-f video+audio"' +                            % (format_1, format_2)) +                        return                      output_ext = (                          formats_info[0]['ext']                          if self.params.get('merge_output_format') is None @@ -1185,7 +1197,7 @@ class YoutubeDL(object):          return res      def _calc_cookies(self, info_dict): -        pr = compat_urllib_request.Request(info_dict['url']) +        pr = sanitized_Request(info_dict['url'])          self.cookiejar.add_cookie_header(pr)          return pr.get_header('Cookie') @@ -1232,13 +1244,20 @@ class YoutubeDL(object):              except (ValueError, OverflowError, OSError):                  pass +        subtitles = info_dict.get('subtitles') +        if subtitles: +            for _, subtitle in subtitles.items(): +                for subtitle_format in subtitle: +                    if 'ext' not in subtitle_format: +                        subtitle_format['ext'] = determine_ext(subtitle_format['url']).lower() +          if self.params.get('listsubtitles', False):              if 'automatic_captions' in info_dict:                  self.list_subtitles(info_dict['id'], info_dict.get('automatic_captions'), 'automatic captions') -            self.list_subtitles(info_dict['id'], info_dict.get('subtitles'), 'subtitles') +            self.list_subtitles(info_dict['id'], subtitles, 'subtitles')              return          info_dict['requested_subtitles'] = self.process_subtitles( -            info_dict['id'], info_dict.get('subtitles'), +            info_dict['id'], subtitles,              info_dict.get('automatic_captions'))          # We now pick which formats have to be downloaded @@ -1442,7 +1461,7 @@ class YoutubeDL(object):              if dn and not os.path.exists(dn):                  os.makedirs(dn)          except (OSError, IOError) as err: -            self.report_error('unable to create directory ' + compat_str(err)) +            self.report_error('unable to create directory ' + error_to_compat_str(err))              return          if self.params.get('writedescription', False): @@ -1493,7 +1512,7 @@ class YoutubeDL(object):                              sub_info['url'], info_dict['id'], note=False)                      except ExtractorError as err:                          self.report_warning('Unable to download subtitle for "%s": %s' % -                                            (sub_lang, compat_str(err.cause))) +                                            (sub_lang, error_to_compat_str(err.cause)))                          continue                  try:                      sub_filename = subtitles_filename(filename, sub_lang, sub_format) @@ -1862,6 +1881,8 @@ class YoutubeDL(object):      def urlopen(self, req):          """ Start an HTTP download """ +        if isinstance(req, compat_basestring): +            req = sanitized_Request(req)          return self._opener.open(req, timeout=self._socket_timeout)      def print_debug_header(self): @@ -1960,8 +1981,9 @@ class YoutubeDL(object):          debuglevel = 1 if self.params.get('debug_printtraffic') else 0          https_handler = make_HTTPS_handler(self.params, debuglevel=debuglevel)          ydlh = YoutubeDLHandler(self.params, debuglevel=debuglevel) +        data_handler = compat_urllib_request_DataHandler()          opener = compat_urllib_request.build_opener( -            proxy_handler, https_handler, cookie_processor, ydlh) +            proxy_handler, https_handler, cookie_processor, ydlh, data_handler)          # Delete the default user-agent header, which would otherwise apply in          # cases where our custom HTTP handler doesn't come into play @@ -2019,4 +2041,4 @@ class YoutubeDL(object):                                     (info_dict['extractor'], info_dict['id'], thumb_display_id, thumb_filename))                  except (compat_urllib_error.URLError, compat_http_client.HTTPException, socket.error) as err:                      self.report_warning('Unable to download thumbnail "%s": %s' % -                                        (t['url'], compat_str(err))) +                                        (t['url'], error_to_compat_str(err))) | 
