mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-27 06:10:12 +01:00
Compare commits
7 Commits
673da61de2
...
1a63b6b95a
Author | SHA1 | Date | |
---|---|---|---|
|
1a63b6b95a | ||
|
4b5eec0aaa | ||
|
3e9b4fdb60 | ||
|
b68122d9aa | ||
|
d9ab668223 | ||
|
4fc802f965 | ||
|
4d24983442 |
|
@ -59,16 +59,15 @@ def _extract_from_api(self, video_id, tld):
|
|||
'Accept': 'application/json',
|
||||
}, fatal=False, impersonate=True) or {}
|
||||
|
||||
status = response.get('room_status')
|
||||
if status != 'public':
|
||||
if error := self._ERROR_MAP.get(status):
|
||||
raise ExtractorError(error, expected=True)
|
||||
self.report_warning('Falling back to webpage extraction')
|
||||
return None
|
||||
|
||||
m3u8_url = response.get('url')
|
||||
if not m3u8_url:
|
||||
self.raise_geo_restricted()
|
||||
status = response.get('room_status')
|
||||
if error := self._ERROR_MAP.get(status):
|
||||
raise ExtractorError(error, expected=True)
|
||||
if status == 'public':
|
||||
self.raise_geo_restricted()
|
||||
self.report_warning(f'Got status "{status}" from API; falling back to webpage extraction')
|
||||
return None
|
||||
|
||||
return {
|
||||
'id': video_id,
|
||||
|
|
|
@ -16,11 +16,20 @@ class FrontendMastersBaseIE(InfoExtractor):
|
|||
|
||||
_NETRC_MACHINE = 'frontendmasters'
|
||||
|
||||
_QUALITIES = {
|
||||
'low': {'width': 480, 'height': 360},
|
||||
'mid': {'width': 1280, 'height': 720},
|
||||
'high': {'width': 1920, 'height': 1080},
|
||||
}
|
||||
def _get_subtitles(self, lesson_data, course_data):
|
||||
captions_base = "https://captions.frontendmasters.com/assets/courses/"
|
||||
lesson_slug = lesson_data.get('slug')
|
||||
lesson_index = lesson_data.get('index')
|
||||
date_published = course_data.get('datePublished')
|
||||
course_slug = course_data.get('slug')
|
||||
|
||||
subtitles_url = f'{captions_base}{date_published}-{course_slug}/{lesson_index}-{lesson_slug}.vtt'
|
||||
|
||||
return {
|
||||
'en': [{
|
||||
'url': subtitles_url
|
||||
}]
|
||||
}
|
||||
|
||||
def _perform_login(self, username, password):
|
||||
login_page = self._download_webpage(
|
||||
|
@ -72,7 +81,7 @@ def _extract_chapters(course):
|
|||
return chapters
|
||||
|
||||
@staticmethod
|
||||
def _extract_lesson(chapters, lesson_id, lesson):
|
||||
def _extract_lesson(chapters, lesson_id, lesson, subtitles):
|
||||
title = lesson.get('title') or lesson_id
|
||||
display_id = lesson.get('slug')
|
||||
description = lesson.get('description')
|
||||
|
@ -109,6 +118,7 @@ def _extract_lesson(chapters, lesson_id, lesson):
|
|||
'duration': duration,
|
||||
'chapter': chapter,
|
||||
'chapter_number': chapter_number,
|
||||
'subtitles': subtitles
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,43 +142,28 @@ def _real_extract(self, url):
|
|||
lesson_id = self._match_id(url)
|
||||
|
||||
source_url = f'{self._API_BASE}/video/{lesson_id}/source'
|
||||
|
||||
formats = []
|
||||
for ext in ('webm', 'mp4'):
|
||||
for quality in ('low', 'mid', 'high'):
|
||||
resolution = self._QUALITIES[quality].copy()
|
||||
format_id = f'{ext}-{quality}'
|
||||
format_url = self._download_json(
|
||||
source_url, lesson_id,
|
||||
f'Downloading {format_id} source JSON', query={
|
||||
'f': ext,
|
||||
'r': resolution['height'],
|
||||
}, headers={
|
||||
'Referer': url,
|
||||
}, fatal=False)['url']
|
||||
|
||||
if not format_url:
|
||||
continue
|
||||
|
||||
f = resolution.copy()
|
||||
f.update({
|
||||
'url': format_url,
|
||||
'ext': ext,
|
||||
'format_id': format_id,
|
||||
})
|
||||
formats.append(f)
|
||||
|
||||
subtitles = {
|
||||
'en': [{
|
||||
'url': f'{self._API_BASE}/transcripts/{lesson_id}.vtt',
|
||||
}],
|
||||
headers = {
|
||||
'Referer': 'https://frontendmasters.com/',
|
||||
}
|
||||
cookies = self._get_cookies("https://frontendmasters.com/")
|
||||
fem_auth_mod = cookies.get('fem_auth_mod')
|
||||
if fem_auth_mod:
|
||||
headers['Cookie'] = f'fem_auth_mod={fem_auth_mod.value}'
|
||||
|
||||
json_response = self._download_json(
|
||||
source_url,
|
||||
'Downloading source JSON', query={
|
||||
'f': 'm3u8'
|
||||
}, headers=headers)
|
||||
|
||||
m3u8_url = json_response.get('url')
|
||||
|
||||
formats = self._extract_m3u8_formats(m3u8_url, lesson_id)
|
||||
|
||||
return {
|
||||
'id': lesson_id,
|
||||
'title': lesson_id,
|
||||
'formats': formats,
|
||||
'subtitles': subtitles,
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,8 +198,9 @@ def _real_extract(self, url):
|
|||
for video_id, data in course['lessonData'].items()
|
||||
if data.get('slug') == lesson_name)
|
||||
|
||||
subtitles = self.extract_subtitles(lesson, course)
|
||||
chapters = self._extract_chapters(course)
|
||||
return self._extract_lesson(chapters, lesson_id, lesson)
|
||||
return self._extract_lesson(chapters, lesson_id, lesson, subtitles)
|
||||
|
||||
|
||||
class FrontendMastersCourseIE(FrontendMastersPageBaseIE):
|
||||
|
@ -239,9 +235,10 @@ def _real_extract(self, url):
|
|||
for lesson in lessons:
|
||||
lesson_name = lesson.get('slug')
|
||||
lesson_id = lesson.get('hash') or lesson.get('statsId')
|
||||
subtitles = self.extract_subtitles(lesson, course)
|
||||
if not lesson_id or not lesson_name:
|
||||
continue
|
||||
entries.append(self._extract_lesson(chapters, lesson_id, lesson))
|
||||
entries.append(self._extract_lesson(chapters, lesson_id, lesson, subtitles))
|
||||
|
||||
title = course.get('title')
|
||||
description = course.get('description')
|
||||
|
|
Loading…
Reference in New Issue
Block a user