format selection by bitrate (vbr>123) appears to be broken #27058

Open
opened 2026-02-21 14:37:20 -05:00 by deekerman · 8 comments
Owner

Originally created by @wellsyw on GitHub (Feb 10, 2025).

Checklist

  • I'm reporting a broken site support issue
  • I've verified that I'm running youtube-dl version 2021.12.17
  • I've checked that all provided URLs are alive and playable in a browser
  • I've checked that all URLs and arguments with special characters are properly quoted or escaped
  • I've searched the bugtracker for similar bug reports including closed ones
  • I've read bugs section in FAQ

Verbose log

D:\ffmpeg-bin>youtube-dl -F eU4NVFsnhg8
[youtube] eU4NVFsnhg8: Downloading webpage
[youtube] eU4NVFsnhg8: Downloading TVHTML5 API JSON
[info] Available formats for eU4NVFsnhg8:
format code  extension  resolution note
251-drc      webm       audio only audio_quality_medium  118k , webm_dash container, opus  (48000Hz), 507.27MiB
251          webm       audio only audio_quality_medium  118k , webm_dash container, opus  (48000Hz), 509.79MiB
140          m4a        audio only audio_quality_medium  129k , m4a_dash container, mp4a.40.2 (44100Hz), 555.63MiB
140-drc      m4a        audio only audio_quality_medium  129k , m4a_dash container, mp4a.40.2 (44100Hz), 555.63MiB
160          mp4        256x144    144p  120k , mp4_dash container, avc1.4d400c, 30fps, video only, 516.86MiB
243          webm       640x360    360p  440k , webm_dash container, vp9, 30fps, video only, 1.84GiB
134          mp4        640x360    360p  584k , mp4_dash container, avc1.4d401e, 30fps, video only, 2.45GiB
136          mp4        1280x720   720p 2187k , mp4_dash container, avc1.64001f, 30fps, video only, 9.17GiB
18           mp4        640x360    360p  712k , avc1.42001E, 30fps, mp4a.40.2 (44100Hz) (best)

D:\ffmpeg-bin>youtube-dl -v -f "136[vbr>800]+140" eU4NVFsnhg8
[debug] System config: []
[debug] User config: []
[debug] Custom config: []
[debug] Command-line args: ['-v', '-f', '136[vbr>800]+140', 'eU4NVFsnhg8']
[debug] Encodings: locale cp1252, fs mbcs, out cp850, pref cp1252
[debug] youtube-dl version 2025.02.07 [711e72c29] (single file build)
[debug] ** This version was built from the latest master code at https://github.com/ytdl-org/youtube-dl.
[debug] ** For support, visit the main site.
[debug] Python 3.4.4 (CPython AMD64 32bit) - Windows-10-10.0.22621 - OpenSSL 1.0.2d 9 Jul 2015
[debug] exe versions: ffmpeg n5.1.6-9-gdcdfd7fb62-20241109, ffprobe n5.1.6-9-gdcdfd7fb62-20241109
[debug] Proxy map: {}
[youtube] eU4NVFsnhg8: Downloading webpage
[youtube] eU4NVFsnhg8: Downloading TVHTML5 API JSON
[debug] [youtube] Decrypted nsig OkcttjHjr5dCOAIQ => hZR2vNaM02p0Mg
[debug] [youtube] Decrypted nsig t4nZTSgjVyqH7cDm => SClZOjSMp7mEHw
ERROR: requested format not available
Traceback (most recent call last):
  File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 879, in wrapper
  File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 986, in __extract_info
  File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 1020, in process_ie_result
  File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 1856, in process_video_result
youtube_dl.utils.ExtractorError: requested format not available

Description

-f 136[vbr>800]+140 should match the available video format (it is 2187 kbps), shouldn't it? Yet it doesn't. 136[vbr<800] doesn't give a match either.

The same command-line works in yt-dlp, it seems.

