mirror of
				https://gitlab.com/ytdl-org/youtube-dl.git
				synced 2025-11-04 10:57:07 -05:00 
			
		
		
		
	Add --list-thumbnails
This commit is contained in:
		@@ -52,6 +52,7 @@ from youtube_dl.utils import (
 | 
				
			|||||||
    urlencode_postdata,
 | 
					    urlencode_postdata,
 | 
				
			||||||
    version_tuple,
 | 
					    version_tuple,
 | 
				
			||||||
    xpath_with_ns,
 | 
					    xpath_with_ns,
 | 
				
			||||||
 | 
					    render_table,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -434,5 +435,15 @@ ffmpeg version 2.4.4 Copyright (c) 2000-2014 the FFmpeg ...'''), '2.4.4')
 | 
				
			|||||||
        self.assertTrue(is_html(  # UTF-32-LE
 | 
					        self.assertTrue(is_html(  # UTF-32-LE
 | 
				
			||||||
            b'\xFF\xFE\x00\x00<\x00\x00\x00h\x00\x00\x00t\x00\x00\x00m\x00\x00\x00l\x00\x00\x00>\x00\x00\x00\xe4\x00\x00\x00'))
 | 
					            b'\xFF\xFE\x00\x00<\x00\x00\x00h\x00\x00\x00t\x00\x00\x00m\x00\x00\x00l\x00\x00\x00>\x00\x00\x00\xe4\x00\x00\x00'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_render_table(self):
 | 
				
			||||||
 | 
					        self.assertEqual(
 | 
				
			||||||
 | 
					            render_table(
 | 
				
			||||||
 | 
					                ['a', 'bcd'],
 | 
				
			||||||
 | 
					                [[123, 4], [9999, 51]]),
 | 
				
			||||||
 | 
					            'a    bcd\n'
 | 
				
			||||||
 | 
					            '123  4\n'
 | 
				
			||||||
 | 
					            '9999 51')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    unittest.main()
 | 
					    unittest.main()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@ from .utils import (
 | 
				
			|||||||
    PostProcessingError,
 | 
					    PostProcessingError,
 | 
				
			||||||
    platform_name,
 | 
					    platform_name,
 | 
				
			||||||
    preferredencoding,
 | 
					    preferredencoding,
 | 
				
			||||||
 | 
					    render_table,
 | 
				
			||||||
    SameFileError,
 | 
					    SameFileError,
 | 
				
			||||||
    sanitize_filename,
 | 
					    sanitize_filename,
 | 
				
			||||||
    std_headers,
 | 
					    std_headers,
 | 
				
			||||||
@@ -221,6 +222,8 @@ class YoutubeDL(object):
 | 
				
			|||||||
                       youtube-dl servers for debugging.
 | 
					                       youtube-dl servers for debugging.
 | 
				
			||||||
    sleep_interval:    Number of seconds to sleep before each download.
 | 
					    sleep_interval:    Number of seconds to sleep before each download.
 | 
				
			||||||
    external_downloader:  Executable of the external downloader to call.
 | 
					    external_downloader:  Executable of the external downloader to call.
 | 
				
			||||||
 | 
					    listformats:       Print an overview of available video formats and exit.
 | 
				
			||||||
 | 
					    list_thumbnails:   Print a table of all thumbnails and exit.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    The following parameters are not used by YoutubeDL itself, they are used by
 | 
					    The following parameters are not used by YoutubeDL itself, they are used by
 | 
				
			||||||
@@ -916,9 +919,14 @@ class YoutubeDL(object):
 | 
				
			|||||||
            info_dict['playlist_index'] = None
 | 
					            info_dict['playlist_index'] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        thumbnails = info_dict.get('thumbnails')
 | 
					        thumbnails = info_dict.get('thumbnails')
 | 
				
			||||||
 | 
					        if thumbnails is None:
 | 
				
			||||||
 | 
					            thumbnail = info_dict.get('thumbnail')
 | 
				
			||||||
 | 
					            if thumbnail:
 | 
				
			||||||
 | 
					                thumbnails = [{'url': thumbnail}]
 | 
				
			||||||
        if thumbnails:
 | 
					        if thumbnails:
 | 
				
			||||||
            thumbnails.sort(key=lambda t: (
 | 
					            thumbnails.sort(key=lambda t: (
 | 
				
			||||||
                t.get('width'), t.get('height'), t.get('url')))
 | 
					                t.get('preference'), t.get('width'), t.get('height'),
 | 
				
			||||||
 | 
					                t.get('id'), t.get('url')))
 | 
				
			||||||
            for t in thumbnails:
 | 
					            for t in thumbnails:
 | 
				
			||||||
                if 'width' in t and 'height' in t:
 | 
					                if 'width' in t and 'height' in t:
 | 
				
			||||||
                    t['resolution'] = '%dx%d' % (t['width'], t['height'])
 | 
					                    t['resolution'] = '%dx%d' % (t['width'], t['height'])
 | 
				
			||||||
@@ -990,9 +998,12 @@ class YoutubeDL(object):
 | 
				
			|||||||
            # element in the 'formats' field in info_dict is info_dict itself,
 | 
					            # element in the 'formats' field in info_dict is info_dict itself,
 | 
				
			||||||
            # wich can't be exported to json
 | 
					            # wich can't be exported to json
 | 
				
			||||||
            info_dict['formats'] = formats
 | 
					            info_dict['formats'] = formats
 | 
				
			||||||
        if self.params.get('listformats', None):
 | 
					        if self.params.get('listformats'):
 | 
				
			||||||
            self.list_formats(info_dict)
 | 
					            self.list_formats(info_dict)
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					        if self.params.get('list_thumbnails'):
 | 
				
			||||||
 | 
					            self.list_thumbnails(info_dict)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        req_format = self.params.get('format')
 | 
					        req_format = self.params.get('format')
 | 
				
			||||||
        if req_format is None:
 | 
					        if req_format is None:
 | 
				
			||||||
@@ -1500,9 +1511,27 @@ class YoutubeDL(object):
 | 
				
			|||||||
        header_line = line({
 | 
					        header_line = line({
 | 
				
			||||||
            'format_id': 'format code', 'ext': 'extension',
 | 
					            'format_id': 'format code', 'ext': 'extension',
 | 
				
			||||||
            'resolution': 'resolution', 'format_note': 'note'}, idlen=idlen)
 | 
					            'resolution': 'resolution', 'format_note': 'note'}, idlen=idlen)
 | 
				
			||||||
        self.to_screen('[info] Available formats for %s:\n%s\n%s' %
 | 
					        self.to_screen(
 | 
				
			||||||
 | 
					            '[info] Available formats for %s:\n%s\n%s' %
 | 
				
			||||||
            (info_dict['id'], header_line, '\n'.join(formats_s)))
 | 
					            (info_dict['id'], header_line, '\n'.join(formats_s)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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] Thumbnails for %s:' % info_dict['id'])
 | 
				
			||||||
 | 
					        self.to_screen(render_table(
 | 
				
			||||||
 | 
					            ['ID', 'width', 'height', 'URL'],
 | 
				
			||||||
 | 
					            [[t['id'], t.get('width', 'unknown'), t.get('height', 'unknown'), t['url']] for t in thumbnails]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def urlopen(self, req):
 | 
					    def urlopen(self, req):
 | 
				
			||||||
        """ Start an HTTP download """
 | 
					        """ Start an HTTP download """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -331,6 +331,7 @@ def _real_main(argv=None):
 | 
				
			|||||||
        'call_home': opts.call_home,
 | 
					        'call_home': opts.call_home,
 | 
				
			||||||
        'sleep_interval': opts.sleep_interval,
 | 
					        'sleep_interval': opts.sleep_interval,
 | 
				
			||||||
        'external_downloader': opts.external_downloader,
 | 
					        'external_downloader': opts.external_downloader,
 | 
				
			||||||
 | 
					        'list_thumbnails': opts.list_thumbnails,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with YoutubeDL(ydl_opts) as ydl:
 | 
					    with YoutubeDL(ydl_opts) as ydl:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,7 +129,9 @@ class InfoExtractor(object):
 | 
				
			|||||||
                    something like "4234987", title "Dancing naked mole rats",
 | 
					                    something like "4234987", title "Dancing naked mole rats",
 | 
				
			||||||
                    and display_id "dancing-naked-mole-rats"
 | 
					                    and display_id "dancing-naked-mole-rats"
 | 
				
			||||||
    thumbnails:     A list of dictionaries, with the following entries:
 | 
					    thumbnails:     A list of dictionaries, with the following entries:
 | 
				
			||||||
 | 
					                        * "id" (optional, string) - Thumbnail format ID
 | 
				
			||||||
                        * "url"
 | 
					                        * "url"
 | 
				
			||||||
 | 
					                        * "preference" (optional, int) - quality of the image
 | 
				
			||||||
                        * "width" (optional, int)
 | 
					                        * "width" (optional, int)
 | 
				
			||||||
                        * "height" (optional, int)
 | 
					                        * "height" (optional, int)
 | 
				
			||||||
                        * "resolution" (optional, string "{width}x{height"},
 | 
					                        * "resolution" (optional, string "{width}x{height"},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .common import InfoExtractor
 | 
					from .common import InfoExtractor
 | 
				
			||||||
from ..utils import int_or_none
 | 
					from ..utils import (
 | 
				
			||||||
 | 
					    int_or_none,
 | 
				
			||||||
 | 
					    qualities,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestTubeIE(InfoExtractor):
 | 
					class TestTubeIE(InfoExtractor):
 | 
				
			||||||
@@ -46,13 +49,22 @@ class TestTubeIE(InfoExtractor):
 | 
				
			|||||||
        self._sort_formats(formats)
 | 
					        self._sort_formats(formats)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        duration = int_or_none(info.get('duration'))
 | 
					        duration = int_or_none(info.get('duration'))
 | 
				
			||||||
 | 
					        images = info.get('images')
 | 
				
			||||||
 | 
					        thumbnails = None
 | 
				
			||||||
 | 
					        preference = qualities(['mini', 'small', 'medium', 'large'])
 | 
				
			||||||
 | 
					        if images:
 | 
				
			||||||
 | 
					            thumbnails = [{
 | 
				
			||||||
 | 
					                'id': thumbnail_id,
 | 
				
			||||||
 | 
					                'url': img_url,
 | 
				
			||||||
 | 
					                'preference': preference(thumbnail_id)
 | 
				
			||||||
 | 
					            } for thumbnail_id, img_url in images.items()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            'id': video_id,
 | 
					            'id': video_id,
 | 
				
			||||||
            'display_id': display_id,
 | 
					            'display_id': display_id,
 | 
				
			||||||
            'title': info['title'],
 | 
					            'title': info['title'],
 | 
				
			||||||
            'description': info.get('summary'),
 | 
					            'description': info.get('summary'),
 | 
				
			||||||
            'thumbnail': info.get('images', {}).get('large'),
 | 
					            'thumbnails': thumbnails,
 | 
				
			||||||
            'uploader': info.get('show', {}).get('name'),
 | 
					            'uploader': info.get('show', {}).get('name'),
 | 
				
			||||||
            'uploader_id': info.get('show', {}).get('slug'),
 | 
					            'uploader_id': info.get('show', {}).get('slug'),
 | 
				
			||||||
            'duration': duration,
 | 
					            'duration': duration,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -614,10 +614,6 @@ def parseOpts(overrideArguments=None):
 | 
				
			|||||||
        '--write-annotations',
 | 
					        '--write-annotations',
 | 
				
			||||||
        action='store_true', dest='writeannotations', default=False,
 | 
					        action='store_true', dest='writeannotations', default=False,
 | 
				
			||||||
        help='write video annotations to a .annotation file')
 | 
					        help='write video annotations to a .annotation file')
 | 
				
			||||||
    filesystem.add_option(
 | 
					 | 
				
			||||||
        '--write-thumbnail',
 | 
					 | 
				
			||||||
        action='store_true', dest='writethumbnail', default=False,
 | 
					 | 
				
			||||||
        help='write thumbnail image to disk')
 | 
					 | 
				
			||||||
    filesystem.add_option(
 | 
					    filesystem.add_option(
 | 
				
			||||||
        '--load-info',
 | 
					        '--load-info',
 | 
				
			||||||
        dest='load_info_filename', metavar='FILE',
 | 
					        dest='load_info_filename', metavar='FILE',
 | 
				
			||||||
@@ -637,6 +633,16 @@ def parseOpts(overrideArguments=None):
 | 
				
			|||||||
        action='store_true', dest='rm_cachedir',
 | 
					        action='store_true', dest='rm_cachedir',
 | 
				
			||||||
        help='Delete all filesystem cache files')
 | 
					        help='Delete all filesystem cache files')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    thumbnail = optparse.OptionGroup(parser, 'Thumbnail images')
 | 
				
			||||||
 | 
					    thumbnail.add_option(
 | 
				
			||||||
 | 
					        '--write-thumbnail',
 | 
				
			||||||
 | 
					        action='store_true', dest='writethumbnail', default=False,
 | 
				
			||||||
 | 
					        help='write thumbnail image to disk')
 | 
				
			||||||
 | 
					    thumbnail.add_option(
 | 
				
			||||||
 | 
					        '--list-thumbnails',
 | 
				
			||||||
 | 
					        action='store_true', dest='list_thumbnails', default=False,
 | 
				
			||||||
 | 
					        help='Simulate and list all available thumbnail formats')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    postproc = optparse.OptionGroup(parser, 'Post-processing Options')
 | 
					    postproc = optparse.OptionGroup(parser, 'Post-processing Options')
 | 
				
			||||||
    postproc.add_option(
 | 
					    postproc.add_option(
 | 
				
			||||||
        '-x', '--extract-audio',
 | 
					        '-x', '--extract-audio',
 | 
				
			||||||
@@ -702,6 +708,7 @@ def parseOpts(overrideArguments=None):
 | 
				
			|||||||
    parser.add_option_group(selection)
 | 
					    parser.add_option_group(selection)
 | 
				
			||||||
    parser.add_option_group(downloader)
 | 
					    parser.add_option_group(downloader)
 | 
				
			||||||
    parser.add_option_group(filesystem)
 | 
					    parser.add_option_group(filesystem)
 | 
				
			||||||
 | 
					    parser.add_option_group(thumbnail)
 | 
				
			||||||
    parser.add_option_group(verbosity)
 | 
					    parser.add_option_group(verbosity)
 | 
				
			||||||
    parser.add_option_group(workarounds)
 | 
					    parser.add_option_group(workarounds)
 | 
				
			||||||
    parser.add_option_group(video_format)
 | 
					    parser.add_option_group(video_format)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1659,3 +1659,11 @@ def determine_protocol(info_dict):
 | 
				
			|||||||
        return 'f4m'
 | 
					        return 'f4m'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return compat_urllib_parse_urlparse(url).scheme
 | 
					    return compat_urllib_parse_urlparse(url).scheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def render_table(header_row, data):
 | 
				
			||||||
 | 
					    """ Render a list of rows, each as a list of values """
 | 
				
			||||||
 | 
					    table = [header_row] + data
 | 
				
			||||||
 | 
					    max_lens = [max(len(compat_str(v)) for v in col) for col in zip(*table)]
 | 
				
			||||||
 | 
					    format_str = ' '.join('%-' + compat_str(ml + 1) + 's' for ml in max_lens[:-1]) + '%s'
 | 
				
			||||||
 | 
					    return '\n'.join(format_str % tuple(row) for row in table)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user