1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
import re
from yt_dlp.utils import (
clean_html,
join_nonempty,
traverse_obj,
update_url_query
)
import yt_dlp_plugins.extractor.radiko_time as rtime
from yt_dlp_plugins.extractor.radiko import _RadikoBaseIE, RadikoTimeFreeIE
class _RadikoMobileBaseIE(_RadikoBaseIE):
_MOBILE_USER_AGENT = 'Mozilla/5.0 (Linux; Android 10; Pixel 4 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Mobile Safari/537.36'
def _get_nextjs_data(self, url, video_id):
html = self._download_webpage(url, video_id, headers={"User-Agent": self._MOBILE_USER_AGENT})
data = self._search_nextjs_data(html, video_id)
return traverse_obj(data, ("props", "pageProps")), data
def _get_station_region(self, station):
api_url = update_url_query("https://radiko.jp/api/stations/batchGetStations", {"stationId": station})
data = self._download_json(api_url, station, note="Getting station regions")
return traverse_obj(data, ("stationList", lambda _, v: v["id"] == station, "prefecturesList"), get_all=False)
_extract_chapters = RadikoTimeFreeIE._extract_chapters
class RadikoMobileEventIE(_RadikoMobileBaseIE):
_VALID_URL = r"https?://(?:www\.)?radiko\.jp/mobile/events/(?P<id>[0-9-]+$)"
def _get_programme_meta(self, program, actors=None):
if actors is not None:
cast = []
for actor_id in program.get("actorIdsList"):
cast.append(traverse_obj(actors, ("actorsList", lambda _, v: v["key"] == actor_id, "name"), get_all=None))
else:
cast = traverse_obj(program, (
'performer', {lambda x: re.split(r'[//、 ,,]', x)}, ..., {str.strip})) or None
start = traverse_obj(program, ("startAt", "seconds"))
end = traverse_obj(program, ("endAt", "seconds"))
return {
**traverse_obj(program, {
"id": "id",
"title": "title",
"series": "rSeasonName",
"tags": "tagsList",
"thumbnail": "imageUrl",
"channel": "stationName",
"channel_id": "stationId",
"uploader": "stationName",
"uploader_id": "stationId",
}),
"description": clean_html(join_nonempty("summary", "description", from_dict=program, delim="\n")),
"cast": cast,
"timestamp": start,
"release_timestamp": end,
"duration": end - start,
}
def _real_extract(self, url):
event_id = self._match_id(url)
pageProps, _ = self._get_nextjs_data(url, event_id)
meta = self._get_programme_meta(pageProps.get("program"), pageProps.get("actors"))
station = meta.get("channel_id")
start = rtime.RadikoTime.fromtimestamp(meta.get("timestamp"), tz=rtime.JST)
end = rtime.RadikoTime.fromtimestamp(meta.get("release_timestamp"), tz=rtime.JST)
chapters = self._extract_chapters(station, start, end, video_id=meta["id"])
area = self._get_station_region(station)[0]
auth_data = self._auth(area)
formats = self._get_station_formats(station, True, auth_data, start_at=start, end_at=end)
return {
**meta,
"chapters": chapters,
"formats": formats,
"live_status": "was_live",
"container": "m4a_dash", # force fixup, AAC-only HLS
}
|