Skip to content

Instantly share code, notes, and snippets.

@NorimasaNabeta
Forked from saitodev/get_authkey.sh
Created December 22, 2015 00:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NorimasaNabeta/4dd21f621baf38c91b00 to your computer and use it in GitHub Desktop.
Save NorimasaNabeta/4dd21f621baf38c91b00 to your computer and use it in GitHub Desktop.
ネットラジオを聴くためのスクリプト。Python製
#!/bin/bash
# -*- coding: utf-8 -*-
PLAYER_URL='http://radiko.jp/player/swf/player_4.1.0.00.swf'
wget $PLAYER_URL -O player.swf
swfextract -b 14 -o authkey.png player.swf
rm -f player.swf
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import os
import base64
import urllib2
import subprocess
class Base(object):
def wait(self):
self.process.communicate()
return
class Radiko(Base):
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
AUTHKEY = os.path.join(BASE_DIR, 'authkey.png')
PLAYER_URL = 'http://radiko.jp/player/swf/player_4.1.0.00.swf'
AUTH1_FMS_URL = 'https://radiko.jp/v2/api/auth1_fms'
AUTH2_FMS_URL = 'https://radiko.jp/v2/api/auth2_fms'
def __init__(self, time, channel):
self.set_default_header()
authtoken, partialkey = self.auth1_fms()
self.auth2_fms(authtoken, partialkey)
self.start_rtmpdump(time, channel, authtoken)
return
def set_default_header(self):
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7'),
('X-Radiko-App', 'pc_1'),
('X-Radiko-App-Version', '2.0.1'),
('X-Radiko-User', 'text-stream'),
('X-Radiko-Device', 'pc'),]
urllib2.install_opener(opener)
return
def auth1_fms(self):
url = self.AUTH1_FMS_URL
data = '\r\n'
req = urllib2.Request(url, data)
text = urllib2.urlopen(req).read()
dct = dict()
for line in text.split('\n'):
if line.find('=') != -1:
key, value = line.rstrip().split('=')
dct[key] = value
authtoken = dct['X-Radiko-AuthToken']
key_offset = int(dct['X-Radiko-KeyOffset'])
key_length = int(dct['X-Radiko-KeyLength'])
with open(self.AUTHKEY, 'rb') as fin:
fin.seek(key_offset)
partialkey = base64.b64encode(fin.read(key_length))
return authtoken, partialkey
def auth2_fms(self, authtoken, partialkey):
url = self.AUTH2_FMS_URL
data = '\r\n'
req = urllib2.Request(url, data)
req.add_header('X-Radiko-Authtoken', authtoken)
req.add_header('X-Radiko-Partialkey', partialkey)
text = urllib2.urlopen(req).read()
return
def start_rtmpdump(self, time, channel, authtoken):
time = str(time)
timeout = str(30)
url = 'rtmpe://w-radiko.smartstream.ne.jp/{0}/_definst_/simul-stream.stream'.format(channel)
args = ['rtmpdump',
'-B', time,
'-m', timeout,
'-r', url,
'-W', self.PLAYER_URL,
'--live',
'--quiet',
'-C', 'S:""',
'-C', 'S:""',
'-C', 'S:""',
'-C', 'S:{0}'.format(authtoken),
'-o', '-',
]
self.process = subprocess.Popen(args, stdout=subprocess.PIPE)
return
@classmethod
def available_channels(cls):
return ('ABC', # ABCラジオ
'MBS', # MBSラジオ
'OBC', # ラジオ大阪
'CCL', # FM COCOLO
'802', # FM 802
'FMO', # FM OSAKA
)
class NhkNetRadio(Base):
CHANNEL_TO_RTMP = {'NHK1' : 'rtmpe://netradio-r1-flash.nhk.jp',
'NHK2' : 'rtmpe://netradio-r2-flash.nhk.jp',
'NHKFM' : 'rtmpe://netradio-fm-flash.nhk.jp',
}
CHANNEL_TO_PLAYPATH = {'NHK1' : 'NetRadio_R1_flash@63346',
'NHK2' : 'NetRadio_R2_flash@63342',
'NHKFM' : 'NetRadio_FM_flash@63343',
}
def __init__(self, time, channel):
time = str(time)
timeout = str(30)
args = ['rtmpdump',
'-B', time,
'-m', timeout,
'-r', self.CHANNEL_TO_RTMP[channel],
'-W', 'http://www3.nhk.or.jp/netradio/files/swf/rtmpe.swf',
'--playpath', self.CHANNEL_TO_PLAYPATH[channel],
'--app', 'live',
'--live',
'--quiet',
'-o', '-',
]
self.process = subprocess.Popen(args, stdout=subprocess.PIPE)
return
@classmethod
def available_channels(cls):
return ('NHK1', 'NHK2', 'NHKFM')
class MPlayer(Base):
def __init__(self, src):
args = ['mplayer', '-really-quiet', '-']
self.process = subprocess.Popen(args, stdin=src.process.stdout)
return
SRC_CLASSES = (Radiko, NhkNetRadio)
CHANNEL_TO_CLASS = dict()
for cls in SRC_CLASSES:
for channel in cls.available_channels():
CHANNEL_TO_CLASS[channel] = cls
def get_source(channel, time):
return CHANNEL_TO_CLASS[channel](time, channel)
def usage():
print('usage: {0} channel time'.format(__file__))
print('available channels:')
for key in sorted(CHANNEL_TO_CLASS.keys()):
print(' ' + key)
return
def main():
if len(sys.argv) < 3:
usage()
sys.exit(0)
channel = sys.argv[1]
time = sys.argv[2]
src = get_source(channel, time)
dst = MPlayer(src)
dst.wait()
src.wait()
return
if __name__ == '__main__':
main()
@NorimasaNabeta
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment