mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 14:45:14 +00:00 
			
		
		
		
	[youtube] Fix format sorting when using alternate clients
This commit is contained in:
		| @@ -2499,11 +2499,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|  |  | ||||||
|     def _extract_formats(self, streaming_data, video_id, player_url, is_live): |     def _extract_formats(self, streaming_data, video_id, player_url, is_live): | ||||||
|         itags, stream_ids = [], [] |         itags, stream_ids = [], [] | ||||||
|         itag_qualities = {} |         itag_qualities, res_qualities = {}, {} | ||||||
|         q = qualities([ |         q = qualities([ | ||||||
|             # "tiny" is the smallest video-only format. But some audio-only formats |             # Normally tiny is the smallest video-only formats. But | ||||||
|             # was also labeled "tiny". It is not clear if such formats still exist |             # audio-only formats with unknown quality may get tagged as tiny | ||||||
|             'tiny', 'audio_quality_low', 'audio_quality_medium', 'audio_quality_high',  # Audio only formats |             'tiny', | ||||||
|  |             'audio_quality_ultralow', 'audio_quality_low', 'audio_quality_medium', 'audio_quality_high',  # Audio only formats | ||||||
|             'small', 'medium', 'large', 'hd720', 'hd1080', 'hd1440', 'hd2160', 'hd2880', 'highres' |             'small', 'medium', 'large', 'hd720', 'hd1080', 'hd1440', 'hd2160', 'hd2880', 'highres' | ||||||
|         ]) |         ]) | ||||||
|         streaming_formats = traverse_obj(streaming_data, (..., ('formats', 'adaptiveFormats'), ...), default=[]) |         streaming_formats = traverse_obj(streaming_data, (..., ('formats', 'adaptiveFormats'), ...), default=[]) | ||||||
| @@ -2519,10 +2520,18 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             quality = fmt.get('quality') |             quality = fmt.get('quality') | ||||||
|  |             height = int_or_none(fmt.get('height')) | ||||||
|             if quality == 'tiny' or not quality: |             if quality == 'tiny' or not quality: | ||||||
|                 quality = fmt.get('audioQuality', '').lower() or quality |                 quality = fmt.get('audioQuality', '').lower() or quality | ||||||
|             if itag and quality: |             # The 3gp format (17) in android client has a quality of "small", | ||||||
|                 itag_qualities[itag] = quality |             # but is actually worse than other formats | ||||||
|  |             if itag == '17': | ||||||
|  |                 quality = 'tiny' | ||||||
|  |             if quality: | ||||||
|  |                 if itag: | ||||||
|  |                     itag_qualities[itag] = quality | ||||||
|  |                 if height: | ||||||
|  |                     res_qualities[height] = quality | ||||||
|             # FORMAT_STREAM_TYPE_OTF(otf=1) requires downloading the init fragment |             # FORMAT_STREAM_TYPE_OTF(otf=1) requires downloading the init fragment | ||||||
|             # (adding `&sq=0` to the URL) and parsing emsg box to determine the |             # (adding `&sq=0` to the URL) and parsing emsg box to determine the | ||||||
|             # number of fragment that would subsequently requested with (`&sq=N`) |             # number of fragment that would subsequently requested with (`&sq=N`) | ||||||
| @@ -2553,13 +2562,14 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|                 'filesize': int_or_none(fmt.get('contentLength')), |                 'filesize': int_or_none(fmt.get('contentLength')), | ||||||
|                 'format_id': itag, |                 'format_id': itag, | ||||||
|                 'format_note': ', '.join(filter(None, ( |                 'format_note': ', '.join(filter(None, ( | ||||||
|                     audio_track.get('displayName'), fmt.get('qualityLabel') or quality))), |                     audio_track.get('displayName'), | ||||||
|  |                     fmt.get('qualityLabel') or quality.replace('audio_quality_', '')))), | ||||||
|                 'fps': int_or_none(fmt.get('fps')), |                 'fps': int_or_none(fmt.get('fps')), | ||||||
|                 'height': int_or_none(fmt.get('height')), |                 'height': height, | ||||||
|                 'quality': q(quality), |                 'quality': q(quality), | ||||||
|                 'tbr': tbr, |                 'tbr': tbr, | ||||||
|                 'url': fmt_url, |                 'url': fmt_url, | ||||||
|                 'width': fmt.get('width'), |                 'width': int_or_none(fmt.get('width')), | ||||||
|                 'language': audio_track.get('id', '').split('.')[0], |                 'language': audio_track.get('id', '').split('.')[0], | ||||||
|             } |             } | ||||||
|             mime_mobj = re.match( |             mime_mobj = re.match( | ||||||
| @@ -2567,11 +2577,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|             if mime_mobj: |             if mime_mobj: | ||||||
|                 dct['ext'] = mimetype2ext(mime_mobj.group(1)) |                 dct['ext'] = mimetype2ext(mime_mobj.group(1)) | ||||||
|                 dct.update(parse_codecs(mime_mobj.group(2))) |                 dct.update(parse_codecs(mime_mobj.group(2))) | ||||||
|                 # The 3gp format in android client has a quality of "small", |  | ||||||
|                 # but is actually worse than all other formats |  | ||||||
|                 if dct['ext'] == '3gp': |  | ||||||
|                     dct['quality'] = q('tiny') |  | ||||||
|                     dct['preference'] = -10 |  | ||||||
|             no_audio = dct.get('acodec') == 'none' |             no_audio = dct.get('acodec') == 'none' | ||||||
|             no_video = dct.get('vcodec') == 'none' |             no_video = dct.get('vcodec') == 'none' | ||||||
|             if no_audio: |             if no_audio: | ||||||
| @@ -2591,11 +2596,16 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|         get_dash = not is_live and 'dash' not in skip_manifests and self.get_param('youtube_include_dash_manifest', True) |         get_dash = not is_live and 'dash' not in skip_manifests and self.get_param('youtube_include_dash_manifest', True) | ||||||
|         get_hls = 'hls' not in skip_manifests and self.get_param('youtube_include_hls_manifest', True) |         get_hls = 'hls' not in skip_manifests and self.get_param('youtube_include_hls_manifest', True) | ||||||
|  |  | ||||||
|  |         def guess_quality(f): | ||||||
|  |             for val, qdict in ((f.get('format_id'), itag_qualities), (f.get('height'), res_qualities)): | ||||||
|  |                 if val in qdict: | ||||||
|  |                     return q(qdict[val]) | ||||||
|  |             return -1 | ||||||
|  |  | ||||||
|         for sd in streaming_data: |         for sd in streaming_data: | ||||||
|             hls_manifest_url = get_hls and sd.get('hlsManifestUrl') |             hls_manifest_url = get_hls and sd.get('hlsManifestUrl') | ||||||
|             if hls_manifest_url: |             if hls_manifest_url: | ||||||
|                 for f in self._extract_m3u8_formats( |                 for f in self._extract_m3u8_formats(hls_manifest_url, video_id, 'mp4', fatal=False): | ||||||
|                         hls_manifest_url, video_id, 'mp4', fatal=False): |  | ||||||
|                     itag = self._search_regex( |                     itag = self._search_regex( | ||||||
|                         r'/itag/(\d+)', f['url'], 'itag', default=None) |                         r'/itag/(\d+)', f['url'], 'itag', default=None) | ||||||
|                     if itag in itags: |                     if itag in itags: | ||||||
| @@ -2603,19 +2613,18 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|                     if itag: |                     if itag: | ||||||
|                         f['format_id'] = itag |                         f['format_id'] = itag | ||||||
|                         itags.append(itag) |                         itags.append(itag) | ||||||
|  |                     f['quality'] = guess_quality(f) | ||||||
|                     yield f |                     yield f | ||||||
|  |  | ||||||
|             dash_manifest_url = get_dash and sd.get('dashManifestUrl') |             dash_manifest_url = get_dash and sd.get('dashManifestUrl') | ||||||
|             if dash_manifest_url: |             if dash_manifest_url: | ||||||
|                 for f in self._extract_mpd_formats( |                 for f in self._extract_mpd_formats(dash_manifest_url, video_id, fatal=False): | ||||||
|                         dash_manifest_url, video_id, fatal=False): |  | ||||||
|                     itag = f['format_id'] |                     itag = f['format_id'] | ||||||
|                     if itag in itags: |                     if itag in itags: | ||||||
|                         continue |                         continue | ||||||
|                     if itag: |                     if itag: | ||||||
|                         itags.append(itag) |                         itags.append(itag) | ||||||
|                     if itag in itag_qualities: |                     f['quality'] = guess_quality(f) | ||||||
|                         f['quality'] = q(itag_qualities[itag]) |  | ||||||
|                     filesize = int_or_none(self._search_regex( |                     filesize = int_or_none(self._search_regex( | ||||||
|                         r'/clen/(\d+)', f.get('fragment_base_url') |                         r'/clen/(\d+)', f.get('fragment_base_url') | ||||||
|                         or f['url'], 'file size', default=None)) |                         or f['url'], 'file size', default=None)) | ||||||
| @@ -2740,13 +2749,14 @@ class YoutubeIE(YoutubeBaseInfoExtractor): | |||||||
|                 self.raise_no_formats(reason, expected=True) |                 self.raise_no_formats(reason, expected=True) | ||||||
|  |  | ||||||
|         for f in formats: |         for f in formats: | ||||||
|             # TODO: detect if throttled |             if '&c=WEB&' in f['url'] and '&ratebypass=yes&' not in f['url']:  # throttled | ||||||
|             if '&n=' in f['url']:  # possibly throttled |  | ||||||
|                 f['source_preference'] = -10 |                 f['source_preference'] = -10 | ||||||
|                 # note = f.get('format_note') |                 note = f.get('format_note') | ||||||
|                 # f['format_note'] = f'{note} (throttled)' if note else '(throttled)' |                 f['format_note'] = f'{note} (throttled)' if note else '(throttled)' | ||||||
|  |  | ||||||
|         self._sort_formats(formats) |         # Source is given priority since formats that throttle are given lower source_preference | ||||||
|  |         # When throttling issue is fully fixed, remove this | ||||||
|  |         self._sort_formats(formats, ('quality', 'height', 'fps', 'source')) | ||||||
|  |  | ||||||
|         keywords = get_first(video_details, 'keywords', expected_type=list) or [] |         keywords = get_first(video_details, 'keywords', expected_type=list) or [] | ||||||
|         if not keywords and webpage: |         if not keywords and webpage: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 pukkandan
					pukkandan