yt-dlp 2025.12.4.233042.dev0__py3-none-any.whl → 2025.12.5.232956.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6176,6 +6176,7 @@ class LoomFolderIE(LazyLoadExtractor):
6176
6176
  _module = 'yt_dlp.extractor.loom'
6177
6177
  IE_NAME = 'loom:folder'
6178
6178
  _VALID_URL = 'https?://(?:www\\.)?loom\\.com/share/folder/(?P<id>[\\da-f]{32})'
6179
+ _WORKING = False
6179
6180
  _RETURN_TYPE = 'playlist'
6180
6181
 
6181
6182
 
yt_dlp/extractor/loom.py CHANGED
@@ -8,12 +8,10 @@ from ..utils import (
8
8
  ExtractorError,
9
9
  determine_ext,
10
10
  filter_dict,
11
- get_first,
12
11
  int_or_none,
13
12
  parse_iso8601,
14
13
  update_url,
15
14
  url_or_none,
16
- variadic,
17
15
  )
18
16
  from ..utils.traversal import traverse_obj
19
17
 
@@ -51,7 +49,7 @@ class LoomIE(InfoExtractor):
51
49
  }, {
52
50
  # m3u8 raw-url, mp4 transcoded-url, cdn url == raw-url, vtt sub and json subs
53
51
  'url': 'https://www.loom.com/share/9458bcbf79784162aa62ffb8dd66201b',
54
- 'md5': '51737ec002969dd28344db4d60b9cbbb',
52
+ 'md5': '7b6bfdef8181c4ffc376e18919a4dcc2',
55
53
  'info_dict': {
56
54
  'id': '9458bcbf79784162aa62ffb8dd66201b',
57
55
  'ext': 'mp4',
@@ -71,12 +69,13 @@ class LoomIE(InfoExtractor):
71
69
  'ext': 'webm',
72
70
  'title': 'OMFG clown',
73
71
  'description': 'md5:285c5ee9d62aa087b7e3271b08796815',
74
- 'uploader': 'MrPumkin B',
72
+ 'uploader': 'Brailey Bragg',
75
73
  'upload_date': '20210924',
76
74
  'timestamp': 1632519618,
77
75
  'duration': 210,
78
76
  },
79
77
  'params': {'skip_download': 'dash'},
78
+ 'expected_warnings': ['Failed to parse JSON'], # transcoded-url no longer available
80
79
  }, {
81
80
  # password-protected
82
81
  'url': 'https://www.loom.com/share/50e26e8aeb7940189dff5630f95ce1f4',
@@ -91,10 +90,11 @@ class LoomIE(InfoExtractor):
91
90
  'duration': 35,
92
91
  },
93
92
  'params': {'videopassword': 'seniorinfants2'},
93
+ 'expected_warnings': ['Failed to parse JSON'], # transcoded-url no longer available
94
94
  }, {
95
95
  # embed, transcoded-url endpoint sends empty JSON response, split video and audio HLS formats
96
96
  'url': 'https://www.loom.com/embed/ddcf1c1ad21f451ea7468b1e33917e4e',
97
- 'md5': 'b321d261656848c184a94e3b93eae28d',
97
+ 'md5': 'f983a0f02f24331738b2f43aecb05256',
98
98
  'info_dict': {
99
99
  'id': 'ddcf1c1ad21f451ea7468b1e33917e4e',
100
100
  'ext': 'mp4',
@@ -119,11 +119,12 @@ class LoomIE(InfoExtractor):
119
119
  'duration': 247,
120
120
  'timestamp': 1676274030,
121
121
  },
122
+ 'skip': '404 Not Found',
122
123
  }]
123
124
 
124
125
  _GRAPHQL_VARIABLES = {
125
126
  'GetVideoSource': {
126
- 'acceptableMimes': ['DASH', 'M3U8', 'MP4'],
127
+ 'acceptableMimes': ['DASH', 'M3U8', 'MP4', 'WEBM'],
127
128
  },
128
129
  }
129
130
  _GRAPHQL_QUERIES = {
@@ -192,6 +193,12 @@ class LoomIE(InfoExtractor):
192
193
  id
193
194
  nullableRawCdnUrl(acceptableMimes: $acceptableMimes, password: $password) {
194
195
  url
196
+ credentials {
197
+ Policy
198
+ Signature
199
+ KeyPairId
200
+ __typename
201
+ }
195
202
  __typename
196
203
  }
197
204
  __typename
@@ -240,9 +247,9 @@ class LoomIE(InfoExtractor):
240
247
  }
