]> jfr.im git - yt-dlp.git/commitdiff
Option to present -F output to a more tabular form
authorpukkandan <redacted>
Sun, 13 Dec 2020 14:29:09 +0000 (19:59 +0530)
committerpukkandan <redacted>
Mon, 4 Jan 2021 17:33:04 +0000 (23:03 +0530)
README.md
youtube_dlc/YoutubeDL.py
youtube_dlc/__init__.py
youtube_dlc/options.py
youtube_dlc/utils.py

index 04ad40f1a1697adb9c216b9f404f3ad599e4d950..0681869c7293468a72c5ca5153bcfc1a9c6d450d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -420,6 +420,7 @@ ## Video Format Options:
                                      one is requested
     -F, --list-formats               List all available formats of requested
                                      videos
+    --list-formats-as-table          Present the output of -F in a more tabular form
     --youtube-skip-dash-manifest     Do not download the DASH manifests and
                                      related data on YouTube videos
     --youtube-skip-hls-manifest      Do not download the HLS manifests and
index 8fe608fc968dfd20e86076e7631c1e3fb3755a00..cbfb03c7bc978e0e1d0041a758e53971c5922c7e 100644 (file)
@@ -61,6 +61,7 @@
     expand_path,
     ExtractorError,
     format_bytes,
+    format_field,
     formatSeconds,
     GeoRestrictedError,
     int_or_none,
@@ -2382,19 +2383,62 @@ def _format_note(self, fdict):
             res += '~' + format_bytes(fdict['filesize_approx'])
         return res
 
+    def _format_note_table(self, f):
+        def join_fields(*vargs):
+            return ', '.join((val for val in vargs if val != ''))
+
+        return join_fields(
+            'UNSUPPORTED' if f.get('ext') in ('f4f', 'f4m') else '',
+            format_field(f, 'language', '[%s]'),
+            format_field(f, 'format_note'),
+            format_field(f, 'container', ignore=(None, f.get('ext'))),
+            format_field(f, 'asr', '%5dHz'))
+
     def list_formats(self, info_dict):
         formats = info_dict.get('formats', [info_dict])
-        table = [
-            [f['format_id'], f['ext'], self.format_resolution(f), self._format_note(f)]
-            for f in formats
-            if f.get('preference') is None or f['preference'] >= -1000]
-        # if len(formats) > 1:
-        #     table[-1][-1] += (' ' if table[-1][-1] else '') + '(best*)'
+        new_format = self.params.get('listformats_table', False)
+        if new_format:
+            table = [
+                [
+                    format_field(f, 'format_id'),
+                    format_field(f, 'ext'),
+                    self.format_resolution(f),
+                    format_field(f, 'fps', '%d'),
+                    '|',
+                    format_field(f, 'filesize', ' %s', func=format_bytes) + format_field(f, 'filesize_approx', '~%s', func=format_bytes),
+                    format_field(f, 'tbr', '%4dk'),
+                    f.get('protocol').replace('http_dash_segments', 'dash').replace("native", "n"),
+                    '|',
+                    format_field(f, 'vcodec', default='unknown').replace('none', ''),
+                    format_field(f, 'vbr', '%4dk'),
+                    format_field(f, 'acodec', default='unknown').replace('none', ''),
+                    format_field(f, 'abr', '%3dk'),
+                    format_field(f, 'asr', '%5dHz'),
+                    self._format_note_table(f)]
+                for f in formats
+                if f.get('preference') is None or f['preference'] >= -1000]
+            header_line = ['ID', 'EXT', 'RESOLUTION', 'FPS', '|', ' FILESIZE', '  TBR', 'PROTO',
+                           '|', 'VCODEC', '  VBR', 'ACODEC', ' ABR', ' ASR', 'NOTE']
+        else:
+            table = [
+                [
+                    format_field(f, 'format_id'),
+                    format_field(f, 'ext'),
+                    self.format_resolution(f),
+                    self._format_note(f)]
+                for f in formats
+                if f.get('preference') is None or f['preference'] >= -1000]
+            header_line = ['format code', 'extension', 'resolution', 'note']
 
