diff options
-rw-r--r-- | yt_dlp_plugins/extractor/radiko.py | 23 | ||||
-rw-r--r-- | yt_dlp_plugins/extractor/radiko_hacks.py | 41 |
2 files changed, 59 insertions, 5 deletions
diff --git a/yt_dlp_plugins/extractor/radiko.py b/yt_dlp_plugins/extractor/radiko.py index c9d2756..e371878 100644 --- a/yt_dlp_plugins/extractor/radiko.py +++ b/yt_dlp_plugins/extractor/radiko.py @@ -21,6 +21,7 @@ from yt_dlp.utils import ( ) import yt_dlp_plugins.extractor.radiko_time as rtime +import yt_dlp_plugins.extractor.radiko_hacks as hacks class _RadikoBaseIE(InfoExtractor): @@ -287,7 +288,6 @@ class _RadikoBaseIE(InfoExtractor): preference = -1 entry_protocol = 'm3u8' - if domain in self._DOESNT_WORK_WITH_FFMPEG and do_blacklist_streams: self.write_debug(f"skipping {domain} (known not working)") continue @@ -297,10 +297,23 @@ class _RadikoBaseIE(InfoExtractor): preference = 1 entry_protocol = None - formats += self._extract_m3u8_formats( - playlist_url, station, m3u8_id=domain, fatal=False, headers=auth_data["token"], - live=delivered_live, preference=preference, entry_protocol=entry_protocol, - note=f"Downloading m3u8 information from {domain}") + if delivered_live and timefree: + chunks = hacks._generate_as_live_chunks(playlist_url, start_at, end_at) + + formats.append({ + "url": playlist_url, # fallback to live for ffmpeg etc + "format_id": join_nonempty(domain, "chunked"), + "live": False, + "hls_media_playlist_data": hacks._playlist_from_chunks(self, chunks, domain, auth_data["token"]), + "preference": preference, + "ext": "m4a", + }) + else: + + formats += self._extract_m3u8_formats( + playlist_url, station, m3u8_id=domain, fatal=False, headers=auth_data["token"], + live=delivered_live, preference=preference, entry_protocol=entry_protocol, + note=f"Downloading m3u8 information from {domain}") return formats diff --git a/yt_dlp_plugins/extractor/radiko_hacks.py b/yt_dlp_plugins/extractor/radiko_hacks.py new file mode 100644 index 0000000..7b20654 --- /dev/null +++ b/yt_dlp_plugins/extractor/radiko_hacks.py @@ -0,0 +1,41 @@ +import datetime + +from yt_dlp.extractor.common import InfoExtractor +from yt_dlp.utils import ( + join_nonempty, + update_url_query, + traverse_obj, +) + +# "hacks" as in great jank/schizo shit that works anyway + +def _generate_as_live_chunks(playlist_url, start_at, end_at): + chunks = [] + chunk_length = 300 # max the api allows + + duration = int(end_at.timestamp() - start_at.timestamp()) + cursor = 0 + while cursor < duration: + chunk_length = min(chunk_length, duration - cursor) + chunk_start = start_at + datetime.timedelta(seconds=cursor) + chunk_url = update_url_query(playlist_url, { + "seek": chunk_start.timestring(), + "l": chunk_length, + }) + chunks.append(chunk_url) + cursor += chunk_length + + return chunks + +def _playlist_from_chunks(self, chunks, src_id, headers={}): + playlist = "" + for i, chunk in enumerate(chunks): + i +=1 # for more friendly cli output, it gets reset each loop so it shouldnt effect anything + chunk_id = join_nonempty(src_id, i) + base_format = self._extract_m3u8_formats( + chunk, chunk_id, fatal=False, headers=headers, + note=f"Preparing {src_id} chunk {i}" + ) + m3u8_url = traverse_obj(base_format, (..., "url",), get_all=False) + playlist += self._download_webpage(m3u8_url, chunk_id, note=f"Getting {src_id} chunk {i} fragments") + return playlist |