Originally created by @wellsyw on GitHub (Feb 10, 2025). <!-- ###################################################################### WARNING! IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN ISSUE CLOSED AS INCOMPLETE ###################################################################### --> ## Checklist <!-- Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl: - First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.12.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED. - Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser. - Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape. - Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates. - Read bugs section in FAQ: http://yt-dl.org/reporting - Finally, put x into all relevant boxes (like this [x]) --> - [X] I'm reporting a broken site support issue - [X] I've verified that I'm running youtube-dl version **2021.12.17** - [X] I've checked that all provided URLs are alive and playable in a browser - [X] I've checked that all URLs and arguments with special characters are properly quoted or escaped - [X] I've searched the bugtracker for similar bug reports including closed ones - [X] I've read bugs section in FAQ ## Verbose log <!-- Provide the complete verbose output of youtube-dl that clearly demonstrates the problem. Add the `-v` flag to your command line you run youtube-dl with (`youtube-dl -v <your command line>`), copy the WHOLE output and insert it below. It should look similar to this: [debug] System config: [] [debug] User config: [] [debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj'] [debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251 [debug] youtube-dl version 2021.12.17 [debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2 [debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4 [debug] Proxy map: {} <more lines> --> ``` D:\ffmpeg-bin>youtube-dl -F eU4NVFsnhg8 [youtube] eU4NVFsnhg8: Downloading webpage [youtube] eU4NVFsnhg8: Downloading TVHTML5 API JSON [info] Available formats for eU4NVFsnhg8: format code extension resolution note 251-drc webm audio only audio_quality_medium 118k , webm_dash container, opus (48000Hz), 507.27MiB 251 webm audio only audio_quality_medium 118k , webm_dash container, opus (48000Hz), 509.79MiB 140 m4a audio only audio_quality_medium 129k , m4a_dash container, mp4a.40.2 (44100Hz), 555.63MiB 140-drc m4a audio only audio_quality_medium 129k , m4a_dash container, mp4a.40.2 (44100Hz), 555.63MiB 160 mp4 256x144 144p 120k , mp4_dash container, avc1.4d400c, 30fps, video only, 516.86MiB 243 webm 640x360 360p 440k , webm_dash container, vp9, 30fps, video only, 1.84GiB 134 mp4 640x360 360p 584k , mp4_dash container, avc1.4d401e, 30fps, video only, 2.45GiB 136 mp4 1280x720 720p 2187k , mp4_dash container, avc1.64001f, 30fps, video only, 9.17GiB 18 mp4 640x360 360p 712k , avc1.42001E, 30fps, mp4a.40.2 (44100Hz) (best) D:\ffmpeg-bin>youtube-dl -v -f "136[vbr>800]+140" eU4NVFsnhg8 [debug] System config: [] [debug] User config: [] [debug] Custom config: [] [debug] Command-line args: ['-v', '-f', '136[vbr>800]+140', 'eU4NVFsnhg8'] [debug] Encodings: locale cp1252, fs mbcs, out cp850, pref cp1252 [debug] youtube-dl version 2025.02.07 [711e72c29] (single file build) [debug] ** This version was built from the latest master code at https://github.com/ytdl-org/youtube-dl. [debug] ** For support, visit the main site. [debug] Python 3.4.4 (CPython AMD64 32bit) - Windows-10-10.0.22621 - OpenSSL 1.0.2d 9 Jul 2015 [debug] exe versions: ffmpeg n5.1.6-9-gdcdfd7fb62-20241109, ffprobe n5.1.6-9-gdcdfd7fb62-20241109 [debug] Proxy map: {} [youtube] eU4NVFsnhg8: Downloading webpage [youtube] eU4NVFsnhg8: Downloading TVHTML5 API JSON [debug] [youtube] Decrypted nsig OkcttjHjr5dCOAIQ => hZR2vNaM02p0Mg [debug] [youtube] Decrypted nsig t4nZTSgjVyqH7cDm => SClZOjSMp7mEHw ERROR: requested format not available Traceback (most recent call last): File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 879, in wrapper File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 986, in __extract_info File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 1020, in process_ie_result File "D:\a\ytdl-nightly\ytdl-nightly\youtube_dl\YoutubeDL.py", line 1856, in process_video_result youtube_dl.utils.ExtractorError: requested format not available ``` ## Description <!-- Provide an explanation of your issue in an arbitrary form. Please make sure the description is worded well enough to be understood, see https://github.com/ytdl-org/youtube-dl#is-the-description-of-the-issue-itself-sufficient. Provide any additional information, suggested solution and as much context and examples as possible. If work on your issue requires account credentials please provide them or explain how one can obtain them. --> `-f 136[vbr>800]+140` should match the available video format (it is 2187 kbps), shouldn't it? Yet it doesn't. `136[vbr<800]` doesn't give a match either. The same command-line works in yt-dlp, it seems.
Author
Owner

@dirkf commented on GitHub (Feb 10, 2025):

vbr isn't separately extracted:

$ youtube-dl -v -f '136' -j 'eU4NVFsnhg8' | jq '.["tbr","vbr","abr"]'
[debug] System config: []
[debug] User config: []
[debug] Custom config: []
[debug] Command-line args: ['-v', '-f', '136', '-j', 'eU4NVFsnhg8']
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, pref UTF-8
[debug] youtube-dl version 2025.02.07 [711e72c29] (single file build)
[debug] ** This version was built from the latest master code at https://github.com/ytdl-org/youtube-dl.
[debug] ** For support, visit the main site.
[debug] Python 3.11.2 (CPython i686 32bit) - Linux-6.1.0-30-686-pae-i686-with-glibc2.36 - OpenSSL 3.0.15 3 Sep 2024 - glibc 2.36
[debug] exe versions: ffmpeg 5.1.6-0, ffprobe 5.1.6-0
[debug] Proxy map: {}
[debug] [youtube] Decrypted nsig rz6_P7jMCuiznSfy => cOgsMvow_Dzvjg
[debug] [youtube] Decrypted nsig hUF5U7GwB9V9xNsH => JtBVCEZ4YFc5wQ
2187.708
null
null
$ 

yt-dlp has this output:

2187.708
2187.708
0

As the emergency switch to the TVHTML5 API instead of extracting from the webpage has possibly broken all sorts of metadata, the extractor needs to be fully upgraded per #32905, which could incidentally resolve this discrepancy.

Currently you can use "136[tbr>800]+140" (perhaps counter-intuitive) or, to exclude a format 136 that confesses to a lower video bitrate, "136[vbr>?800]+140" (probably the same as "136+140" in reality).

@dirkf commented on GitHub (Feb 10, 2025): `vbr` isn't separately extracted: ```console $ youtube-dl -v -f '136' -j 'eU4NVFsnhg8' | jq '.["tbr","vbr","abr"]' [debug] System config: [] [debug] User config: [] [debug] Custom config: [] [debug] Command-line args: ['-v', '-f', '136', '-j', 'eU4NVFsnhg8'] [debug] Encodings: locale UTF-8, fs utf-8, out utf-8, pref UTF-8 [debug] youtube-dl version 2025.02.07 [711e72c29] (single file build) [debug] ** This version was built from the latest master code at https://github.com/ytdl-org/youtube-dl. [debug] ** For support, visit the main site. [debug] Python 3.11.2 (CPython i686 32bit) - Linux-6.1.0-30-686-pae-i686-with-glibc2.36 - OpenSSL 3.0.15 3 Sep 2024 - glibc 2.36 [debug] exe versions: ffmpeg 5.1.6-0, ffprobe 5.1.6-0 [debug] Proxy map: {} [debug] [youtube] Decrypted nsig rz6_P7jMCuiznSfy => cOgsMvow_Dzvjg [debug] [youtube] Decrypted nsig hUF5U7GwB9V9xNsH => JtBVCEZ4YFc5wQ 2187.708 null null $ ``` _yt-dlp_ has this output: ``` 2187.708 2187.708 0 ``` As the emergency switch to the TVHTML5 API instead of extracting from the webpage has possibly broken all sorts of metadata, the extractor needs to be fully upgraded per #32905, which could incidentally resolve this discrepancy. Currently you can use `"136[tbr>800]+140"` (perhaps counter-intuitive) or, to exclude a format 136 that confesses to a lower video bitrate, `"136[vbr>?800]+140"` (probably the same as `"136+140"` in reality).
Author
Owner

@dirkf commented on GitHub (Feb 10, 2025):

For historical reasons, the YT extractor here always sets tbr even though it might be appropriate to set vbr when acodec is 'none'andabrwhenvcodec is 'none'. yt-dlp does the same.

This change from current WIP in extractor/common.py sets vbr, similar to yt-dlp:

         for f in formats:
             # Automatically determine tbr when missing based on abr and vbr (improves
             # formats sorting in some cases)
