summaryrefslogtreecommitdiffstatshomepage
path: root/yt_dlp_plugins/extractor/radiko.py
diff options
context:
space:
mode:
Diffstat (limited to 'yt_dlp_plugins/extractor/radiko.py')
-rwxr-xr-xyt_dlp_plugins/extractor/radiko.py97
1 files changed, 88 insertions, 9 deletions
diff --git a/yt_dlp_plugins/extractor/radiko.py b/yt_dlp_plugins/extractor/radiko.py
index 651a6f1..2a942b8 100755
--- a/yt_dlp_plugins/extractor/radiko.py
+++ b/yt_dlp_plugins/extractor/radiko.py
@@ -1,4 +1,5 @@
import base64
+import datetime
import random
import secrets
import urllib.parse
@@ -533,11 +534,14 @@ class RadikoLiveIE(RadikoBaseIE):
'id': 'FMT',
'ext': 'm4a',
'live_status': 'is_live',
- 'filename': 'test_RadikoLive_FMT.m4a',
'alt_title': 'TOKYO FM',
'title': 're:^TOKYO FM.+$',
'thumbnail': 'https://radiko.jp/res/banner/FMT/20220512162447.jpg',
'uploader_url': 'https://www.tfm.co.jp/',
+ 'channel_url': 'https://www.tfm.co.jp/',
+ 'channel': 'TOKYO FM',
+ 'channel_id': 'FMT',
+
},
}, {
# JP1 (Hokkaido)
@@ -550,6 +554,9 @@ class RadikoLiveIE(RadikoBaseIE):
'title': 're:^FM NORTH WAVE.+$',
'live_status': 'is_live',
'thumbnail': 'https://radiko.jp/res/banner/NORTHWAVE/20150731161543.png',
+ 'channel': 'FM NORTH WAVE',
+ 'channel_url': 'https://www.fmnorth.co.jp/',
+ 'channel_id': 'NORTHWAVE',
},
}, {
# ALL (all prefectures)
@@ -563,6 +570,9 @@ class RadikoLiveIE(RadikoBaseIE):
'uploader_url': 'https://www.ouj.ac.jp/',
'alt_title': 'HOUSOU-DAIGAKU',
'thumbnail': 'https://radiko.jp/res/banner/HOUSOU-DAIGAKU/20150805145127.png',
+ 'channel': '放送大学',
+ 'channel_url': 'https://www.ouj.ac.jp/',
+ 'channel_id': 'HOUSOU-DAIGAKU',
},
}]
@@ -621,24 +631,92 @@ class RadikoTimeFreeIE(RadikoBaseIE):
'tags': ['ノースウェーブ', '角松敏生', '人気アーティストトーク'],
'cast': ['角松\u3000敏生'],
'series': '角松敏生 My BLUES LIFE',
- 'description': 'md5:bed1be17dd7d188a37d3fa998533b1ff',
+ 'description': 'md5:027860a5731c04779b6720047c7b8b59',
+ },
+ },{
+ # late-night show, see comment in _unfuck_day
+ 'url': 'https://radiko.jp/#!/ts/TBS/20230506030000',
+ 'info_dict': {
+ 'id': 'TBS-20230506030000',
+ 'ext': 'm4a',
+ 'title': 'CITY CHILL CLUB',
+ 'cast': ['イハラカンタロウ'],
+ 'thumbnail': 'https://radiko.jp/res/program/DEFAULT_IMAGE/TBS/xxeimdxszs.jpg',
+ 'description': 'md5:f60b1012f0606b336660416598d82043',
+ 'timestamp': 1683309600,
+ 'tags': ['CCC905', '音楽との出会いが楽しめる', '人気アーティストトーク', '音楽プロデューサー出演', 'ドライブ中におすすめ', '寝る前におすすめ', '学生におすすめ'],
+ 'channel': 'TBSラジオ',
+ 'uploader_url': 'https://www.tbsradio.jp/',
+ 'channel_id': 'TBS',
+ 'channel_url': 'https://www.tbsradio.jp/',
+ 'duration': 7200,
+ 'series': 'CITY CHILL CLUB',
+ 'upload_date': '20230505',
+ 'live_status': 'was_live',
+
+ },
+ },{
+ # early-morning show, same reason
+ 'url': 'https://radiko.jp/#!/ts/TBS/20230504050000',
+ 'info_dict':
+ {
+ 'title': '生島ヒロシのおはよう定食・一直線',
+ 'id': 'TBS-20230504050000',
+ 'ext': 'm4a',
+ 'upload_date': '20230503',
+ 'cast': ['生島\u3000ヒロシ', '齋藤\u3000孝'],
+ 'channel': 'TBSラジオ',
+ 'thumbnail': 'https://radiko.jp/res/program/DEFAULT_IMAGE/TBS/ch3vcvtc5e.jpg',
+ 'description': 'md5:26dba9e22df6883c072067cdc5ac0511',
+ 'series': '生島ヒロシのおはよう定食・一直線',
+ 'tags': ['生島ヒロシ', '健康', '檀れい', '朝のニュースを効率良く'],
+ 'channel_url': 'https://www.tbsradio.jp/',
+ 'uploader_url': 'https://www.tbsradio.jp/',
+ 'channel_id': 'TBS',
+ 'timestamp': 1683144000,
+ 'duration': 5400,
+ 'live_status': 'was_live',
},
}]
+ def _unfuck_day(self, time):
+ # api counts 05:00 -> 28:59 (04:59 next day) as all the same day
+ # like the 30-hour day, 06:00 -> 29:59 (05:59)
+ # https://en.wikipedia.org/wiki/Date_and_time_notation_in_Japan#Time
+ # but ends earlier, presumably so the early morning programmes dont look like late night ones
+ # this means we have to shift back by a day so we can use the right api
+
+ hour_mins = int(time[8:])
+ if hour_mins < 50000: # 050000 - 5AM
+ date = datetime.datetime(int(time[:4]), int(time[4:6]), int(time[6:8]),
+ hour=int(time[8:10]), minute=int(time[10:12]), second=int(time[12:14]))
+
+ date -= datetime.timedelta(days=1)
+ time = date.strftime("%Y%m%d")
+
+ return time
+ return time[:8]
+
def _get_programme_meta(self, station_id, start_time):
- date = start_time[:8]
- meta = self._download_json(f'https://radiko.jp/v4/program/station/date/{date}/{station_id}.json', station_id,
+ day = self._unfuck_day(start_time)
+ meta = self._download_json(f'https://radiko.jp/v4/program/station/date/{day}/{station_id}.json', station_id,
note="Downloading programme data")
programmes = traverse_obj(meta, ('stations', lambda _, v: v['station_id'] == station_id,
'programs', 'program'), get_all=False)
+
for prog in programmes:
if prog['ft'] == start_time:
+ if len(prog.get('person')) > 0:
+ cast = [person.get("name") for person in prog.get('person')]
+ else:
+ cast = [prog.get('performer')]
+
return {
'id': join_nonempty(station_id, start_time),
- 'timestamp': unified_timestamp(f'{start_time}+0900'), # hack to account for timezone
- 'live_status': 'was_live',
- 'cast': [person.get("name") for person in prog.get('person')],
- 'description': clean_html(f"{prog.get('summary')}\n{prog.get('description')}"),
+ 'release_timestamp': unified_timestamp(f'{start_time}+0900'), # hack to account for timezone
+ 'timestamp': unified_timestamp(f'{prog["to"]}+0900'),
+ 'cast': cast,
+ 'description': clean_html(join_nonempty('summary', 'description', from_dict=prog, delim='\n')),
**traverse_obj(prog, {
'title': 'title',
'duration': 'dur',
@@ -662,5 +740,6 @@ class RadikoTimeFreeIE(RadikoBaseIE):
'alt_title': None,
**meta,
'formats': formats,
-# 'is_live': True, # -blatant lie
+ 'live_status': 'was_live',
+ 'container': 'm4a_dash', # force fixup, AAC-only HLS
}