Radiko自動化プロジェクト / テック解説

「放送局のWebページURLを入力するだけで、自動的にメタデータが特定され、エリア制限をバイパスして、高速に番組音声がダウンロードされる」――本記事では、Radikoのタイムフリー閲覧URLからプレイリストを特定し、並列セグメント収集からffmpeg結合、さらには音声認識(Whisper)用ログ作成までを一貫して自動化するロジックの設計と検証プロセスを詳述します。

Radikoにはプレミアム(エリア外聴取)制限があり、通常はIP判定やユーザーログイン情報が要求されます。しかし、プレイヤーが内部的に発行しているAPIの検証を行うことで、日本全国のエリアコードと各局のIDさえ特定できていれば、ログイン不要で正しい認証トークンおよびm3u8ストリームを取得し、ダウンロードを行えることが実証されました。

一貫自動化処理のアーキテクチャ

閲覧URLから最終的な音声ファイル(M4A)を出力するまでの一連の処理は、以下の4つの主要フェーズに分かれています。

フェーズ 1:URL解析 入力されたタイムフリーURLやシェアURLから、放送局名(Station ID)放送開始日時(start_at)終了日時(end_at)を正規表現パターンマッチでロバストに切り出します。
フェーズ 2:メタデータ抽出 特定した放送局IDと日付をもとに、公式の番組表 XML API (radiko.jp/v3/program/date/...xml) を非同期で取得。番組タイトル、詳細説明(desc)、出演者(pfm)を自動で取得し、CSVデータベースに記録します。
フェーズ 3:Dynamic Authentication & エリアバイパス 部分的な認証鍵生成アルゴリズムを実行して一時的な X-Radiko-AuthToken を動的に取得。これと同時に、局IDに対応するエリアID(例:TBSラジオなら JP13)を事前定義マッピング辞書から解決し、エリア判定ヘッダに設定します。
フェーズ 4:並列ダウンロードと再構成 マスターm3u8から音声ストリームのプレイリストURLを引き出し、数秒単位に分割された音声セグメント(AAC)のリストを取得。複数ワーカーを用いて aria2c による並列ダウンロードを実行後、ffmpeg でコンテナ結合しメタデータを埋め込みます。

1. ロバストなURLパースと局特定

ユーザーがブラウザのロケーションバーからコピーするURLは多岐にわたります。以下の2つの主要なURLスキーマに対応できるようにしています。

  • 通常タイムシフトURL: https://radiko.jp/#!/ts/LFR/20260531120000
  • SNSシェア用URL: https://radiko.jp/share/?sid=LFR&t=20260531120000

正規表現を用いてこれらを正規化し、LFR(ニッポン放送)や 20260531120000(開始日時)を正確に取り出すことで、URL入力だけで動作する一貫性を確保しました。

2. ログイン不要のエリア制限バイパス

Radikoのエリア制限は、アクセス元のIPアドレスによって提供される局が制限される仕組みです。しかし、APIリクエスト時に以下のヘッダを付与することで、ログイン情報を送信することなく制限を回避できます。

headers = {
    "X-Radiko-AuthToken": authtoken,
    "X-Radiko-AreaId": area_id # 例: 関西局なら JP27, 関東局なら JP13
}

全国47都道府県の全加盟局(約100局)のIDに対応する適切なエリアIDを STATION_TO_AREA 辞書テーブルとしてハードコーディングすることで、どの局のURLが入力されても即座に最適な AreaId を自動設定して認証を通過することに成功しました。

3. 高速並列ダウンロードと進捗監視

ストリーミングのダウンロードにおいて、1つのコネクションで順次セグメントを取得すると時間がかかります。そこで、セグメントのURL一覧をすべて先んじて切り出し、aria2c を用いて最大16〜32の同時接続で並列取得を行います。

また、並列処理中の進行具合を可視化するため、別スレッドの進捗監視モニターを実装しました。一時フォルダにダウンロードされたセグメントの数 (*.aac) を定期的にカウントし、全セグメント数と比較することで、UI側へリアルタイムに進捗パーセンテージを通知します。

# 進捗監視ロジックの簡略化表現
total_segments = len(segment_urls)
while downloading:
    downloaded = len(glob.glob(os.path.join(temp_dir, "*.aac")))
    progress_pct = int((downloaded / total_segments) * 100)
    update_progress_to_csv(progress_pct)
    time.sleep(3)

4. 検証と安定性評価

本一貫ロジックの動作検証を行った結果、以下のような非常に安定したパフォーマンスが得られました。

  • 番組表XML連携: 特殊文字やHTMLタグが含まれる番組説明文も自動デコードおよびサニタイズされ、データベースおよびWebUIに正しく保管されることを確認。
  • 高速結合: 2時間の番組(約240セグメント)を並列処理で15秒以内にダウンロード完了し、ffmpegによる無劣化結合(-c copy)が完了。
  • エラー復旧: 何らかの理由でセグメントの一部に取得失敗が生じた場合も、自動リトライおよびエラーハンドラが動作し、中途半端な一時フォルダのゴミデータを残さない安全設計を確立。
本ロジックは、Radiko Fast Downloaderのコアエンジンである download_radiko.py に実装されており、WebUIとCLIの両方から呼び出すことが可能です。これにより、ラジオの録音からWhisperによる音素の文字起こしまで、スムーズに行える統合的な開発環境が完成しました。

まとめ: 閲覧URLのロバストな解析、47都道府県のマッピングテーブルによるエリア対応、並列ダウンロード、および番組表 XML API 連携の一貫ロジックにより、IP制限に縛られない安定した録音パイプラインが実現しました。この実装は、今後のラジオデータ解析プロジェクトの有用な基盤となります。