-            if 'tbr' not in f and f.get('abr') is not None and f.get('vbr') is not None:
-                f['tbr'] = f['abr'] + f['vbr']
+            if 'tbr' not in f:
+                if f.get('abr') is not None and f.get('vbr') is not None:
+                    f['tbr'] = f['abr'] + f['vbr']
+            elif 'abr' not in f and f.get('vcodec') == 'none':
+                f['abr'] = f['tbr']
+            elif 'vbr' not in f and f.get('acodec') == 'none':
+                f['vbr'] = f['tbr']
 
         def _formats_key(f):
             # TODO remove the following workaround
@dirkf commented on GitHub (Feb 10, 2025): For historical reasons, the YT extractor here always sets `tbr` even though it might be appropriate to set `vbr` when `acodec` is 'none'` and `abr` when `vcodec` is 'none'`. _yt-dlp_ does the same. This change from current WIP in `extractor/common.py` sets `vbr`, similar to _yt-dlp_: ```diff for f in formats: # Automatically determine tbr when missing based on abr and vbr (improves # formats sorting in some cases) - if 'tbr' not in f and f.get('abr') is not None and f.get('vbr') is not None: - f['tbr'] = f['abr'] + f['vbr'] + if 'tbr' not in f: + if f.get('abr') is not None and f.get('vbr') is not None: + f['tbr'] = f['abr'] + f['vbr'] + elif 'abr' not in f and f.get('vcodec') == 'none': + f['abr'] = f['tbr'] + elif 'vbr' not in f and f.get('acodec') == 'none': + f['vbr'] = f['tbr'] def _formats_key(f): # TODO remove the following workaround ```
Author
Owner

@dirkf commented on GitHub (Feb 10, 2025):

But years ago, @glenn-slayden wrote:

The "tbr" value in the YouTube JSON information, also reported in the YouTubeDL -F option, contains the boilerplate values 1155 (for format 135) or 2200 and 2310 (for format 136) when the bitrate is actually unknown.

and concluded

I think it's more likely that YouTube computes the reported tbr value by using the data size field (which appears in the rightmost column) as a numerator. When the data size is not available for some reason, the tbr computation falls back to some kind of extremely crude approximation, possibly using values from a lookup table.

This would explain the clustering of false/invalid tbr values that I noted (i.e., "1155" or "2200"/"2310"). It would also suggest that whenever filesize is not reported, the 'tbr' value should be ignored, since in those cases we would possess just as much information as YouTube did, and so we can make our own approximations 'thank you very much.'

What does anyone (eg, @pukkandan, @coletdjnz, @bashonly) think?

  • Is this still valid?
  • Even if not, should the extractor set the appropriate bitrate key(s) according to what type of stream(s) are included?
  • Does a video-only stream have abr 0 as shown above for yt-dlp?
