インターネット同時配信を調べた前回に引き続き、今回は
以前は、時間調整用の埋め草的な番組
また、従来は別ページで管理されていた語学講座や高校講座も同じページから利用できるようになり、一覧ページはずいぶん賑やかです。
「インスペクター」による調査
まずは前回同様、Firefoxの
表示画面の色を手掛かりに調べていくと、<div>タグ部で配信元のURLが見つかりました。以前は
<div class="nol_audio_player_base" data-hlsurl="https://vod-stream.nhk.jp/radioondemand/r/K7NR257MJ5/s/stream_K7NR257MJ5_dd92abfe668c31bb2f75f56b92ad6ec8/index.m3u8" data-aa="[radio]vod;名曲スケッチ 「波を越えて」「ドナウ川のさざ波」;r2,130;2025121666476;2025-12-16T09:45:00+09:00_2025-12-16T09:55:00+09:00"><a href="javascript:slidedownPlayer(0);">このページで再生</a></div>
“data-hlsurl”
配信元がわかったので、vlcを使って直接ダウンロードしてみたところ、最初のハンドシェイク時に多少のエラーは出るものの、特に問題なく配信データをダウンロードできました。下記の実行例では、
$ vlc --play-and-exit --intf dummy "https://vod-stream.nhk.jp/radioondemand/r/K7NR257MJ5/s/stream_K7NR257MJ5_dd92abfe668c31bb2f75f56b92ad6ec8/index.m3u8" --sout=file/ts:test_output.ts VLC media player 3.0.22-rc2 Vetinari (revision 3.0.22-rc2-3-g02102a8890) [0000000010d7e5a0] dummy interface: using the dummy interface module... [00007fcbf4007480] gnutls tls client error: TLS handshake error: Error in the push function. [00007fcbf4007480] main tls client error: TLS session handshake error ... [00007fcbf4232420] adaptive demux: Changing stream format Unknown -> Packed AAC [00007fcbec004cb0] mpeg4audio demux packetizer: AAC channels: 2 samplerate: 24000 [0000000010cf7e50] main playlist: end of playlist, exiting $ ls -lh test_output.ts -rw-r--r-- 1 kojima users 6.6M 12月 15日 19:47 test_output.ts $ file test_output.ts test_output.ts: MPEG transport stream data
前回紹介したラジオとの同時配信の場合、配信データはリアルタイムで流れてくるため、10分の番組を録音するには10分かかります。一方、聴き逃し配信ではあらかじめ用意されているデータを受け取るだけなので、ずっと短い時間で録音
「デバッガー」による聴き逃し配信の解析
とりあえず聴き逃し配信をダウンロードすることは可能になったものの、配信元URLを調べるために毎回インスペクターを立ち上げるのは面倒です。また、保存した録音データには番組情報等を記録しておきたいのがエアチェック・
デバッガーで調べたところ、聴き逃し配信の各ページは
/////////らじる★らじる 聴き逃し(詳細)/////////
var pagedomain = document.domain,
apipath = pagedomain.indexOf("stg-") > -1 || pagedomain.indexOf("pre-") > -1 || pagedomain.indexOf("dev-") > -1 || pagedomain.indexOf("ter-") > -1 ? "stg-" : "",
rapiuri = "https://www.nhk.or.jp/" + apipath + "radio-api/app/v1/web/ondemand/series?site_id={siteid}&corner_site_id={cornerid}",
itemperpage = 10,
途中の
さて、ここで指定する
$(function() {
if (getQuery("p")) {
var a = getQuery("p");
if (a.indexOf("_") > -1 && a.length < 14) {
var e = a.split("_");
$.getJSON(rapiuri.replace("{siteid}", e[0]).replace("{cornerid}", e[1]), function(s) {
ざっと見、クエリとして与えた
ということで、さっそくこのURIを叩いてみたところ、無事JSON形式で番組情報が返ってきました。
$ curl 'https://www.nhk.or.jp/radio-api/app/v1/web/ondemand/series?site_id=K7NR257MJ5&corner_site_id=01' | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 5301 100 5301 0 0 43230 0 --:--:-- --:--:-- --:--:-- 43450
{
"id": 174,
"title": "名曲スケッチ",
"radio_broadcast": "R2,FM",
"schedule": "【ラジオ第2】月・火・木・金 午前9時45分、午後10時00分 /土曜 午前8時30分、午前11時45分【NHK-FM】火曜~金曜 午前1時50分/土曜 午後0時15分、午後9時50分/日曜 午前5時40分",
"corner_name": "",
"thumbnail_url": "https://img.nhk.jp/static/assets/images/radioseries/rs/K7NR257MJ5/K7NR257MJ5-eyecatch_56ba75a4f8ae94f3bf0be92216135097.png",
"series_description": "「名曲アルバム」から生まれたラジオ番組。世界の名曲を2曲お届けします。",
"series_url": "https://www.nhk.jp/p/sketch/rs/K7NR257MJ5/",
"share_text_title": "名曲スケッチ",
"share_text_url": "https://www.nhk.or.jp/radioondemand/share/174_1389.html",
"share_text_description": "#radiru",
"episodes": [
{
"id": 4289434,
"program_title": "名曲スケッチ 「波を越えて」「ドナウ川のさざ波」",
"onair_date": "12月16日(火)午前9:45放送",
"closed_at": "2025年12月23日(火)午前9:55配信終了",
"stream_url": "https://vod-stream.nhk.jp/radioondemand/r/K7NR257MJ5/s/stream_K7NR257MJ5_dd92abfe668c31bb2f75f56b92ad6ec8/index.m3u8",
"aa_contents_id": "[radio]vod;名曲スケッチ 「波を越えて」「ドナウ川のさざ波」;r2,130;2025121666476;2025-12-16T09:45:00+09:00_2025-12-16T09:55:00+09:00",
"annotation_title": "",
"annotation_url": "",
"program_sub_title": " イヴァノヴィチ作曲、岩河三郎・編曲 (管弦楽)東京フィルハーモニー交響楽団 (指揮)渡邉暁雄"
},
{
"id": 4289203,
"program_title": "名曲スケッチ 「歌劇“椿姫”前奏曲」「歌劇“ノートルダム”間奏曲」",
"onair_date": "12月15日(月)午前9:45放送",
"closed_at": "2025年12月22日(月)午前9:55配信終了",
...
このように、番組IDを指定して番組情報DBのAPIを叩くと、”
Pythonを使った聴き逃し配信解析ツール
Pythonでは、HTTP回りの処理をするrequests、JSONデータを扱うjson等、豊富なモジュールが揃っています。とりあえず今回は
#!/usr/bin/python
#-*- coding: utf-8 -*-
import sys, requests, json
bangumi_id = sys.argv[1]
'''
p=K7NR257MJ5_01 みたいな指定の場合、'p='の部分をカットする
'''
if 'p=' in bangumi_id:
bangumi_id = bangumi_id.replace('p=','')
(pr, ser) = bangumi_id.split('_')
api_url = f"https://www.nhk.or.jp/radio-api/app/v1/web/ondemand/series?site_id={pr}&corner_site_id={ser}"
res = requests.get(api_url)
'''
週一の番組では'episodes'は一つだが、帯番組だと複数の番組情報が返るので、
とりあえず一覧しておく
'''
bangumi_info = res.json()['episodes']
print(f"bangumi count:{len(bangumi_info)}")
for i in range(len(bangumi_info)) :
print(f"title:{bangumi_info[i]['program_title']}")
print(f"date:{bangumi_info[i]['onair_date']}")
print(f"url:{bangumi_info[i]['stream_url']}")
print(f"subtitle:{bangumi_info[i]['program_sub_title']}")
print("")
このスクリプトを
$ python ./dl_test.py p=LG96ZW5KZ4_01 bangumi count:4 title:クラシックの庭 ヨハン・シュトラウスのワルツ「美しく青きドナウ」 date:12月17日(水)午後2:00放送 url:https://vod-stream.nhk.jp/radioondemand/r/LG96ZW5KZ4/s/stream_LG96ZW5KZ4_66adc770838490d5c05069b2aecd9116/index.m3u8 subtitle:登レイナ title:クラシックの庭 チャイコフスキーのピアノ協奏曲第2番 date:12月16日(火)午後2:00放送 url:https://vod-stream.nhk.jp/radioondemand/r/LG96ZW5KZ4/s/stream_LG96ZW5KZ4_6e810514ce557f3b1a990b223a5b1a6f/index.m3u8 subtitle:登レイナ title:クラシックの庭 ショスタコーヴィチのチェロ協奏曲第1番 date:12月15日(月)午後2:00放送 url:https://vod-stream.nhk.jp/radioondemand/r/LG96ZW5KZ4/s/stream_LG96ZW5KZ4_97908a3c6c1be032ed43c89a05bcd079/index.m3u8 subtitle:登レイナ title:クラシックの庭 ベートーベンの交響曲第6番「田園」 date:12月11日(木)午後2:00放送 url:https://vod-stream.nhk.jp/radioondemand/r/LG96ZW5KZ4/s/stream_LG96ZW5KZ4_8c033fbdb28646542514cf937897eaa2/index.m3u8 subtitle:田添菜穂子
得られたURLを元に、
今回は聴き逃し配信のページから番組IDを調べ、そのIDを元に番組情報データベースから配信元URLや番組タイトル等を得るあたりを調べてみました。とりあえずこれだけでもダウンローダーは書けるものの、しばらくイジっていると、楽曲情報や出演者等、より詳しい情報も拾ってみたくなります。次回はそのあたりの機能拡張について考えてみる予定です。
