radiko 録音用 shell scriptの修正・見直し(2025/06/09修正)

June 9, 2025 – 5:16 pm

6月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

  


Post a Comment