-        header_line = ['format code', 'extension', 'resolution', 'note']
+        # if len(formats) > 1:
+        #     table[-1][-1] += (' ' if table[-1][-1] else '') + '(best)'
         self.to_screen(
-            '[info] Available formats for %s:\n%s' %
-            (info_dict['id'], render_table(header_line, table)))
+            '[info] Available formats for %s:\n%s' % (info_dict['id'], render_table(
+                header_line,
+                table,
+                delim=new_format,
+                extraGap=(0 if new_format else 1),
+                hideEmpty=new_format)))
 
     def list_thumbnails(self, info_dict):
         thumbnails = info_dict.get('thumbnails')
index 4f57ac6a80254518bcd868197da046d798e8fde4..72dd40a56fd7dada59dd72381e5182c3f5907a29 100644 (file)
@@ -358,6 +358,7 @@ def parse_retries(retries):
         'allow_multiple_video_streams': opts.allow_multiple_video_streams,
         'allow_multiple_audio_streams': opts.allow_multiple_audio_streams,
         'listformats': opts.listformats,
+        'listformats_table': opts.listformats_table,
         'outtmpl': outtmpl,
         'autonumber_size': opts.autonumber_size,
         'autonumber_start': opts.autonumber_start,
index e85006a87130b86633cdc4b568b3ca858dffa8ca..f2878e4685c6eea515554b765b1da3c1ed347119 100644 (file)
@@ -443,6 +443,14 @@ def _comma_separated_values_options_callback(option, opt_str, value, parser):
         '-F', '--list-formats',
         action='store_true', dest='listformats',
         help='List all available formats of requested videos')
+    video_format.add_option(
+        '--list-formats-as-table',
+        action='store_true', dest='listformats_table', default=False,
+        help='Present the output of -F in a more tabular form')
+    video_format.add_option(
+        '--list-formats-old',
+        action='store_false', dest='listformats_table',
+        help=optparse.SUPPRESS_HELP)
     video_format.add_option(
         '--youtube-include-dash-manifest',
         action='store_true', dest='youtube_include_dash_manifest', default=True,
index d814eb2ac8b5e0ed56976ffda1e2c7f0b3453333..8c2c377af5463415dd4a31e2a025d4e47e52cfc6 100644 (file)
@@ -4315,11 +4315,25 @@ def determine_protocol(info_dict):
     return compat_urllib_parse_urlparse(url).scheme
 
 
-def render_table(header_row, data):
+def render_table(header_row, data, delim=False, extraGap=0, hideEmpty=False):
     """ Render a list of rows, each as a list of values """
+
+    def get_max_lens(table):
+        return [max(len(compat_str(v)) for v in col) for col in zip(*table)]
+
+    def filter_using_list(row, filterArray):
+        return [col for (take, col) in zip(filterArray, row) if take]
+
+    if hideEmpty:
+        max_lens = get_max_lens(data)
+        header_row = filter_using_list(header_row, max_lens)
+        data = [filter_using_list(row, max_lens) for row in data]
+
     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'
+    max_lens = get_max_lens(table)
+    if delim:
+        table = [header_row] + [['-' * ml for ml in max_lens]] + data
+    format_str = ' '.join('%-' + compat_str(ml + extraGap) + 's' for ml in max_lens[:-1]) + ' %s'
     return '\n'.join(format_str % tuple(row) for row in table)
 
 
@@ -5795,3 +5809,9 @@ def to_high_limit_path(path):
         return r'\\?\ '.rstrip() + os.path.abspath(path)
 
     return path
+
+def format_field(obj, field, template='%s', ignore=(None, ''), default='', func=None):
+    val = obj.get(field, default)
+    if func and val not in ignore:
+        val = func(val)
+    return template % val if val not in ignore else default