diff options
Diffstat (limited to 'youtube_dl/YoutubeDL.py')
| -rwxr-xr-x | youtube_dl/YoutubeDL.py | 95 | 
1 files changed, 59 insertions, 36 deletions
| diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 3cabfbc03..8c651cd52 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -24,9 +24,6 @@ import time  import tokenize  import traceback -if os.name == 'nt': -    import ctypes -  from .compat import (      compat_basestring,      compat_cookiejar, @@ -34,6 +31,7 @@ from .compat import (      compat_get_terminal_size,      compat_http_client,      compat_kwargs, +    compat_os_name,      compat_str,      compat_tokenize_tokenize,      compat_urllib_error, @@ -87,6 +85,7 @@ from .extractor import get_info_extractor, gen_extractors  from .downloader import get_suitable_downloader  from .downloader.rtmp import rtmpdump_version  from .postprocessor import ( +    FFmpegFixupM3u8PP,      FFmpegFixupM4aPP,      FFmpegFixupStretchedPP,      FFmpegMergerPP, @@ -95,6 +94,9 @@ from .postprocessor import (  )  from .version import __version__ +if compat_os_name == 'nt': +    import ctypes +  class YoutubeDL(object):      """YoutubeDL class. @@ -450,7 +452,7 @@ class YoutubeDL(object):      def to_console_title(self, message):          if not self.params.get('consoletitle', False):              return -        if os.name == 'nt' and ctypes.windll.kernel32.GetConsoleWindow(): +        if compat_os_name == 'nt' and ctypes.windll.kernel32.GetConsoleWindow():              # c_wchar_p() might not be necessary if `message` is              # already of type unicode()              ctypes.windll.kernel32.SetConsoleTitleW(ctypes.c_wchar_p(message)) @@ -521,7 +523,7 @@ class YoutubeDL(object):          else:              if self.params.get('no_warnings'):                  return -            if not self.params.get('no_color') and self._err_file.isatty() and os.name != 'nt': +            if not self.params.get('no_color') and self._err_file.isatty() and compat_os_name != 'nt':                  _msg_header = '\033[0;33mWARNING:\033[0m'              else:                  _msg_header = 'WARNING:' @@ -533,7 +535,7 @@ class YoutubeDL(object):          Do the same as trouble, but prefixes the message with 'ERROR:', colored          in red if stderr is a tty file.          ''' -        if not self.params.get('no_color') and self._err_file.isatty() and os.name != 'nt': +        if not self.params.get('no_color') and self._err_file.isatty() and compat_os_name != 'nt':              _msg_header = '\033[0;31mERROR:\033[0m'          else:              _msg_header = 'ERROR:' @@ -566,7 +568,7 @@ class YoutubeDL(object):                  elif template_dict.get('height'):                      template_dict['resolution'] = '%sp' % template_dict['height']                  elif template_dict.get('width'): -                    template_dict['resolution'] = '?x%d' % template_dict['width'] +                    template_dict['resolution'] = '%dx?' % template_dict['width']              sanitize = lambda k, v: sanitize_filename(                  compat_str(v), @@ -605,12 +607,12 @@ class YoutubeDL(object):              if rejecttitle:                  if re.search(rejecttitle, title, re.IGNORECASE):                      return '"' + title + '" title matched reject pattern "' + rejecttitle + '"' -        date = info_dict.get('upload_date', None) +        date = info_dict.get('upload_date')          if date is not None:              dateRange = self.params.get('daterange', DateRange())              if date not in dateRange:                  return '%s upload date is not in range %s' % (date_from_str(date).isoformat(), dateRange) -        view_count = info_dict.get('view_count', None) +        view_count = info_dict.get('view_count')          if view_count is not None:              min_views = self.params.get('min_views')              if min_views is not None and view_count < min_views: @@ -747,18 +749,18 @@ class YoutubeDL(object):                  new_result, download=download, extra_info=extra_info)          elif result_type == 'playlist' or result_type == 'multi_video':              # We process each entry in the playlist -            playlist = ie_result.get('title', None) or ie_result.get('id', None) +            playlist = ie_result.get('title') or ie_result.get('id')              self.to_screen('[download] Downloading playlist: %s' % playlist)              playlist_results = []              playliststart = self.params.get('playliststart', 1) - 1 -            playlistend = self.params.get('playlistend', None) +            playlistend = self.params.get('playlistend')              # For backwards compatibility, interpret -1 as whole list              if playlistend == -1:                  playlistend = None -            playlistitems_str = self.params.get('playlist_items', None) +            playlistitems_str = self.params.get('playlist_items')              playlistitems = None              if playlistitems_str is not None:                  def iter_playlistitems(format): @@ -782,7 +784,7 @@ class YoutubeDL(object):                      entries = ie_entries[playliststart:playlistend]                  n_entries = len(entries)                  self.to_screen( -                    "[%s] playlist %s: Collected %d video ids (downloading %d of them)" % +                    '[%s] playlist %s: Collected %d video ids (downloading %d of them)' %                      (ie_result['extractor'], playlist, n_all_entries, n_entries))              elif isinstance(ie_entries, PagedList):                  if playlistitems: @@ -796,7 +798,7 @@ class YoutubeDL(object):                          playliststart, playlistend)                  n_entries = len(entries)                  self.to_screen( -                    "[%s] playlist %s: Downloading %d videos" % +                    '[%s] playlist %s: Downloading %d videos' %                      (ie_result['extractor'], playlist, n_entries))              else:  # iterable                  if playlistitems: @@ -807,7 +809,7 @@ class YoutubeDL(object):                          ie_entries, playliststart, playlistend))                  n_entries = len(entries)                  self.to_screen( -                    "[%s] playlist %s: Downloading %d videos" % +                    '[%s] playlist %s: Downloading %d videos' %                      (ie_result['extractor'], playlist, n_entries))              if self.params.get('playlistreverse', False): @@ -1232,6 +1234,10 @@ class YoutubeDL(object):                  if t.get('id') is None:                      t['id'] = '%d' % i +        if self.params.get('list_thumbnails'): +            self.list_thumbnails(info_dict) +            return +          if thumbnails and 'thumbnail' not in info_dict:              info_dict['thumbnail'] = thumbnails[-1]['url'] @@ -1333,15 +1339,11 @@ class YoutubeDL(object):          if self.params.get('listformats'):              self.list_formats(info_dict)              return -        if self.params.get('list_thumbnails'): -            self.list_thumbnails(info_dict) -            return          req_format = self.params.get('format')          if req_format is None:              req_format_list = []              if (self.params.get('outtmpl', DEFAULT_OUTTMPL) != '-' and -                    info_dict['extractor'] in ['youtube', 'ted'] and                      not info_dict.get('is_live')):                  merger = FFmpegMergerPP(self)                  if merger.available and merger.can_merge(): @@ -1632,12 +1634,14 @@ class YoutubeDL(object):                  self.report_error('content too short (expected %s bytes and served %s)' % (err.expected, err.downloaded))                  return -            if success: +            if success and filename != '-':                  # Fixup content                  fixup_policy = self.params.get('fixup')                  if fixup_policy is None:                      fixup_policy = 'detect_or_warn' +                INSTALL_FFMPEG_MESSAGE = 'Install ffmpeg or avconv to fix this automatically.' +                  stretched_ratio = info_dict.get('stretched_ratio')                  if stretched_ratio is not None and stretched_ratio != 1:                      if fixup_policy == 'warn': @@ -1650,15 +1654,18 @@ class YoutubeDL(object):                              info_dict['__postprocessors'].append(stretched_pp)                          else:                              self.report_warning( -                                '%s: Non-uniform pixel ratio (%s). Install ffmpeg or avconv to fix this automatically.' % ( -                                    info_dict['id'], stretched_ratio)) +                                '%s: Non-uniform pixel ratio (%s). %s' +                                % (info_dict['id'], stretched_ratio, INSTALL_FFMPEG_MESSAGE))                      else:                          assert fixup_policy in ('ignore', 'never') -                if info_dict.get('requested_formats') is None and info_dict.get('container') == 'm4a_dash': +                if (info_dict.get('requested_formats') is None and +                        info_dict.get('container') == 'm4a_dash'):                      if fixup_policy == 'warn': -                        self.report_warning('%s: writing DASH m4a. Only some players support this container.' % ( -                            info_dict['id'])) +                        self.report_warning( +                            '%s: writing DASH m4a. ' +                            'Only some players support this container.' +                            % info_dict['id'])                      elif fixup_policy == 'detect_or_warn':                          fixup_pp = FFmpegFixupM4aPP(self)                          if fixup_pp.available: @@ -1666,8 +1673,27 @@ class YoutubeDL(object):                              info_dict['__postprocessors'].append(fixup_pp)                          else:                              self.report_warning( -                                '%s: writing DASH m4a. Only some players support this container. Install ffmpeg or avconv to fix this automatically.' % ( -                                    info_dict['id'])) +                                '%s: writing DASH m4a. ' +                                'Only some players support this container. %s' +                                % (info_dict['id'], INSTALL_FFMPEG_MESSAGE)) +                    else: +                        assert fixup_policy in ('ignore', 'never') + +                if (info_dict.get('protocol') == 'm3u8_native' or +                        info_dict.get('protocol') == 'm3u8' and +                        self.params.get('hls_prefer_native')): +                    if fixup_policy == 'warn': +                        self.report_warning('%s: malformated aac bitstream.' % ( +                            info_dict['id'])) +                    elif fixup_policy == 'detect_or_warn': +                        fixup_pp = FFmpegFixupM3u8PP(self) +                        if fixup_pp.available: +                            info_dict.setdefault('__postprocessors', []) +                            info_dict['__postprocessors'].append(fixup_pp) +                        else: +                            self.report_warning( +                                '%s: malformated aac bitstream. %s' +                                % (info_dict['id'], INSTALL_FFMPEG_MESSAGE))                      else:                          assert fixup_policy in ('ignore', 'never') @@ -1798,7 +1824,7 @@ class YoutubeDL(object):              else:                  res = '%sp' % format['height']          elif format.get('width') is not None: -            res = '?x%d' % format['width'] +            res = '%dx?' % format['width']          else:              res = default          return res @@ -1831,7 +1857,9 @@ class YoutubeDL(object):          if fdict.get('vbr') is not None:              res += '%4dk' % fdict['vbr']          if fdict.get('fps') is not None: -            res += ', %sfps' % fdict['fps'] +            if res: +                res += ', ' +            res += '%sfps' % fdict['fps']          if fdict.get('acodec') is not None:              if res:                  res += ', ' @@ -1874,13 +1902,8 @@ class YoutubeDL(object):      def list_thumbnails(self, info_dict):          thumbnails = info_dict.get('thumbnails')          if not thumbnails: -            tn_url = info_dict.get('thumbnail') -            if tn_url: -                thumbnails = [{'id': '0', 'url': tn_url}] -            else: -                self.to_screen( -                    '[info] No thumbnails present for %s' % info_dict['id']) -                return +            self.to_screen('[info] No thumbnails present for %s' % info_dict['id']) +            return          self.to_screen(              '[info] Thumbnails for %s:' % info_dict['id']) | 
