radikoのタイムフリー&エリアフリーを保存する(ruby版)

以前にradikoのタイムフリー&エアフリーを保存するする手順を書きましたが、今回はRuby版です。

環境

  • macOS Mojava
  • ruby 2.5
  • 事前にffmpegとswftoolsを導入しておく
  • httpclient gemをインストールしておく

事前準備

myplayer-release.swfのダウンロード

認証のための事前準備としてswfファイルをダウンロードする

$ curl -O http://radiko.jp/apps/js/flash/myplayer-release.swf

swfファイルから画像ファイルを取り出す

認証にキーとなる画像ファイルをswfextractで取り出す

$ swfextract myplayer-release.swf -b 12 -o authkey.png
$ ls authkey.png
authkey.png

実行方法

タイムフリー(エリア内)

$ ruby rec_radiko.rb --sid=LFR --ft=201812190000 --to=20181219010000

エリアフリー(mailとpassにプレミア登録している情報を設定する)

$ ruby rec_radiko.rb --sid=MBS --ft=201812190000 --to=20181219010000 --mail=hoge@example.com --pass=password

rec_radiko.rb

require 'optparse'
require 'date'
require 'httpclient'

M4A_FILE = DateTime.now.strftime('%Y%m%d%H%M%S') + ".m4a"

LOGIN_URL = 'https://radiko.jp/ap/member/login/login'
LOGIN_CHECK_URL = 'https://radiko.jp/ap/member/webapi/member/login/check'
AUTH1_URL = 'https://radiko.jp/v2/api/auth1_fms'
AUTH2_URL = 'https://radiko.jp/v2/api/auth2_fms'

params = ARGV.getopts("", "sid:", "ft:", "to:", "mail:", "pass:")

if params["sid"] == nil || params["ft"] == nil || params["to"] == nil
    puts "Usage: ruby rec_radiko.rb --sid=<station id> --ft=<start time> --to=<end time> --mail=<mail address --pass=<password>"
    exit
end

sid = params["sid"]
ft = params["ft"]
to = params["to"]

PLAYLIST_URL = "https://radiko.jp/v2/api/ts/playlist.m3u8?station_id=#{sid}&l=15&ft=#{ft}&to=#{to}"

mail = params["mail"]
pass = params["pass"]

client = HTTPClient.new

header = { \
    'Content-Type' => 'application/x-www-form-urlencoded', \
    'Referer' =>  'http://radiko.jp/', \
    'Pragma' => 'no-cache', \
    'User-Agent' =>  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30', \
    'X-Radiko-Device' => 'pc', \
    'X-Radiko-App-Version' =>  '4.0.0', \
    'X-Radiko-User' =>  'test-stream', \
    'X-Radiko-App' => 'pc_ts' \
    }

# premium login
if mail != nil && pass != nil
    res = client.post(LOGIN_URL, {'mail' => mail, 'pass' => pass}, header)
    res = client.get(LOGIN_CHECK_URL, nil, header)
    if HTTP::Status.successful?(res.code) != true
        puts "Login failed"
        exit 1
    end
    puts "Login Succeed"
end

# Authentication 1
res = client.post(AUTH1_URL, nil, header)
if HTTP::Status.successful?(res.code) != true
    puts "Auth1 failed"
    exit 1
end
puts "Auth1 Succeed"

# X-Radiko-AuthToken が大文字の場合と小文字の場合があるため両方に対応
if res.headers['X-Radiko-AuthToken'] != nil
    header['X-Radiko-Authtoken'] = res.headers['X-Radiko-AuthToken']
elsif res.headers['X-RADIKO-AUTHTOKEN'] != nil
    header['X-Radiko-Authtoken'] = res.headers['X-RADIKO-AUTHTOKEN']
else
    puts "X-Radiko-AuthToken not found"
    exit 1
end
    
header['X-Radiko-Partialkey'] = `dd if=authkey.png ibs=1 skip=#{res.headers['X-Radiko-KeyOffset']} count=#{res.headers['X-Radiko-KeyLength']} 2>/dev/null | base64`.chomp

# Authentication 2
res = client.post(AUTH2_URL, nil, header)
if HTTP::Status.successful?(res.code) != true
    puts "Auth2 failed"
    exit 1
end
puts "Auth2 Succeed"

# ffmpegで保存
ffmpeg = "ffmpeg \
-content_type 'application/x-www-form-urlencoded' \
-headers 'Referer: http://radiko.jp/' \
-headers 'Pragma: no-cache' \
-headers 'X-Radiko-AuthToken: #{header['X-Radiko-Authtoken']}' \
-user_agent 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30' \
-i '#{PLAYLIST_URL}' \
-vn -acodec copy -bsf aac_adtstoasc #{M4A_FILE}"

`#{ffmpeg}`

コメント

タイトルとURLをコピーしました