radiko 録音用 shell scriptの修正・見直し(2025/06/09修正)
June 9, 2025 – 5:16 pm6月30日からradikoの録音ができなくなった。
前回(2025/03/07)に加えて、再びshell script のなかのstream uriを設定する部分が変更されているようだった。
いろいろ調べてみると、uru2/radishで障害に対応するかたちで修正されていたので、ここで公開されているスクリプト radi.sh のradiko部分を借用するかたちで、いままでと同様な入出力になるようスクリプトを書き直した。
更新後のshell scriptのsourceは以下:
#!/bin/bash LANG=ja_JP.utf8 pid=$$ date=`date '+%Y-%m-%d-%H:%M'` outdir="." if [ $# -le 1 ]; then echo "usage : $0 channel_name duration(minuites) [outputdir] [prefix]" exit 1 fi if [ $# -ge 2 ]; then channel=$1 DURATION=`expr $2 \* 60` fi if [ $# -ge 3 ]; then outdir=$3 fi PREFIX=${channel} if [ $# -ge 4 ]; then PREFIX=$4 fi ####################################### # Radiko Login # Arguments: # Mail address # Password # Returns: # 0: Success # 1: Failed ####################################### login_radiko() { mail=$1 password=$2 # Login login_json=$(curl \ --silent \ --request POST \ --data-urlencode "mail=${mail}" \ --data-urlencode "pass=${password}" \ --output - \ "https://radiko.jp/ap/member/webapi/member/login") # Extract login result radiko_session=$(echo "${login_json}" | jq -r ".radiko_session") areafree=$(echo "${login_json}" | jq -r ".areafree") # Check login if [ -z "${radiko_session}" ] || [ "${areafree}" != "1" ]; then return 1 fi echo "${radiko_session}" return 0 } ####################################### # Radiko Logout # Arguments: # radiko Session # Returns: # None ####################################### logout_radiko() { radiko_session=$1 # Logout curl \ --silent \ --request POST \ --data-urlencode "radiko_session=${radiko_session}" \ --output /dev/null \ "https://radiko.jp/v4/api/member/logout" } ####################################### # Authorize radiko # Arguments: # radiko Session # Returns: # 0: Success # 1: Failed ####################################### radiko_authorize() { radiko_session=$1 # Define authorize key value (from https://radiko.jp/apps/js/playerCommon.js) RADIKO_AUTHKEY_VALUE="bcd151073c03b352e1ef2fd66c32209da9ca0afa" # Authorize 1 auth1_res=$(curl \ --silent \ --header "X-Radiko-App: pc_html5" \ --header "X-Radiko-App-Version: 0.0.1" \ --header "X-Radiko-Device: pc" \ --header "X-Radiko-User: dummy_user" \ --dump-header - \ --output /dev/null \ "https://radiko.jp/v2/api/auth1") # Get partial key authtoken=$(echo "${auth1_res}" | awk 'tolower($0) ~/^x-radiko-authtoken: / {print substr($0,21,length($0)-21)}') keyoffset=$(echo "${auth1_res}" | awk 'tolower($0) ~/^x-radiko-keyoffset: / {print substr($0,21,length($0)-21)}') keylength=$(echo "${auth1_res}" | awk 'tolower($0) ~/^x-radiko-keylength: / {print substr($0,21,length($0)-21)}') if [ -z "${authtoken}" ] || [ -z "${keyoffset}" ] || [ -z "${keylength}" ]; then return 1 fi partialkey=$(echo "${RADIKO_AUTHKEY_VALUE}" | dd bs=1 "skip=${keyoffset}" "count=${keylength}" 2> /dev/null | base64) # Authorize 2 auth2_url_param="" if [ -n "${radiko_session}" ]; then auth2_url_param="?radiko_session=${radiko_session}" fi curl \ --silent \ --header "X-Radiko-Device: pc" \ --header "X-Radiko-User: dummy_user" \ --header "X-Radiko-AuthToken: ${authtoken}" \ --header "X-Radiko-PartialKey: ${partialkey}" \ --output /dev/null \ "https://radiko.jp/v2/api/auth2${auth2_url_param}" ret=$? if [ ${ret} -ne 0 ]; then return 1 fi echo "${authtoken}" return 0 } ####################################### # Get radiko HLS streaming URI # Arguments: # Station ID # radiko login status # Returns: # None ####################################### get_hls_uri_radiko() { station_id=$1 radiko_login_status=$2 areafree="0" if [ "${radiko_login_status}" = "1" ]; then areafree="1" fi uri=$(curl --silent "https://radiko.jp/v3/station/stream/pc_html5/${station_id}.xml" | xmllint --xpath "/urls/url[@timefree='0' and @areafree='${areafree}'][playlist_create_url[not(contains(text(),'_definst_'))]][2]/playlist_create_url/text()" - | sed 's/\&/\&/g' 2> /dev/null) echo "${uri}?station_id=${station_id}&l=15&type=c&lsid=" } ##### Main routine start ##### playlist_uri="" radiko_authtoken="" # radiko radiko_session="" radiko_login_status="0" # Login radiko premium if [ -n "${login_id}" ]; then radiko_session=$(login_radiko "${login_id}" "${login_password}") ret=$? if [ ${ret} -ne 0 ]; then echo "Cannot login radiko premium" >&2 exit 1 fi # Register radiko logout handler trap "logout_radiko ""${radiko_session}""" EXIT HUP INT QUIT TERM radiko_login_status="1" fi # Authorize radiko_authtoken=$(radiko_authorize "${radiko_session}") ret=$? if [ ${ret} -ne 0 ]; then echo "radiko authorize failed" >&2 exit 1 fi #playlist_uri=$(get_hls_uri_radiko "${station_id}" "${radiko_login_status}") playlist_uri=$(get_hls_uri_radiko "${channel}" "${radiko_login_status}") if [ -z "${playlist_uri}" ]; then echo "Cannot get playlist URI" >&2 exit 1 fi # # ffmpeg # ffmpeg \ -loglevel error \ -fflags +discardcorrupt \ -headers "X-Radiko-Authtoken: ${radiko_authtoken}" \ -i "${playlist_uri}" \ -acodec copy \ -vn \ -bsf:a aac_adtstoasc \ -y \ -t ${DURATION} \ "/tmp/${channel}_${date}.m4a" #ffmpeg -loglevel quiet -y -i "/tmp/${channel}_${date}.m4a" -acodec libmp3lame -ab 128k "${outdir}/${PREFIX}_${date}.mp3" ffmpeg -i "/tmp/${channel}_${date}.m4a" -acodec libmp3lame -ab 128k "/var/www/test/audio/${channel}_${date}.mp3" if [ $? = 0 ]; then rm -f "/tmp/${channel}_${date}.m4a" fi