Compare commits

...

5 Commits

Author SHA1 Message Date
github-actions[bot]
891613b098 Release 2026.01.31
Created by: bashonly

:ci skip all
2026-01-31 23:52:50 +00:00
bashonly
9a9a6b6fe4
[cleanup] Misc (#15788)
Authored by: bashonly
2026-01-31 23:50:20 +00:00
bashonly
8eb794366e
[ie/youtube] Remove broken tv_embedded player client (#15787)
Authored by: bashonly
2026-01-31 23:25:21 +00:00
bashonly
c3674575fa
[ie/youtube] Remove broken ios_downgraded player client (#15786)
Closes #15782
Authored by: bashonly
2026-01-31 22:55:35 +00:00
bashonly
bb1c05752c
[ie/youtube] Add web_embedded fallback for android_vr client (#15785)
Closes #15751, Closes #15780
Authored by: bashonly
2026-01-31 22:48:41 +00:00
10 changed files with 36 additions and 59 deletions

View File

@ -26,6 +26,7 @@ concurrency:
jobs:
tests:
name: Challenge Tests
if: ${{ !contains(github.event.head_commit.message, ':ci skip') }}
permissions:
contents: read
runs-on: ${{ matrix.os }}

View File

@ -32,7 +32,7 @@ concurrency:
jobs:
tests:
name: Core Tests
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
if: ${{ !contains(github.event.head_commit.message, ':ci skip') }}
permissions:
contents: read
runs-on: ${{ matrix.os }}

View File

@ -10,7 +10,7 @@ concurrency:
jobs:
tests:
name: Core Test
if: ${{ !contains(github.event.head_commit.message, 'ci skip all') }}
if: ${{ !contains(github.event.head_commit.message, ':ci skip all') }}
permissions:
contents: read
runs-on: ubuntu-latest
@ -33,7 +33,7 @@ jobs:
python3 ./devscripts/run_tests.py --pytest-args '--reruns 2 --reruns-delay 3.0' core
check:
name: Code check
if: ${{ !contains(github.event.head_commit.message, 'ci skip all') }}
if: ${{ !contains(github.event.head_commit.message, ':ci skip all') }}
permissions:
contents: read
runs-on: ubuntu-latest

View File

@ -862,3 +862,5 @@ quietvoid
romainreignier
Sytm
zahlman
azdlonky
thematuu

View File

@ -4,6 +4,20 @@
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
-->
### 2026.01.31
#### Extractor changes
- **soop**: [Support subscription-only VODs](https://github.com/yt-dlp/yt-dlp/commit/d0bf3d0fc3455d411ae44c0a5dc974dd1481e3aa) ([#15523](https://github.com/yt-dlp/yt-dlp/issues/15523)) by [thematuu](https://github.com/thematuu)
- **unsupported**: [Update unsupported URLs](https://github.com/yt-dlp/yt-dlp/commit/bf5d8c2a663ac690711262aebc733c1b06a54b26) ([#15410](https://github.com/yt-dlp/yt-dlp/issues/15410)) by [bashonly](https://github.com/bashonly)
- **whyp**: [Extract more metadata](https://github.com/yt-dlp/yt-dlp/commit/0d8ee637e83d62edaf22aa85833a51c70d560389) ([#15757](https://github.com/yt-dlp/yt-dlp/issues/15757)) by [azdlonky](https://github.com/azdlonky)
- **youtube**
- [Add `web_embedded` fallback for `android_vr` client](https://github.com/yt-dlp/yt-dlp/commit/bb1c05752c288a81e0e281f1caf5395411936376) ([#15785](https://github.com/yt-dlp/yt-dlp/issues/15785)) by [bashonly](https://github.com/bashonly)
- [Remove broken `ios_downgraded` player client](https://github.com/yt-dlp/yt-dlp/commit/c3674575faa23b20e97be8b73f68b9f7b4cea9ab) ([#15786](https://github.com/yt-dlp/yt-dlp/issues/15786)) by [bashonly](https://github.com/bashonly)
- [Remove broken `tv_embedded` player client](https://github.com/yt-dlp/yt-dlp/commit/8eb794366eb69e7377ff88eed7929c00195c8d74) ([#15787](https://github.com/yt-dlp/yt-dlp/issues/15787)) by [bashonly](https://github.com/bashonly)
#### Misc. changes
- **cleanup**: Miscellaneous: [9a9a6b6](https://github.com/yt-dlp/yt-dlp/commit/9a9a6b6fe44a30458c1754ef064f354f04a84004) by [bashonly](https://github.com/bashonly)
### 2026.01.29
#### Core changes

View File

@ -1860,7 +1860,7 @@ The following extractors use this feature:
#### youtube
* `lang`: Prefer translated metadata (`title`, `description` etc) of this language code (case-sensitive). By default, the video primary language metadata is preferred, with a fallback to `en` translated. See [youtube/_base.py](https://github.com/yt-dlp/yt-dlp/blob/415b4c9f955b1a0391204bd24a7132590e7b3bdb/yt_dlp/extractor/youtube/_base.py#L402-L409) for the list of supported content language codes
* `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `ios_downgraded`, `android`, `android_vr`, `tv`, `tv_simply`, `tv_downgraded`, and `tv_embedded`. By default, `android_vr,ios_downgraded,web,web_safari` is used. If no JavaScript runtime/engine is available, then `android_vr,ios_downgraded` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only works if the video is embeddable. The `tv_embedded` and `web_creator` clients are added for age-restricted videos if account age-verification is required. Some clients, such as `web` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-ios`
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. By default, `android_vr,web,web_safari` is used. If no JavaScript runtime/engine is available, then only `android_vr` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web,web_safari` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable), and may be added as a fallback if `android_vr` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web`
* `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests
* `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp.

View File

@ -36,7 +36,6 @@ class Variant(enum.Enum):
tv = 'tv-player-ias.vflset/tv-player-ias.js'
tv_es6 = 'tv-player-es6.vflset/tv-player-es6.js'
phone = 'player-plasma-ias-phone-en_US.vflset/base.js'
tablet = 'player-plasma-ias-tablet-en_US.vflset/base.js'
@dataclasses.dataclass

View File

@ -271,34 +271,6 @@ INNERTUBE_CLIENTS = {
'PLAYER_PO_TOKEN_POLICY': PlayerPoTokenPolicy(required=False, recommended=True),
'REQUIRE_JS_PLAYER': False,
},
'ios_downgraded': {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'IOS',
'clientVersion': '19.49.7',
'deviceMake': 'Apple',
'deviceModel': 'iPhone16,2',
'userAgent': 'com.google.ios.youtube/19.49.7 (iPhone16,2; U; CPU iOS 17_5_1 like Mac OS X;)',
'osName': 'iPhone',
'osVersion': '17.5.1.21F90',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 5,
'GVS_PO_TOKEN_POLICY': {
StreamingProtocol.HTTPS: GvsPoTokenPolicy(
required=True,
recommended=True,
not_required_with_player_token=True,
),
StreamingProtocol.HLS: GvsPoTokenPolicy(
required=False,
recommended=True,
not_required_with_player_token=True,
),
},
'PLAYER_PO_TOKEN_POLICY': PlayerPoTokenPolicy(required=False, recommended=True),
'REQUIRE_JS_PLAYER': False,
},
# mweb has 'ultralow' formats
# See: https://github.com/yt-dlp/yt-dlp/pull/557
'mweb': {
@ -379,20 +351,6 @@ INNERTUBE_CLIENTS = {
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 75,
},
# This client now requires sign-in for every video
# It was previously an age-gate workaround for videos that were `playable_in_embed`
# It may still be useful if signed into an EU account that is not age-verified
'tv_embedded': {
'INNERTUBE_CONTEXT': {
'client': {
'clientName': 'TVHTML5_SIMPLY_EMBEDDED_PLAYER',
'clientVersion': '2.0',
},
},
'INNERTUBE_CONTEXT_CLIENT_NAME': 85,
'REQUIRE_AUTH': True,
'SUPPORTS_COOKIES': True,
},
}

View File

@ -145,8 +145,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
r'\b(?P<id>vfl[a-zA-Z0-9_-]+)\b.*?\.js$',
)
_SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'srt', 'vtt')
_DEFAULT_CLIENTS = ('android_vr', 'ios_downgraded', 'web', 'web_safari')
_DEFAULT_JSLESS_CLIENTS = ('android_vr', 'ios_downgraded')
_DEFAULT_CLIENTS = ('android_vr', 'web', 'web_safari')
_DEFAULT_JSLESS_CLIENTS = ('android_vr',)
_DEFAULT_AUTHED_CLIENTS = ('tv_downgraded', 'web', 'web_safari')
# Premium does not require POT (except for subtitles)
_DEFAULT_PREMIUM_CLIENTS = ('tv_downgraded', 'web_creator', 'web')
@ -1443,7 +1443,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
'view_count': int,
},
'params': {
'extractor_args': {'youtube': {'player_client': ['tv_embedded']}},
'format': '251-drc',
'skip_download': True,
},
@ -3118,6 +3117,15 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
else:
prs.append(pr)
if (
# Is this a "made for kids" video that can't be downloaded with android_vr?
client == 'android_vr' and self._is_unplayable(pr)
and webpage and 'made for kids' in webpage
# ...and is a JS runtime is available?
and any(p.is_available() for p in self._jsc_director.providers.values())
):
append_client('web_embedded')
# web_embedded can work around age-gate and age-verification for some embeddable videos
if self._is_agegated(pr) and variant != 'web_embedded':
append_client(f'web_embedded.{base_client}')
@ -3134,9 +3142,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
self.to_screen(
f'{video_id}: This video is age-restricted and YouTube is requiring '
'account age-verification; some formats may be missing', only_once=True)
# tv_embedded can work around the age-verification requirement for embeddable videos
# web_creator may work around age-verification for all videos but requires PO token
append_client('tv_embedded', 'web_creator')
append_client('web_creator')
status = traverse_obj(pr, ('playabilityStatus', 'status', {str}))
if status not in ('OK', 'LIVE_STREAM_OFFLINE', 'AGE_CHECK_REQUIRED', 'AGE_VERIFICATION_REQUIRED'):
@ -3595,10 +3602,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
if client_name == 'web_safari' and proto == 'hls' and live_status != 'is_live':
f['source_preference'] -= 1
# Safeguard against inevitable ios_downgraded client breakage
if client_name == 'ios_downgraded' and proto == 'hls' and live_status != 'is_live':
f['__needs_testing'] = True
if missing_pot:
f['format_note'] = join_nonempty(f.get('format_note'), 'MISSING POT', delim=' ')
f['source_preference'] -= 20

View File

@ -1,8 +1,8 @@
# Autogenerated by devscripts/update-version.py
__version__ = '2026.01.29'
__version__ = '2026.01.31'
RELEASE_GIT_HEAD = '8b275536d945c4b3d07b6c520677922c67a7c10f'
RELEASE_GIT_HEAD = '9a9a6b6fe44a30458c1754ef064f354f04a84004'
VARIANT = None
@ -12,4 +12,4 @@ CHANNEL = 'stable'
ORIGIN = 'yt-dlp/yt-dlp'
_pkg_version = '2026.01.29'
_pkg_version = '2026.01.31'