diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 4d60be5bb..29cb3a7f0 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -1381,13 +1381,15 @@ class InfoExtractor(object): sort = {} for item in _get_sort_list(): - if item[:1] == "+": - sort.setdefault(item[1:], True) # Value = reverse? + item = item.split(":", 1) + lim = float(item[1]) if len(item)>1 else None + if item[0][:1] == "+": + sort.setdefault(item[0][1:], (-1, lim)) # item[key] = (Reverse for best, reverse again below this) else: - sort.setdefault(item, False) + sort.setdefault(item[0], (1, lim)) if self._downloader.params.get('verbose', False): self._downloader.to_screen('[debug] Formats sorted by: %s' - % [("+" + i) if sort[i] else i for i in sort]) + % ["".join(( ("+" if sort[i][0]<0 else ""), i, ":"+str(sort[i][1]) )) for i in sort] ) for f in formats: # Automatically determine tbr when missing based on abr and vbr (improves @@ -1465,15 +1467,37 @@ class InfoExtractor(object): 'ext_preference': ext_preference, 'audio_ext_preference': audio_ext_preference, 'codec_preference': codec_preference, - 'audio_codec_preference': audio_codec_preference} + 'audio_codec_preference': audio_codec_preference } - return tuple( - (-1 if field != 'format_id' and sort[field] else 1)*( - prefVars.get(field) - if prefVars.get(field) is not None - else (f.get(field) if f.get(field) is not None - else ('' if field == 'format_id' else -sort[field]))) - for field in sort) + def format_get_val(field): + return f.get(field) if prefVars.get(field) is None else prefVars.get(field) + + def format_get_preference(field): + val = format_get_val(field) + return ( + (0, f.get(field, '')) + if field == 'format_id' + else (-10, 0) + if val is None + else (0, sort[field][0]*val) + if sort[field][1] is None + else (0, -val) + if val==sort[field][1] and sort[field][0]<0 + else (0, -val) + if val>sort[field][1] + else (-1, val) + if sort[field][0]<0 + else (0, val) ) + + ''' # For DEBUGGING + if self._downloader.params.get('verbose', False): + for field in sort: + self._downloader.to_screen('[debug] %s[%s] = %s | Pref = %s' + %( field, format_get_val('format_id'), format_get_val(field), str(format_get_preference(field)) ) ) + self._downloader.to_screen('') + ''' #''' + + return tuple(format_get_preference(field) for field in sort ) formats.sort(key=_formats_key) diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 014fc6858..83e31112e 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -398,21 +398,28 @@ def parseOpts(overrideArguments=None): '--format-sort', action='store', dest='format_sort', metavar='FORMAT', default=None, help=( - 'Sort the formats by the fields given (e.g. height,width,+filesize). ' + 'Sort the formats by the fields given. ' 'Default order: preference, language_preference, quality, ' 'tbr, filesize, vbr, height, width, ' 'proto_preference, ext_preference, codec_preference, ' 'abr, audio_ext_preference, audio_codec_preference, ' - 'fps, filesize_approx, source_preference, format_id.' + 'fps, filesize_approx, source_preference, format_id. ' 'Prefix the field (except format_id) by a + to sort it in reverse. ' + 'Suffix the field with :value to give highest preference to "value". ' 'preference and language_preference will always have the highest priority ' - 'unless --format-sort-force is given')) + 'unless --format-sort-force is given. ' + 'Examples: 1) "-f bestvideo --format-sort +height:720,fps,+filesize" gets the video with ' + 'the smallest filesize with largest fps with ' + 'the smallest height>=720 (or largest height available if there is no such format). ' + '2) "-f bestvideo --format-sort height:720,proto_preference,tbr" gets the video with ' + 'largest bitrate with best protocol with ' + 'the largest height<=720 (or smallest height available if there is no such format)')) video_format.add_option( '--format-sort-force', action='store_true', dest='format_sort_force', metavar='FORMAT', default=False, help=( 'User specified sort order takes priority even over ' - 'preference, language_preference and quality')) + 'preference and language_preference')) video_format.add_option( '--all-formats', action='store_const', dest='format', const='all',