ホーム > サーバ > とあるサイトの録音手段 (シェルスクリプト)

とあるサイトの録音手段 (シェルスクリプト)

2011 年 3 月 21 日 コメントをどうぞ コメント

13日にradikoが全国で聴取できるようになった事は記憶に新しいですが、
その仕様変更の際にRTMPDumpによるストリーミングの保存が不可能となってしまいました。

しかしながら、ネットのチカラは恐ろしいですね。
仕様変更に対応したシェルスクリプトが、saiten様により19日に公開されました。

簡易radiko録音ツール。要swftools

私もこちらのページを参考にSWFTOOLSを導入してみた所、
見事にストリーミングの保存が可能となりました。

ですが、上記のスクリプトだとリトライ機能が無いため
予約録音に失敗してしまう場合があります。

そこで、上記のスクリプトをベースに、いくつかの機能を追加してみました。


—–

SWFTOOLS・RTMPDump・FFmpegがインストールされていることを前提とします。
それぞれのインストール場所にあわせて、パスなどを書き換えてください。
(筆者はCentOS 5.5上での動作を確認しております。)

#!/bin/sh

if [ $# -eq 3 ]; then
  OUTFILEPREFIX=$1
  RECTIMEMIN=$2
  CHANNEL=$3
else
  echo "usage : $0 OUTFILEPREFIX RECTIMEMIN CHANNEL"
  exit 1
fi

OUTFILEPREFIX=$1
RECTIMEMIN=$2
CHANNEL=$3

RTMPDUMP=/path/to/rtmpdump
FFMPEG=/path/to/ffmpeg

OUTFILEBASEPATH=/path/to/radiko
OUTFILENAME=${OUTFILEBASEPATH}/${OUTFILEPREFIX}_`date +%Y-%m-%d`
FLVFILEEXT=".flv"
AACFILEEXT=".aac"

MARGINTIMEMIN=1
RECTIME=`expr ${RECTIMEMIN} \* 60 + ${MARGINTIMEMIN} \* 2 \* 60`

cd ${OUTFILEBASEPATH}

playerurl=http://radiko.jp/player/swf/player_2.0.1.00.swf
playerfile=./player.swf
keyfile=./authkey.png

#
# get player
#
if [ ! -f $playerfile ]; then
  wget -q -O $playerfile $playerurl

  if [ $? -ne 0 ]; then
    echo "failed get player"
    exit 1
  fi
fi

#
# get keydata (need swftools)
#
if [ ! -f $keyfile ]; then
  swfextract -b 5 $playerfile -o $keyfile

  if [ ! -f $keyfile ]; then
    echo "failed get keydata"
    exit 1
  fi
fi

if [ -f auth1_fms_${OUTFILEPREFIX}_${CHANNEL} ]; then
  rm -f auth1_fms_${OUTFILEPREFIX}_${CHANNEL}
fi

#
# access auth1_fms
#
wget -q \
     --header="pragma: no-cache" \
     --header="X-Radiko-App: pc_1" \
     --header="X-Radiko-App-Version: 2.0.1" \
     --header="X-Radiko-User: test-stream" \
     --header="X-Radiko-Device: pc" \
     --post-data='\r\n' \
     --no-check-certificate \
     --save-headers \
     --tries=5 \
     --timeout=5 \
     -O auth1_fms_${OUTFILEPREFIX}_${CHANNEL} \
     https://radiko.jp/v2/api/auth1_fms

if [ $? -ne 0 ]; then
  echo "failed auth1 process"
  exit 1
fi

#
# get partial key
#
authtoken=`cat auth1_fms_${OUTFILEPREFIX}_${CHANNEL} | perl -ne 'print $1 if(/x-radiko-authtoken: ([\w-]+)/i)'`
offset=`cat auth1_fms_${OUTFILEPREFIX}_${CHANNEL} | perl -ne 'print $1 if(/x-radiko-keyoffset: (\d+)/i)'`
length=`cat auth1_fms_${OUTFILEPREFIX}_${CHANNEL} | perl -ne 'print $1 if(/x-radiko-keylength: (\d+)/i)'`

partialkey=`dd if=$keyfile bs=1 skip=${offset} count=${length} 2> /dev/null | base64`

echo "authtoken: ${authtoken} \noffset: ${offset} length: ${length} \npartialkey: $partialkey"

rm -f auth1_fms_${OUTFILEPREFIX}_${CHANNEL}

if [ -f auth2_fms_${OUTFILEPREFIX}_${CHANNEL} ]; then
  rm -f auth2_fms_${OUTFILEPREFIX}_${CHANNEL}
fi

#
# access auth2_fms
#
wget -q \
     --header="pragma: no-cache" \
     --header="X-Radiko-App: pc_1" \
     --header="X-Radiko-App-Version: 2.0.1" \
     --header="X-Radiko-User: test-stream" \
     --header="X-Radiko-Device: pc" \
     --header="X-Radiko-Authtoken: ${authtoken}" \
     --header="X-Radiko-Partialkey: ${partialkey}" \
     --post-data='\r\n' \
     --no-check-certificate \
     --tries=5 \
     --timeout=5 \
     -O auth2_fms_${OUTFILEPREFIX}_${CHANNEL} \
     https://radiko.jp/v2/api/auth2_fms

if [ $? -ne 0 -o ! -f auth2_fms_${OUTFILEPREFIX}_${CHANNEL} ]; then
  echo "failed auth2 process"
  exit 1
fi

echo "authentication success"

areaid=`cat auth2_fms_${OUTFILEPREFIX}_${CHANNEL} | perl -ne 'print $1 if(/^([^,]+),/i)'`
echo "areaid: $areaid"

rm -f auth2_fms_${OUTFILEPREFIX}_${CHANNEL}

#
# rtmpdump
#
RETRYCOUNT=0
while :
do
  ${RTMPDUMP} -v \
              -r "rtmpe://radiko.smartstream.ne.jp" \
              --playpath "simul-stream" \
              --app "${CHANNEL}/_defInst_" \
              -W $playerurl \
              -C S:"" -C S:"" -C S:"" -C S:$authtoken \
              --live \
              --flv ${OUTFILENAME}${FLVFILEEXT} \
              --stop ${RECTIME}
  if [ $? -ne 1 -o `wc -c ${OUTFILENAME}${FLVFILEEXT} | awk '{print $1}'` -ge 10240 ]; then
    break
  elif [ ${RETRYCOUNT} -ge 5 ]; then
    echo "failed rtmpdump"
    exit 1
  else
    RETRYCOUNT=`expr ${RETRYCOUNT} + 1`
  fi
done

${FFMPEG} -y -i "${OUTFILENAME}${FLVFILEEXT}" -vn -acodec copy "${OUTFILENAME}${AACFILEEXT}"

rm -f ${OUTFILENAME}${FLVFILEEXT}

使い方は先日掲載したスクリプトと同様に

title 60 TBS

という引数を与えると、TBSラジオを62分間録音し、”title_YYYY-mm-dd.aac”として保存します。
(“YYYY-mm-dd”は実行した日付に置換されます。 例: 2011-03-21)
(要するに、タイムラグをカバーするために前後に1分ずつ余裕を持たせます。
cronで予約する場合は開始1分前から実行されるように設定してください。)

なお、リトライ機能が付いているため、録音開始が最大で
auth1_fms + auth2_fms + rtmpdump =
5[秒] × 5[回] + 5[秒] × 5[回] + 30[秒] × 5[回] = 200[秒]
程度遅延する可能性があります。

しかし、試しに15番組ほどcronで予約録音を行ってみましたが、
成功確率は100%で、最大開始遅延時間は約35秒でした。
(リトライ機能が無いスクリプトだと、成功確率はかなり落ちます。)
これなら1分の余裕を持たせれば、特に問題は無いように思われます。
(気になる方は余白を多めに取ることをオススメします。)

被災地の方から録音を依頼されている場合などで、
どうしても保存しておきたい番組がある方はお試しください。

カテゴリー: サーバ タグ: , ,
  1. qnv
    2011 年 10 月 8 日 21:29 | #1

    こんにちは、

    新しく始まったラジオ番組の録音方法を模索していたところ、
    ここに行き着きました。

    Vine linux 5.2 でためしてみたところ、
    公開いただいているスクリプト (+ パスの修正3行)
    でうまくいきました。

    お礼がてら、動作報告です。

  2. タツヤ
    2011 年 10 月 17 日 01:51 | #2

    こんにちは。
    遅くなりましたが、動作報告ありがとうございました。
    お役に立てましたら幸いです。

  3. Anonymous
    2012 年 2 月 23 日 10:24 | #3

    素晴らしい!
    スクリプトの勉強にもなります。
    ありがとうございます!

  4. toyo36jeff
    2012 年 5 月 4 日 17:11 | #4

    大変参考になりました。
    ありがとうございました。

  1. 2011 年 10 月 26 日 16:08 | #1
  2. 2011 年 11 月 20 日 22:08 | #2