From bbbb74fe781effaf1fd28acac04cb7cdab39e9bf Mon Sep 17 00:00:00 2001 From: Renee Margaret McConahy Date: Thu, 24 Dec 2015 12:00:22 -0500 Subject: [PATCH 1/3] Change format sorting. Prioritize video height and width above tbr. --- youtube_dl/extractor/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index 828f58f12..ad2020dee 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -811,11 +811,11 @@ class InfoExtractor(object): preference, f.get('language_preference') if f.get('language_preference') is not None else -1, f.get('quality') if f.get('quality') is not None else -1, + f.get('height') if f.get('height') is not None else -1, + f.get('width') if f.get('width') is not None else -1, f.get('tbr') if f.get('tbr') is not None else -1, f.get('filesize') if f.get('filesize') is not None else -1, f.get('vbr') if f.get('vbr') is not None else -1, - f.get('height') if f.get('height') is not None else -1, - f.get('width') if f.get('width') is not None else -1, ext_preference, f.get('abr') if f.get('abr') is not None else -1, audio_ext_preference, From 7c889a211a6aec81f8dd49a0317767cff5753191 Mon Sep 17 00:00:00 2001 From: Renee Margaret McConahy Date: Sat, 26 Dec 2015 10:28:22 -0500 Subject: [PATCH 2/3] Change format sorting for YouTube only. --- youtube_dl/extractor/common.py | 4 +-- youtube_dl/extractor/youtube.py | 63 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index ad2020dee..828f58f12 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -811,11 +811,11 @@ class InfoExtractor(object): preference, f.get('language_preference') if f.get('language_preference') is not None else -1, f.get('quality') if f.get('quality') is not None else -1, - f.get('height') if f.get('height') is not None else -1, - f.get('width') if f.get('width') is not None else -1, f.get('tbr') if f.get('tbr') is not None else -1, f.get('filesize') if f.get('filesize') is not None else -1, f.get('vbr') if f.get('vbr') is not None else -1, + f.get('height') if f.get('height') is not None else -1, + f.get('width') if f.get('width') is not None else -1, ext_preference, f.get('abr') if f.get('abr') is not None else -1, audio_ext_preference, diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index 4aac2cc03..f99ba6ff6 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -769,6 +769,69 @@ class YoutubeIE(YoutubeBaseInfoExtractor): """Indicate the download will use the RTMP protocol.""" self.to_screen('RTMP download detected') + def _sort_formats(self, formats, field_preference=None): + if not formats: + raise ExtractorError('No video formats found') + + def _formats_key(f): + # TODO remove the following workaround + from ..utils import determine_ext + if not f.get('ext') and 'url' in f: + f['ext'] = determine_ext(f['url']) + + if isinstance(field_preference, (list, tuple)): + return tuple(f.get(field) if f.get(field) is not None else -1 for field in field_preference) + + preference = f.get('preference') + if preference is None: + proto = f.get('protocol') + if proto is None: + proto = compat_urllib_parse_urlparse(f.get('url', '')).scheme + + preference = 0 if proto in ['http', 'https'] else -0.1 + if f.get('ext') in ['f4f', 'f4m']: # Not yet supported + preference -= 0.5 + + if f.get('vcodec') == 'none': # audio only + if self._downloader.params.get('prefer_free_formats'): + ORDER = ['aac', 'mp3', 'm4a', 'webm', 'ogg', 'opus'] + else: + ORDER = ['webm', 'opus', 'ogg', 'mp3', 'aac', 'm4a'] + ext_preference = 0 + try: + audio_ext_preference = ORDER.index(f['ext']) + except ValueError: + audio_ext_preference = -1 + else: + if self._downloader.params.get('prefer_free_formats'): + ORDER = ['flv', 'mp4', 'webm'] + else: + ORDER = ['webm', 'flv', 'mp4'] + try: + ext_preference = ORDER.index(f['ext']) + except ValueError: + ext_preference = -1 + audio_ext_preference = 0 + + return ( + preference, + f.get('language_preference') if f.get('language_preference') is not None else -1, + f.get('quality') if f.get('quality') is not None else -1, + f.get('height') if f.get('height') is not None else -1, + f.get('width') if f.get('width') is not None else -1, + f.get('tbr') if f.get('tbr') is not None else -1, + f.get('filesize') if f.get('filesize') is not None else -1, + f.get('vbr') if f.get('vbr') is not None else -1, + ext_preference, + f.get('abr') if f.get('abr') is not None else -1, + audio_ext_preference, + f.get('fps') if f.get('fps') is not None else -1, + f.get('filesize_approx') if f.get('filesize_approx') is not None else -1, + f.get('source_preference') if f.get('source_preference') is not None else -1, + f.get('format_id') if f.get('format_id') is not None else '', + ) + formats.sort(key=_formats_key) + def _signature_cache_id(self, example_sig): """ Return a string representation of a signature """ return '.'.join(compat_str(len(part)) for part in example_sig.split('.')) From 2e893a06ac0df05b7e721924b2cc56787bab5273 Mon Sep 17 00:00:00 2001 From: Renee Margaret McConahy Date: Tue, 29 Dec 2015 06:39:31 -0500 Subject: [PATCH 3/3] Use field_preference parameter. --- youtube_dl/extractor/youtube.py | 68 ++------------------------------- 1 file changed, 4 insertions(+), 64 deletions(-) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index f99ba6ff6..21a7ec35c 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -769,69 +769,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor): """Indicate the download will use the RTMP protocol.""" self.to_screen('RTMP download detected') - def _sort_formats(self, formats, field_preference=None): - if not formats: - raise ExtractorError('No video formats found') - - def _formats_key(f): - # TODO remove the following workaround - from ..utils import determine_ext - if not f.get('ext') and 'url' in f: - f['ext'] = determine_ext(f['url']) - - if isinstance(field_preference, (list, tuple)): - return tuple(f.get(field) if f.get(field) is not None else -1 for field in field_preference) - - preference = f.get('preference') - if preference is None: - proto = f.get('protocol') - if proto is None: - proto = compat_urllib_parse_urlparse(f.get('url', '')).scheme - - preference = 0 if proto in ['http', 'https'] else -0.1 - if f.get('ext') in ['f4f', 'f4m']: # Not yet supported - preference -= 0.5 - - if f.get('vcodec') == 'none': # audio only - if self._downloader.params.get('prefer_free_formats'): - ORDER = ['aac', 'mp3', 'm4a', 'webm', 'ogg', 'opus'] - else: - ORDER = ['webm', 'opus', 'ogg', 'mp3', 'aac', 'm4a'] - ext_preference = 0 - try: - audio_ext_preference = ORDER.index(f['ext']) - except ValueError: - audio_ext_preference = -1 - else: - if self._downloader.params.get('prefer_free_formats'): - ORDER = ['flv', 'mp4', 'webm'] - else: - ORDER = ['webm', 'flv', 'mp4'] - try: - ext_preference = ORDER.index(f['ext']) - except ValueError: - ext_preference = -1 - audio_ext_preference = 0 - - return ( - preference, - f.get('language_preference') if f.get('language_preference') is not None else -1, - f.get('quality') if f.get('quality') is not None else -1, - f.get('height') if f.get('height') is not None else -1, - f.get('width') if f.get('width') is not None else -1, - f.get('tbr') if f.get('tbr') is not None else -1, - f.get('filesize') if f.get('filesize') is not None else -1, - f.get('vbr') if f.get('vbr') is not None else -1, - ext_preference, - f.get('abr') if f.get('abr') is not None else -1, - audio_ext_preference, - f.get('fps') if f.get('fps') is not None else -1, - f.get('filesize_approx') if f.get('filesize_approx') is not None else -1, - f.get('source_preference') if f.get('source_preference') is not None else -1, - f.get('format_id') if f.get('format_id') is not None else '', - ) - formats.sort(key=_formats_key) - def _signature_cache_id(self, example_sig): """ Return a string representation of a signature """ return '.'.join(compat_str(len(part)) for part in example_sig.split('.')) @@ -1614,7 +1551,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor): if f.get('vcodec') != 'none': f['stretched_ratio'] = ratio - self._sort_formats(formats) + # YouTube reports total bitrate inaccurately for some videos. Compensate by prioritizing picture size. + self._sort_formats(formats, field_preference=('preference', 'language_preference', 'quality', 'height', 'width', + 'ext_preference', 'tbr', 'filesize', 'vbr', 'abr', 'audio_ext_preference', 'fps', 'filesize_approx', + 'source_preference')) return { 'id': video_id,