Compare commits

..

2 Commits

Author SHA1 Message Date
DmitryScaletta
b6668a4ea0
[KukuluLive] Handle playlists for VODs 2024-01-08 23:32:44 +03:00
DmitryScaletta
e474be6b38
[KukuluLive] Improve formats 2024-01-08 23:10:33 +03:00

View File

@ -4,8 +4,12 @@ from ..utils import (
clean_html, clean_html,
get_element_by_id, get_element_by_id,
urljoin, urljoin,
js_to_json,
traverse_obj,
int_or_none,
url_or_none,
) )
from ..compat import compat_parse_qs from urllib.parse import parse_qs
class KukuluLiveIE(InfoExtractor): class KukuluLiveIE(InfoExtractor):
@ -26,39 +30,32 @@ class KukuluLiveIE(InfoExtractor):
}, },
note=f'Downloading {description} quality metadata', note=f'Downloading {description} quality metadata',
errnote=f'Unable to download {description} quality metadata') errnote=f'Unable to download {description} quality metadata')
return compat_parse_qs(qs) return parse_qs(qs)
def _add_quality_formats(self, formats, quality_meta): def _add_quality_formats(self, formats, quality_meta):
vcodec = quality_meta.get('vcodec')[0] vcodec = traverse_obj(quality_meta, ('vcodec', 0))
quality = quality_meta.get('now_quality')[0] quality = traverse_obj(quality_meta, ('now_quality', 0))
quality_priority = { quality_priority = {
'high': 3, 'high': 3,
'h264': 2, 'h264': 2,
'low': 1, 'low': 1,
} }.get(quality, 0)
formats.extend([ if traverse_obj(quality_meta, ('hlsaddr', 0, {url_or_none})):
{ formats.append({
'format_id': quality, 'format_id': quality,
'url': quality_meta.get('hlsaddr')[0], 'url': quality_meta['hlsaddr'][0],
'ext': 'mp4', 'ext': 'mp4',
'vcodec': vcodec, 'vcodec': vcodec,
'quality': quality_priority[quality], 'quality': quality_priority,
}, })
{ if traverse_obj(quality_meta, ('hlsaddr_audioonly', 0, {url_or_none})):
'format_id': f'{quality}-rtmp', formats.append({
'url': quality_meta.get('streamaddr')[0],
'ext': 'mp4',
'vcodec': vcodec,
'quality': quality_priority[quality] - 5,
},
{
'format_id': f'{quality}-audioonly', 'format_id': f'{quality}-audioonly',
'url': quality_meta.get('hlsaddr_audioonly')[0], 'url': quality_meta['hlsaddr_audioonly'][0],
'ext': 'aac', 'ext': 'm4a',
'vcodec': 'none', 'vcodec': 'none',
'quality': quality_priority[quality] - 10, 'quality': quality_priority,
}, })
])
def _real_extract(self, url): def _real_extract(self, url):
video_id = self._match_id(url) video_id = self._match_id(url)
@ -100,26 +97,38 @@ class KukuluLiveIE(InfoExtractor):
note='Downloading player html', note='Downloading player html',
errnote='Unable to download player html') errnote='Unable to download player html')
# https://regex101.com/r/3AXpSA/3 sources_json = self._search_json(
sources = self._search_regex(r'var fplayer_source = ([^;]+)', player_html, 'sources') r'var\s+fplayer_source\s*=', player_html, 'stream data', video_id,
sources_json = self._parse_json(sources.replace('.mp4",', '.mp4"'), video_id) contains_pattern=r'\[(?s:.+)\]', transform_source=js_to_json)
formats = [] def _parse_segment(segment, id, title):
for source in sources_json: path = segment.get('file')
path = source.get('file') if not path:
formats.append({ return None
formats = [{
'url': urljoin('https://live.erinn.biz', path), 'url': urljoin('https://live.erinn.biz', path),
'ext': 'mp4', 'ext': 'mp4',
'protocol': 'm3u8_native', 'protocol': 'm3u8_native',
}) }]
return { return {
'id': video_id, 'id': id,
'title': title, 'title': title,
'description': description, 'description': description,
'timestamp': sources_json[0].get('time_start'), 'timestamp': traverse_obj(segment, ('time_start', {int_or_none})),
'thumbnail': thumbnail, 'thumbnail': thumbnail,
'formats': formats, 'formats': formats,
} }
raise ExtractorError('Cannot parse live stream or VOD', expected=True) is_playlist = len(sources_json) > 1
if is_playlist:
entries = []
for i, segment in enumerate(sources_json):
entry = _parse_segment(segment, f'{video_id}_{i}', f'{title} (Part {i + 1})')
if not entry:
continue
entries.append(entry)
return self.playlist_result(entries, video_id, title, description, multi_video=True)
else:
return _parse_segment(sources_json[0], video_id, title)
raise ExtractorError('Could not detect media type')