aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--youtube_dlc/YoutubeDL.py62
-rw-r--r--youtube_dlc/__init__.py1
-rw-r--r--youtube_dlc/options.py8
-rw-r--r--youtube_dlc/utils.py26
5 files changed, 86 insertions, 12 deletions
diff --git a/README.md b/README.md
index 04ad40f1a..0681869c7 100644
--- a/README.md
+++ b/README.md
@@ -420,6 +420,7 @@ I will add some memorable short links to the binaries so you can download them e
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
diff --git a/youtube_dlc/YoutubeDL.py b/youtube_dlc/YoutubeDL.py
index 8fe608fc9..cbfb03c7b 100644
--- a/youtube_dlc/YoutubeDL.py
+++ b/youtube_dlc/YoutubeDL.py
@@ -61,6 +61,7 @@ from .utils import (
expand_path,
ExtractorError,
format_bytes,
+ format_field,
formatSeconds,
GeoRestrictedError,
int_or_none,
@@ -2382,19 +2383,62 @@ class YoutubeDL(object):
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')
diff --git a/youtube_dlc/__init__.py b/youtube_dlc/__init__.py
index 4f57ac6a8..72dd40a56 100644
--- a/youtube_dlc/__init__.py
+++ b/youtube_dlc/__init__.py
@@ -358,6 +358,7 @@ def _real_main(argv=None):
'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,
diff --git a/youtube_dlc/options.py b/youtube_dlc/options.py
index e85006a87..f2878e468 100644
--- a/youtube_dlc/options.py
+++ b/youtube_dlc/options.py
@@ -444,6 +444,14 @@ def parseOpts(overrideArguments=None):
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,
help=optparse.SUPPRESS_HELP)
diff --git a/youtube_dlc/utils.py b/youtube_dlc/utils.py
index d814eb2ac..8c2c377af 100644
--- a/youtube_dlc/utils.py
+++ b/youtube_dlc/utils.py
@@ -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