241
248
  }\n'''),
242
249
  }
243
- _APOLLO_GRAPHQL_VERSION = '0a1856c'
250
+ _APOLLO_GRAPHQL_VERSION = '45a5bd4'
244
251
 
245
- def _call_graphql_api(self, operations, video_id, note=None, errnote=None):
252
+ def _call_graphql_api(self, operation_name, video_id, note=None, errnote=None, fatal=True):
246
253
  password = self.get_param('videopassword')
247
254
  return self._download_json(
248
255
  'https://www.loom.com/graphql', video_id, note or 'Downloading GraphQL JSON',
@@ -252,7 +259,9 @@ class LoomIE(InfoExtractor):
252
259
  'x-loom-request-source': f'loom_web_{self._APOLLO_GRAPHQL_VERSION}',
253
260
  'apollographql-client-name': 'web',
254
261
  'apollographql-client-version': self._APOLLO_GRAPHQL_VERSION,
255
- }, data=json.dumps([{
262
+ 'graphql-operation-name': operation_name,
263
+ 'Origin': 'https://www.loom.com',
264
+ }, data=json.dumps({
256
265
  'operationName': operation_name,
257
266
  'variables': {
258
267
  'videoId': video_id,
@@ -260,7 +269,7 @@ class LoomIE(InfoExtractor):
260
269
  **self._GRAPHQL_VARIABLES.get(operation_name, {}),
261
270
  },
262
271
  'query': self._GRAPHQL_QUERIES[operation_name],
263
- } for operation_name in variadic(operations)], separators=(',', ':')).encode())
272
+ }, separators=(',', ':')).encode(), fatal=fatal)
264
273
 
265
274
  def _call_url_api(self, endpoint, video_id):
266
275
  response = self._download_json(
@@ -275,7 +284,7 @@ class LoomIE(InfoExtractor):
275
284
  }, separators=(',', ':')).encode())
276
285
  return traverse_obj(response, ('url', {url_or_none}))
277
286
 
278
- def _extract_formats(self, video_id, metadata, gql_data):
287
+ def _extract_formats(self, video_id, metadata, video_data):
279
288
  formats = []
280
289
  video_properties = traverse_obj(metadata, ('video_properties', {
281
290
  'width': ('width', {int_or_none}),
@@ -330,7 +339,7 @@ class LoomIE(InfoExtractor):
330
339
  transcoded_url = self._call_url_api('transcoded-url', video_id)
331
340
  formats.extend(get_formats(transcoded_url, 'transcoded', quality=-1)) # transcoded quality
332
341
 
333
- cdn_url = get_first(gql_data, ('data', 'getVideo', 'nullableRawCdnUrl', 'url', {url_or_none}))
342
+ cdn_url = traverse_obj(video_data, ('data', 'getVideo', 'nullableRawCdnUrl', 'url', {url_or_none}))
334
343
  # cdn_url is usually a dupe, but the raw-url/transcoded-url endpoints could return errors
335
344
  valid_urls = [update_url(url, query=None) for url in (raw_url, transcoded_url) if url]
336
345
  if cdn_url and update_url(cdn_url, query=None) not in valid_urls:
@@ -338,10 +347,21 @@ class LoomIE(InfoExtractor):
338
347
 
339
348
  return formats
340
349
 
350
+ def _get_subtitles(self, video_id):
351
+ subs_data = self._call_graphql_api(
352
+ 'FetchVideoTranscript', video_id, 'Downloading GraphQL subtitles JSON', fatal=False)
353
+ return filter_dict({
354
+ 'en': traverse_obj(subs_data, (
355
+ 'data', 'fetchVideoTranscript',
356
+ ('source_url', 'captions_source_url'), {
357
+ 'url': {url_or_none},
358
+ })) or None,
359
+ })
360
+
341
361
  def _real_extract(self, url):
342
362
  video_id = self._match_id(url)
343
- metadata = get_first(
344
- self._call_graphql_api('GetVideoSSR', video_id, 'Downloading GraphQL metadata JSON'),
363
+ metadata = traverse_obj(
364
+ self._call_graphql_api('GetVideoSSR', video_id, 'Downloading GraphQL metadata JSON', fatal=False),
345
365
  ('data', 'getVideo', {dict})) or {}
346
366
 
347
367
  if metadata.get('__typename') == 'VideoPasswordMissingOrIncorrect':
@@ -350,22 +370,19 @@ class LoomIE(InfoExtractor):
350
370
  'This video is password-protected, use the --video-password option', expected=True)
351
371
  raise ExtractorError('Invalid video password', expected=True)
352
372
 
353
- gql_data = self._call_graphql_api(['FetchChapters', 'FetchVideoTranscript', 'GetVideoSource'], video_id)
373
+ video_data = self._call_graphql_api(
374
+ 'GetVideoSource', video_id, 'Downloading GraphQL video JSON')
375
+ chapter_data = self._call_graphql_api(
376
+ 'FetchChapters', video_id, 'Downloading GraphQL chapters JSON', fatal=False)
354
377
  duration = traverse_obj(metadata, ('video_properties', 'duration', {int_or_none}))
355
378
 
356
379
  return {
357
380
  'id': video_id,
358
381
  'duration': duration,
359
382
  'chapters': self._extract_chapters_from_description(
360
- get_first(gql_data, ('data', 'fetchVideoChapters', 'content', {str})), duration) or None,
361
- 'formats': self._extract_formats(video_id, metadata, gql_data),
362
- 'subtitles': filter_dict({
363
- 'en': traverse_obj(gql_data, (
364
- ..., 'data', 'fetchVideoTranscript',
365
- ('source_url', 'captions_source_url'), {
366
- 'url': {url_or_none},
367
- })) or None,
368
- }),
383
+ traverse_obj(chapter_data, ('data', 'fetchVideoChapters', 'content', {str})), duration) or None,
384
+ 'formats': self._extract_formats(video_id, metadata, video_data),
385
+ 'subtitles': self.extract_subtitles(video_id),
369
386
  **traverse_obj(metadata, {
370
387
  'title': ('name', {str}),
371
388
  'description': ('description', {str}),
@@ -376,6 +393,7 @@ class LoomIE(InfoExtractor):
376
393
 
377
394
 
378
395
  class LoomFolderIE(InfoExtractor):
396
+ _WORKING = False
379
397
  IE_NAME = 'loom:folder'
380
398
  _VALID_URL = r'https?://(?:www\.)?loom\.com/share/folder/(?P<id>[\da-f]{32})'
381
399
  _TESTS = [{
yt_dlp/version.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # Autogenerated by devscripts/update-version.py
2
2
 
3
- __version__ = '2025.12.04.233042'
3
+ __version__ = '2025.12.05.232956'
4
4
 
5
- RELEASE_GIT_HEAD = '7ec6b9bc40ee8a21b11cce83a09a07a37014062e'
5
+ RELEASE_GIT_HEAD = '36b29bb3532e008a2aaf3d36d1c6fc3944137930'
6
6
 
7
7
  VARIANT = 'pip'
8
8
 
@@ -12,4 +12,4 @@ CHANNEL = 'nightly'
12
12
 
13
13
  ORIGIN = 'yt-dlp/yt-dlp-nightly-builds'
14
14
 
15
- _pkg_version = '2025.12.04.233042dev'
15
+ _pkg_version = '2025.12.05.232956dev'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: yt-dlp
3
- Version: 2025.12.4.233042.dev0
3
+ Version: 2025.12.5.232956.dev0
4
4
  Summary: A feature-rich command-line audio/video downloader
5
5
  Project-URL: Documentation, https://github.com/yt-dlp/yt-dlp#readme
6
6
  Project-URL: Repository, https://github.com/yt-dlp/yt-dlp
@@ -11,7 +11,7 @@ yt_dlp/options.py,sha256=Icc0JRiKOzITWoMujE_ihEmkCS-uCcie42XhIh8LvS4,100388
11
11
  yt_dlp/plugins.py,sha256=EGmR0ydaahNspGrgszTNX4-YjHe93WOOhcw1gf6PZSs,8215
12
12
  yt_dlp/socks.py,sha256=oAuAfWM6jxI8A5hHDLEKq2U2-k9NyMB_z6nrKzNE9fg,8936
13
13
  yt_dlp/update.py,sha256=sY7gNFBQorzs7sEjRrqL5QOsTBNmGGa_FnpTtbxY1vA,25280
14
- yt_dlp/version.py,sha256=h5SMPbyrWurCsxjBA0uxBzhfB5YV5QG-GrvnO4VodO4,360
14
+ yt_dlp/version.py,sha256=ObMmEuCPDAZEf-cqx4M9br9QkZNQpoAOguP4Hg2KZWI,360
15
15
  yt_dlp/webvtt.py,sha256=ONkXaaNCZcX8pQhJn3iwIKyaQ34BtVDrMEdG6wRNZwM,11451
16
16
  yt_dlp/__pyinstaller/__init__.py,sha256=-c4Zo8nQGKAm8wc_LDscxMtK7zr_YhZwRnC9CMruUBE,72
17
17
  yt_dlp/__pyinstaller/hook-yt_dlp.py,sha256=5Rd0zV2pDskjY1KtT0wsjxv4hStx67sLCjUexsFvFus,1339
@@ -458,7 +458,7 @@ yt_dlp/extractor/la7.py,sha256=GShDLu1N0rS1bY4uIiUkznThvn7gNiwtSgmh7Rs7t08,9435
458
458
  yt_dlp/extractor/laracasts.py,sha256=PzTqAbHXiUqog-mpp2qR_rpKa-sZel4mLyzWTPkbDuc,4587
459
459
  yt_dlp/extractor/lastfm.py,sha256=OpmE-Y-2rcav2r2xaDQzX_EJiltmbbe6fO9VzkLqNWQ,4748
460
460
  yt_dlp/extractor/laxarxames.py,sha256=-YyL-5y4t2L9ptTSLXhvK-SJwvXGqv5l1HfT129zF0c,2773
461
- yt_dlp/extractor/lazy_extractors.py,sha256=aUHT3Pq3Pu11vA0Qk120M8a4xTkq9A0wh6BnDhxbRsQ,814963
461
+ yt_dlp/extractor/lazy_extractors.py,sha256=EUfWKPLhZw4CIMqCgfuKMNqKt8MuUZ0768n8jPNTsOo,814984
462
462
  yt_dlp/extractor/lbry.py,sha256=gC9jRRo8wSXc1-6somhW13brAtmWGlJ5_Q0NMhZpKwk,18078
463
463
  yt_dlp/extractor/lci.py,sha256=_0XuoITIt_QFA-6eBNpDXZZfouwUWfcdHQlpAOuiLEs,2131
464
464
  yt_dlp/extractor/lcp.py,sha256=edMA8L-eJZLquDvHcSY4oFWI0C8yGgjqW1tmhhLMJ5U,2279
@@ -483,7 +483,7 @@ yt_dlp/extractor/livestream.py,sha256=Tb9IVpZc0xxT2JHXUpOTbfzkPatgMmWw2i3QmBK2zu
483
483
  yt_dlp/extractor/livestreamfails.py,sha256=mNjvcF9ofvJzeuXMpkSxAk9Yv73yWV8NCcJJdHBQZbk,1568
484
484
  yt_dlp/extractor/lnk.py,sha256=9cY3o9b6utrU7tcQMBKFt1ikYvnrbOWY2itBETssM_Q,3377
485
485
  yt_dlp/extractor/loco.py,sha256=ffe2T0H6c9gMme5PDnp2HCgR3QMFpzXQBbp7K0sNFEI,6973
486
- yt_dlp/extractor/loom.py,sha256=nOdhTpnCioF_zFpX9VAaDlopBMGwM2Yu3etjRZaPqm4,18482
486
+ yt_dlp/extractor/loom.py,sha256=7E1nSN8gWJ4Mr86C-HSUWKIbGCUX6T_gnxEpXEmPH4w,19354
487
487
  yt_dlp/extractor/lovehomeporn.py,sha256=iv60L0aXcg1EoZkGGXT-Mh3JS78M_NOZ_Y5bouICZnY,1130
488
488
  yt_dlp/extractor/lrt.py,sha256=uNnpbXpngJZVByP9YCoFIKyhnW0NbUeCKv8rcqYAuHM,7088
489
489
  yt_dlp/extractor/lsm.py,sha256=_wCHc27uzRBL9BcUk3sD2fqj9dVKfxE5p8T2UxXMUVg,12816
@@ -1122,13 +1122,13 @@ yt_dlp/utils/progress.py,sha256=t9kVvJ0oWuEqRzo9fdFbIhHUBtO_8mg348QwZ1faqLo,3261
1122
1122
  yt_dlp/utils/traversal.py,sha256=64E3RcZ56iSX50RI_HbKdDNftkETMLBaEPX791_b7yQ,18265
1123
1123
  yt_dlp/utils/jslib/__init__.py,sha256=CbdJiRA7Eh5PnjF2V4lDTcg0J0XjBMaaq0H4pCfq9Tk,87
1124
1124
  yt_dlp/utils/jslib/devalue.py,sha256=7DCGK_zUN0ZeV5hwPT06zaRMUxX_hyUyFWqs79rxw24,5621
1125
- yt_dlp-2025.12.4.233042.dev0.data/data/share/bash-completion/completions/yt-dlp,sha256=b0pb9GLseKD27CjnLE6LlhVxhfmQjmyqV6r_CRbd6ko,5989
1126
- yt_dlp-2025.12.4.233042.dev0.data/data/share/doc/yt_dlp/README.txt,sha256=Bgx271dvWVM7TqhGKdrgqQGXSJmlvO678jfyNC6aCJA,164826
1127
- yt_dlp-2025.12.4.233042.dev0.data/data/share/fish/vendor_completions.d/yt-dlp.fish,sha256=hLa6lZnm7keENpNCjml9A88hbvefdsdoOpAiaNCVyHo,51488
1128
- yt_dlp-2025.12.4.233042.dev0.data/data/share/man/man1/yt-dlp.1,sha256=EfXpaxlohoxUn8X5ROJ0THnppGch3vy9bXOPsKPs3Bw,159331
1129
- yt_dlp-2025.12.4.233042.dev0.data/data/share/zsh/site-functions/_yt-dlp,sha256=pNhu8tT4ZKrksLRI2mXLqarzGGhnOlm_hkCBVhSxLzg,5985
1130
- yt_dlp-2025.12.4.233042.dev0.dist-info/METADATA,sha256=KrHbZGBKrm9rtvEdPyUCnAM_gDUGGmVdDr8EJ862XhQ,180215
1131
- yt_dlp-2025.12.4.233042.dev0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
1132
- yt_dlp-2025.12.4.233042.dev0.dist-info/entry_points.txt,sha256=vWfetvzYgZIwDfMW6BjCe0Cy4pmTZEXRNzxAkfYlRJA,103
1133
- yt_dlp-2025.12.4.233042.dev0.dist-info/licenses/LICENSE,sha256=fhLl30uuEsshWBuhV87SDhmGoFCN0Q0Oikq5pM-U6Fw,1211
1134
- yt_dlp-2025.12.4.233042.dev0.dist-info/RECORD,,
1125
+ yt_dlp-2025.12.5.232956.dev0.data/data/share/bash-completion/completions/yt-dlp,sha256=b0pb9GLseKD27CjnLE6LlhVxhfmQjmyqV6r_CRbd6ko,5989
1126
+ yt_dlp-2025.12.5.232956.dev0.data/data/share/doc/yt_dlp/README.txt,sha256=Bgx271dvWVM7TqhGKdrgqQGXSJmlvO678jfyNC6aCJA,164826
1127
+ yt_dlp-2025.12.5.232956.dev0.data/data/share/fish/vendor_completions.d/yt-dlp.fish,sha256=hLa6lZnm7keENpNCjml9A88hbvefdsdoOpAiaNCVyHo,51488
1128
+ yt_dlp-2025.12.5.232956.dev0.data/data/share/man/man1/yt-dlp.1,sha256=EfXpaxlohoxUn8X5ROJ0THnppGch3vy9bXOPsKPs3Bw,159331
1129
+ yt_dlp-2025.12.5.232956.dev0.data/data/share/zsh/site-functions/_yt-dlp,sha256=pNhu8tT4ZKrksLRI2mXLqarzGGhnOlm_hkCBVhSxLzg,5985
1130
+ yt_dlp-2025.12.5.232956.dev0.dist-info/METADATA,sha256=zGMF0oBx-oCfAJp1APmlK9r-HDmQbYm7ZzH9UHK5k6U,180215
1131
+ yt_dlp-2025.12.5.232956.dev0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
1132
+ yt_dlp-2025.12.5.232956.dev0.dist-info/entry_points.txt,sha256=vWfetvzYgZIwDfMW6BjCe0Cy4pmTZEXRNzxAkfYlRJA,103
1133
+ yt_dlp-2025.12.5.232956.dev0.dist-info/licenses/LICENSE,sha256=fhLl30uuEsshWBuhV87SDhmGoFCN0Q0Oikq5pM-U6Fw,1211
1134
+ yt_dlp-2025.12.5.232956.dev0.dist-info/RECORD,,