]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/lego.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
7 from ..compat
import compat_HTTPError
15 class LEGOIE(InfoExtractor
):
16 _VALID_URL
= r
'https?://(?:www\.)?lego\.com/(?P<locale>[a-z]{2}-[a-z]{2})/(?:[^/]+/)*videos/(?:[^/]+/)*[^/?#]+-(?P<id>[0-9a-f]{32})'
18 'url': 'http://www.lego.com/en-us/videos/themes/club/blocumentary-kawaguchi-55492d823b1b4d5e985787fa8c2973b1',
19 'md5': 'f34468f176cfd76488767fc162c405fa',
21 'id': '55492d82-3b1b-4d5e-9857-87fa8c2973b1_en-US',
23 'title': 'Blocumentary Great Creations: Akiyuki Kawaguchi',
24 'description': 'Blocumentary Great Creations: Akiyuki Kawaguchi',
27 # geo-restricted but the contentUrl contain a valid url
28 'url': 'http://www.lego.com/nl-nl/videos/themes/nexoknights/episode-20-kingdom-of-heroes-13bdc2299ab24d9685701a915b3d71e7##sp=399',
29 'md5': 'c7420221f7ffd03ff056f9db7f8d807c',
31 'id': '13bdc229-9ab2-4d96-8570-1a915b3d71e7_nl-NL',
33 'title': 'Aflevering 20: Helden van het koninkrijk',
34 'description': 'md5:8ee499aac26d7fa8bcb0cedb7f9c3941',
39 'url': 'https://www.lego.com/nl-nl/kids/videos/classic/creative-storytelling-the-little-puppy-aa24f27c7d5242bc86102ebdc0f24cba',
41 'id': 'aa24f27c-7d52-42bc-8610-2ebdc0f24cba_nl-NL',
43 'title': 'De kleine puppy',
44 'description': 'md5:5b725471f849348ac73f2e12cfb4be06',
49 'url': r
're:^https://.+\.srt$',
54 'skip_download': True,
58 'Lowest': (64, 180, 320),
59 'Low': (64, 270, 480),
60 'Medium': (96, 360, 640),
61 'High': (128, 540, 960),
62 'Highest': (128, 720, 1280),
65 def _real_extract(self
, url
):
66 locale
, video_id
= self
._match
_valid
_url
(url
).groups()
67 countries
= [locale
.split('-')[1].upper()]
68 self
._initialize
_geo
_bypass
({
69 'countries': countries
,
73 item
= self
._download
_json
(
74 # https://contentfeed.services.lego.com/api/v2/item/[VIDEO_ID]?culture=[LOCALE]&contentType=Video
75 'https://services.slingshot.lego.com/mediaplayer/v2',
77 'videoId': '%s_%s' % (uuid
.UUID(video_id
), locale
),
78 }, headers
=self
.geo_verification_headers())
79 except ExtractorError
as e
:
80 if isinstance(e
.cause
, compat_HTTPError
) and e
.cause
.code
== 451:
81 self
.raise_geo_restricted(countries
=countries
)
85 video_id
= video
['Id']
86 title
= video
['Title']
88 q
= qualities(['Lowest', 'Low', 'Medium', 'High', 'Highest'])
90 for video_source
in item
.get('VideoFormats', []):
91 video_source_url
= video_source
.get('Url')
92 if not video_source_url
:
94 video_source_format
= video_source
.get('Format')
95 if video_source_format
== 'F4M':
96 formats
.extend(self
._extract
_f
4m
_formats
(
97 video_source_url
, video_id
,
98 f4m_id
=video_source_format
, fatal
=False))
99 elif video_source_format
== 'M3U8':
100 formats
.extend(self
._extract
_m
3u8_formats
(
101 video_source_url
, video_id
, 'mp4', 'm3u8_native',
102 m3u8_id
=video_source_format
, fatal
=False))
104 video_source_quality
= video_source
.get('Quality')
106 for v
in (video_source_format
, video_source_quality
):
110 'format_id': '-'.join(format_id
),
111 'quality': q(video_source_quality
),
112 'url': video_source_url
,
114 quality
= self
._QUALITIES
.get(video_source_quality
)
118 'height': quality
[1],
122 self
._sort
_formats
(formats
)
125 sub_file_id
= video
.get('SubFileId')
126 if sub_file_id
and sub_file_id
!= '00000000-0000-0000-0000-000000000000':
127 net_storage_path
= video
.get('NetstoragePath')
128 invariant_id
= video
.get('InvariantId')
129 video_file_id
= video
.get('VideoFileId')
130 video_version
= video
.get('VideoVersion')
131 if net_storage_path
and invariant_id
and video_file_id
and video_version
:
132 subtitles
.setdefault(locale
[:2], []).append({
133 'url': 'https://lc-mediaplayerns-live-s.legocdn.com/public/%s/%s_%s_%s_%s_sub.srt' % (net_storage_path
, invariant_id
, video_file_id
, locale
, video_version
),
139 'description': video
.get('Description'),
140 'thumbnail': video
.get('GeneratedCoverImage') or video
.get('GeneratedThumbnail'),
141 'duration': int_or_none(video
.get('Length')),
143 'subtitles': subtitles
,
144 'age_limit': int_or_none(video
.get('AgeFrom')),
145 'season': video
.get('SeasonTitle'),
146 'season_number': int_or_none(video
.get('Season')) or None,
147 'episode_number': int_or_none(video
.get('Episode')) or None,