mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-29 18:51:24 +01:00
Compare commits
8 Commits
69926d80e8
...
37ff053333
Author | SHA1 | Date | |
---|---|---|---|
|
37ff053333 | ||
|
b0088b0e92 | ||
|
f806717288 | ||
|
7b3d6e1887 | ||
|
72800be3e0 | ||
|
c003b6cf41 | ||
|
3c77896933 | ||
|
1832b26f49 |
|
@ -4,9 +4,12 @@ from .common import InfoExtractor
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
clean_html,
|
clean_html,
|
||||||
|
filter_dict,
|
||||||
get_element_by_id,
|
get_element_by_id,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
|
join_nonempty,
|
||||||
js_to_json,
|
js_to_json,
|
||||||
|
qualities,
|
||||||
url_or_none,
|
url_or_none,
|
||||||
urljoin,
|
urljoin,
|
||||||
)
|
)
|
||||||
|
@ -44,27 +47,22 @@ class KukuluLiveIE(InfoExtractor):
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _get_quality_meta(self, video_id, desc, code, force_h264=''):
|
def _get_quality_meta(self, video_id, desc, code, force_h264=None):
|
||||||
description = desc if force_h264 == '' else f'{desc} (force_h264)'
|
desc += ' (force_h264)' if force_h264 else ''
|
||||||
qs = self._download_webpage(
|
qs = self._download_webpage(
|
||||||
'https://live.erinn.biz/live.player.fplayer.php', video_id,
|
'https://live.erinn.biz/live.player.fplayer.php', video_id,
|
||||||
query={
|
f'Downloading {desc} quality metadata', f'Unable to download {desc} quality metadata',
|
||||||
|
query=filter_dict({
|
||||||
'hash': video_id,
|
'hash': video_id,
|
||||||
'action': f'get{code}liveByAjax',
|
'action': f'get{code}liveByAjax',
|
||||||
'force_h264': force_h264,
|
'force_h264': force_h264,
|
||||||
},
|
}))
|
||||||
note=f'Downloading {description} quality metadata',
|
|
||||||
errnote=f'Unable to download {description} quality metadata')
|
|
||||||
return urllib.parse.parse_qs(qs)
|
return urllib.parse.parse_qs(qs)
|
||||||
|
|
||||||
def _add_quality_formats(self, formats, quality_meta):
|
def _add_quality_formats(self, formats, quality_meta):
|
||||||
vcodec = traverse_obj(quality_meta, ('vcodec', 0))
|
vcodec = traverse_obj(quality_meta, ('vcodec', 0, {str}))
|
||||||
quality = traverse_obj(quality_meta, ('now_quality', 0))
|
quality = traverse_obj(quality_meta, ('now_quality', 0, {str}))
|
||||||
quality_priority = {
|
quality_priority = qualities(('low', 'h264', 'high'))(quality)
|
||||||
'high': 3,
|
|
||||||
'h264': 2,
|
|
||||||
'low': 1,
|
|
||||||
}.get(quality, 0)
|
|
||||||
if traverse_obj(quality_meta, ('hlsaddr', 0, {url_or_none})):
|
if traverse_obj(quality_meta, ('hlsaddr', 0, {url_or_none})):
|
||||||
formats.append({
|
formats.append({
|
||||||
'format_id': quality,
|
'format_id': quality,
|
||||||
|
@ -75,7 +73,7 @@ class KukuluLiveIE(InfoExtractor):
|
||||||
})
|
})
|
||||||
if traverse_obj(quality_meta, ('hlsaddr_audioonly', 0, {url_or_none})):
|
if traverse_obj(quality_meta, ('hlsaddr_audioonly', 0, {url_or_none})):
|
||||||
formats.append({
|
formats.append({
|
||||||
'format_id': f'{quality}-audioonly',
|
'format_id': join_nonempty(quality, 'audioonly'),
|
||||||
'url': quality_meta['hlsaddr_audioonly'][0],
|
'url': quality_meta['hlsaddr_audioonly'][0],
|
||||||
'ext': 'm4a',
|
'ext': 'm4a',
|
||||||
'vcodec': 'none',
|
'vcodec': 'none',
|
||||||
|
@ -86,25 +84,22 @@ class KukuluLiveIE(InfoExtractor):
|
||||||
video_id = self._match_id(url)
|
video_id = self._match_id(url)
|
||||||
html = self._download_webpage(url, video_id)
|
html = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
title = clean_html(get_element_by_id('livetitle', html.replace('<SPAN', '<span').replace('SPAN>', 'span>')))
|
if '>タイムシフトが見つかりませんでした。<' in html:
|
||||||
|
raise ExtractorError('This stream has expired', expected=True)
|
||||||
|
|
||||||
|
title = clean_html(
|
||||||
|
get_element_by_id('livetitle', html.replace('<SPAN', '<span').replace('SPAN>', 'span>')))
|
||||||
description = self._html_search_meta('Description', html)
|
description = self._html_search_meta('Description', html)
|
||||||
thumbnail = self._html_search_meta(['og:image', 'twitter:image'], html)
|
thumbnail = self._html_search_meta(['og:image', 'twitter:image'], html)
|
||||||
|
|
||||||
is_live_stream = 'var timeshift = false;' in html
|
if self._search_regex(r'(var\s+timeshift\s*=\s*false)', html, 'is livestream', default=False):
|
||||||
is_vod = 'var timeshift = true;' in html
|
|
||||||
|
|
||||||
if is_live_stream:
|
|
||||||
qualities = [
|
|
||||||
('high', 'Z'),
|
|
||||||
('low', 'ForceLow'),
|
|
||||||
]
|
|
||||||
formats = []
|
formats = []
|
||||||
for (desc, code) in qualities:
|
for (desc, code) in [('high', 'Z'), ('low', 'ForceLow')]:
|
||||||
quality_meta = self._get_quality_meta(video_id, desc, code)
|
quality_meta = self._get_quality_meta(video_id, desc, code)
|
||||||
self._add_quality_formats(formats, quality_meta)
|
self._add_quality_formats(formats, quality_meta)
|
||||||
if desc == 'high' and quality_meta.get('vcodec')[0] == 'HEVC':
|
if desc == 'high' and traverse_obj(quality_meta, ('vcodec', 0)) == 'HEVC':
|
||||||
h264_meta = self._get_quality_meta(video_id, desc, code, force_h264='1')
|
self._add_quality_formats(
|
||||||
self._add_quality_formats(formats, h264_meta)
|
formats, self._get_quality_meta(video_id, desc, code, force_h264='1'))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
|
@ -115,42 +110,31 @@ class KukuluLiveIE(InfoExtractor):
|
||||||
'formats': formats,
|
'formats': formats,
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_vod:
|
# VOD extraction
|
||||||
player_html = self._download_webpage(
|
player_html = self._download_webpage(
|
||||||
'https://live.erinn.biz/live.timeshift.fplayer.php', video_id,
|
'https://live.erinn.biz/live.timeshift.fplayer.php', video_id,
|
||||||
query={'hash': video_id},
|
'Downloading player html', 'Unable to download player html', query={'hash': video_id})
|
||||||
note='Downloading player html',
|
|
||||||
errnote='Unable to download player html')
|
|
||||||
|
|
||||||
sources_json = self._search_json(
|
sources = traverse_obj(self._search_json(
|
||||||
r'var\s+fplayer_source\s*=', player_html, 'stream data', video_id,
|
r'var\s+fplayer_source\s*=', player_html, 'stream data', video_id,
|
||||||
contains_pattern=r'\[(?s:.+)\]', transform_source=js_to_json)
|
contains_pattern=r'\[(?s:.+)\]', transform_source=js_to_json), lambda _, v: v['file'])
|
||||||
|
|
||||||
def parse_segment(segment, segment_id, segment_title):
|
def entries(segments, playlist=True):
|
||||||
path = segment.get('file')
|
for i, segment in enumerate(segments, 1):
|
||||||
if not path:
|
yield {
|
||||||
return None
|
'id': f'{video_id}_{i}' if playlist else video_id,
|
||||||
formats = [{
|
'title': f'{title} (Part {i})' if playlist else title,
|
||||||
'url': urljoin('https://live.erinn.biz', path),
|
|
||||||
'ext': 'mp4',
|
|
||||||
'protocol': 'm3u8_native',
|
|
||||||
}]
|
|
||||||
return {
|
|
||||||
'id': segment_id,
|
|
||||||
'title': segment_title,
|
|
||||||
'description': description,
|
'description': description,
|
||||||
'timestamp': traverse_obj(segment, ('time_start', {int_or_none})),
|
'timestamp': traverse_obj(segment, ('time_start', {int_or_none})),
|
||||||
'thumbnail': thumbnail,
|
'thumbnail': thumbnail,
|
||||||
'formats': formats,
|
'formats': [{
|
||||||
|
'url': urljoin('https://live.erinn.biz', segment['file']),
|
||||||
|
'ext': 'mp4',
|
||||||
|
'protocol': 'm3u8_native',
|
||||||
|
}],
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sources_json) == 1:
|
if len(sources) == 1:
|
||||||
return parse_segment(sources_json[0], video_id, title)
|
return next(entries(sources, playlist=False))
|
||||||
|
|
||||||
entries = []
|
return self.playlist_result(entries(sources), video_id, title, description, multi_video=True)
|
||||||
for i, segment in enumerate(sources_json):
|
|
||||||
if entry := parse_segment(segment, f'{video_id}_{i}', f'{title} (Part {i + 1})'):
|
|
||||||
entries.append(entry)
|
|
||||||
return self.playlist_result(entries, video_id, title, description, multi_video=True)
|
|
||||||
|
|
||||||
raise ExtractorError('Could not detect media type')
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user