@dirkf commented on GitHub (Feb 10, 2025): But years ago, [@glenn-slayden wrote](https://github.com/ytdl-org/youtube-dl/issues/14143): >The "tbr" value in the YouTube JSON information, also reported in the YouTubeDL -F option, contains the boilerplate values 1155 (for format 135) or 2200 and 2310 (for format 136) when the bitrate is actually unknown. and [concluded](https://github.com/ytdl-org/youtube-dl/issues/14143#issuecomment-327866524) >I think it's more likely that YouTube computes the reported tbr value by using the data size field (which appears in the rightmost column) as a numerator. When the data size is not available for some reason, the tbr computation falls back to some kind of extremely crude approximation, possibly using values from a lookup table. > >This would explain the clustering of false/invalid tbr values that I noted (i.e., "1155" or "2200"/"2310"). It would also suggest that whenever filesize is not reported, the 'tbr' value should be ignored, since in those cases we would possess just as much information as YouTube did, and so we can make our own approximations 'thank you very much.' What does anyone (eg, @pukkandan, @coletdjnz, @bashonly) think? * Is this still valid? * Even if not, should the extractor set the appropriate bitrate key(s) according to what type of stream(s) are included? * Does a video-only stream have `abr` 0 as shown [above for _yt-dlp_](https://github.com/ytdl-org/youtube-dl/issues/33054#issuecomment-2648771037)?
Author
Owner

@fireattack commented on GitHub (Feb 10, 2025):

IIRC, YouTube never claims these values to be "average bitrate" but something like "max bitrate" in m3u8?

Anyway, yes they're still vastly inaccurate, particularly when comparing between different codecs. For example, an AVC format often has better (perceptional) quality than the VP9 one having higher "nominal" bitrate, because the actual file size of said AVC format is often (much) larger than the VP9 counterpart, and the compression efficiency of a newer codec isn't enough to compensate this sheer difference in real bitrate (and this fact totally affects how we sort the format to choose the best).

However I don't think there is a real solution to this. You usually can get enough formats that will real file sizes from various players, so that's something. But certain formats, like premium ones (616 etc.) don't have such format.

@fireattack commented on GitHub (Feb 10, 2025): IIRC, YouTube never claims these values to be "average bitrate" but something like "max bitrate" in m3u8? Anyway, yes they're still vastly inaccurate, particularly when comparing between different codecs. For example, an AVC format often has better (perceptional) quality than the VP9 one having higher "nominal" bitrate, because the actual file size of said AVC format is often (much) larger than the VP9 counterpart, and the compression efficiency of a newer codec isn't enough to compensate this sheer difference in *real* bitrate (and this fact totally affects how we sort the format to choose the best). However I don't think there is a real solution to this. You usually can get enough formats that will real file sizes from various players, so that's something. But certain formats, like premium ones (616 etc.) don't have such format.
Author
Owner

@pukkandan commented on GitHub (Feb 11, 2025):

  • Is this still valid?

Idk how youtube does the calculation. But either way, having this max/approx bitrate is better than extracting nothing imo. Especially in youtube-dl, if some formats lack tbr (while other formats have it), they'll get deprioritized below everything else, which is undesirable.

That's obvious, no? How could a video-only stream have a non-zero abr??

  • Even if not, should the extractor set the appropriate bitrate key(s) according to what type of stream(s) are included?

Why not have the core set it like in yt-dlp instead of burdening the extractor?

@pukkandan commented on GitHub (Feb 11, 2025): > * Is this still valid? Idk how youtube does the calculation. But either way, having this max/approx bitrate is better than extracting nothing imo. Especially in youtube-dl, if some formats lack `tbr` (while other formats have it), they'll get deprioritized below everything else, which is undesirable. > * Does a video-only stream have `abr` 0 as shown [above for _yt-dlp_](https://github.com/ytdl-org/youtube-dl/issues/33054#issuecomment-2648771037)? That's obvious, no? How could a video-only stream have a non-zero `abr`?? > * Even if not, should the extractor set the appropriate bitrate key(s) according to what type of stream(s) are included? Why not have the core set it like in yt-dlp instead of burdening the extractor?
Author
Owner

@dirkf commented on GitHub (Feb 11, 2025):

That's obvious, no? How could a video-only stream have a non-zero abr??

It could have no abr (None), as in the code above that would implement 'Why not ...?', rather than 0 abr.

@dirkf commented on GitHub (Feb 11, 2025): >That's obvious, no? How could a video-only stream have a non-zero abr?? It could have no `abr` (`None`), as in the [code above that would implement 'Why not ...?'](https://github.com/ytdl-org/youtube-dl/issues/33054#issuecomment-2649271711), rather than 0 `abr`.
Author
Owner

@pukkandan commented on GitHub (Feb 11, 2025):

None in infodict typically means "unknown". But we know that the abr is 0 when there is no audio stream. Is there any benefit to having it as None?

@pukkandan commented on GitHub (Feb 11, 2025): `None` in infodict typically means "unknown". But we know that the `abr` is `0` when there is no audio stream. Is there any benefit to having it as `None`?
Author
Owner

@dirkf commented on GitHub (Feb 11, 2025):

It seems more natural to have an empty value than one that could result from the presence of a stream whose bitrate has been rounded down to 0 or wrongly calculated. I grant that 0.49bit/s would be quite a specialist type of audio: RFC 1149, anyone?

@dirkf commented on GitHub (Feb 11, 2025): It seems more natural to have an empty value than one that could result from the presence of a stream whose bitrate has been rounded down to 0 or wrongly calculated. I grant that 0.49bit/s would be quite a specialist type of audio: RFC 1149, anyone?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/youtube-dl-ytdl-org#27058
No description provided.