SSブログ
Raspberry Pi ブログトップ

Radiko受信スクリプト修正 [Raspberry Pi]

2016年10月11日のRadikoタイムフリーサービス開始後、Raspberry Piに仕込んだRadiko受信スクリプトが正常に動かなくなっていたので修正を施しました。

仕込んだスクリプトは、先人によるshellスクリプトを参考にして、らじる★らじるとRadikoの双方に対応できるようPythonで書き直したものです。

ゆえに、他の方が修正したshellスクリプトを見ても、(自分のスクリプトの)どこを直せばいいんだか、ひと目ではわかりにくい。X-)

あれやこれやググってみると、その名もズバリ「忘れたらググればいい」さんの「radikoの仕様変更で録音ができなくなる問題を修正(2016年10月)」に変更点がわかりやすくまとめられておりました。


1)
playerurl=http://radiko.jp/apps/js/flash/myplayer-release.swfに変更


2)
X-Radiko-App: pc_tsに変更


3)
X-Radiko-App-Version: 4.0.0に変更


4)
/opt/local/bin/swfextract -b 12 /dev/stdin -o /dev/stdoutに変更


(「忘れたらググればいい/radikoの仕様変更で録音ができなくなる問題を修正(2016年10月)」より引用)


加えて、「radikoの仕様変更によるRaspberry Piでの録音失敗対応」に書かれている「Authtoken,Partialkeyのキャメルケース変更」も適用しました。


5)
X-Radiko-AuthTokenに変更


6)
X-Radiko-PartialKeyに変更



これらを参考に自前のPythonスクリプトを修正し、ふたたびRasPiでラジオを聴けるようになったのでした。めでたし。










Raspberry Piにリブート/シャットダウンスイッチをつける [Raspberry Pi]

Raspberry Pi B+/Pi 2 B用のリブート/シャットダウンスイッチを作ってみました。

まずは、Raspberry Piに取りつけるリブート/シャットダウンボタンを製作します。

resetbutton1.jpg
▲秋月で購入した2ピンタクトスイッチと、好みの長さに切断できる分割ロングピンソケットで、リセット/シャットダウンスイッチを作ります。RasPi内蔵プルアップ抵抗を使うので、外付け抵抗は不要です。

resetbutton2.jpg
▲タクトスイッチを、Pin39(GND)-Pin40(GPIO21)間に挿します。

電子工作はこれだけ。超カンタン。


続いて、リブート/シャットダウンスクリプトを作成。あらかじめ、Python(Python3) GPIOモジュールもインストールしておきましょう。
$ sudo aptitude install python-rpi.gpio pyhton3-rpi.gpio


スクリプトの仕様と、動作シーケンスは以下のとおりです。

(1) リブート/シャットダウンスクリプトが起動すると、オンボードPower LEDが点滅します(2秒毎に0.1秒間消灯)。
(2) タクトスイッチを1秒以上押し続けると、LEDがゆっくり点滅(3秒間)。この間にスイッチを離すとリブートします。
(3) さらにタクトスイッチを押し続けると、LEDが速く点滅(3秒間)。この間にスイッチを離すとシャットダウンします。
(4) さらにタクトスイッチを押し続けると、リブート/シャットダウン処理をキャンセルできます。
(1)へ戻る

リセットボタンを押したあとに「いかん! 編集中のデータをまだ保存してなかった!」的な事態に陥っても、ボタンを長押ししつづければ危機回避が可能な仕様となっております。


$ sudo vi /usr/local/bin/resetbutton.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
# REBOOT & SHUTDOWN Button
# for Raspberry Pi B+ / Pi 2 B
# Written by gaecen ueno
# [Dec.24,2015]
#
#===================================================================
#
# GPIO Connection
# S=TACT SW (GPIO 21) / G=GND
#
# 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0 0
# 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1 9 7 5 3 1
# G - - - - - - G - - - - - - - G - - - -
# S - - - - - - - - - G - - G - - - - - -
# 4 3 3 3 3 3 2 2 2 2 2 1 1 1 1 1 0 0 0 0
# 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2 0 8 6 4 2
#
# Holding down the button(tact switch)
#   | [1second]
#   | [3seconds](LED blink slowly)  Release the button -> Reboot
#   V [3seconds](LED blink faster)  Release the button -> Shutdown
# Abort Reboot and Shutdown

GPIO_BUTTON = 21  # GPIO 21(pin40) -> TACT SW -> GND
GPIO_LED = 35     # GPIO 35 is On-Board PWR LED(/sys/class/leds/led1)

LED_BLINK_TIME = [
  [1.9, 0.1],    # default  on=1.9sec off=0.1sec
  [0.5, 0.5],    # reboot   on=0.5sec off=0.5sec
  [0.1, 0.1]     # shutdown on=0.1sec off=0.1sec
]

#===================================================================

import  RPi.GPIO as GPIO
import  time
import  os

SHUTDOWN_NONE = 0
SHUTDOWN_REBOOT = 1
SHUTDOWN_HALT = 2


def getButtonState(io):
  cnt = 0
  prev_btn = not GPIO.input(io)

  while cnt < 3:
    time.sleep(0.01)
    btn = not GPIO.input(io)
    if prev_btn == btn:
      cnt += 1
    else:
      prev_btn = btn
      cnt = 0

  return btn


def callback(ch):
  global  shutdown_mode
  global  do_shutdown

  # Waiting for holding down the button.(1sec)
  for i in range(10):
    btn = getButtonState(GPIO_BUTTON)
    if btn == False:
      break
    time.sleep(0.1)

  # [REBOOT] Release the button when the LED is blinking slowly.(3sec)
  else:
    shutdown_mode = SHUTDOWN_REBOOT
    for i in range(30):
      btn = getButtonState(GPIO_BUTTON)
      if btn == False:
        do_shutdown = True
        break
      time.sleep(0.1)

    # [SHUTDOWN] Release the button when the LED is blinking faster.(3sec)
    else:
      shutdown_mode = SHUTDOWN_HALT
      for i in range(30):
        btn = getButtonState(GPIO_BUTTON)
        if btn == False:
          do_shutdown = True
          break
        time.sleep(0.1)

  if do_shutdown == False:
    shutdown_mode = SHUTDOWN_NONE

  return

#===================================================================

if __name__ == '__main__':
  GPIO.setwarnings(False)
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(GPIO_LED, GPIO.OUT, initial=GPIO.HIGH)
  GPIO.setup(GPIO_BUTTON, GPIO.IN, pull_up_down=GPIO.PUD_UP)

  shutdown_mode = SHUTDOWN_NONE
  do_shutdown = False

  GPIO.add_event_detect(GPIO_BUTTON, GPIO.FALLING, callback=callback)

  try:
    while do_shutdown == False:
        GPIO.output(GPIO_LED, GPIO.HIGH)
        time.sleep(LED_BLINK_TIME[shutdown_mode][0])
        GPIO.output(GPIO_LED, GPIO.LOW)
        time.sleep(LED_BLINK_TIME[shutdown_mode][1])

    if shutdown_mode == SHUTDOWN_REBOOT:
      os.system("sudo shutdown -r now > /dev/null 2>&1")
    elif shutdown_mode == SHUTDOWN_HALT:
      os.system("sudo shutdown -h now > /dev/null 2>&1")

  except KeyboardInterrupt:
    pass

  finally:
    GPIO.cleanup(GPIO_LED)
    GPIO.cleanup(GPIO_BUTTON)


スクリプトを起動し、動作確認を行います。
$ sudo chmod 755 /usr/local/bin/resetbutton.py
$ sudo /usr/local/bin/resetbutton.py

リブート、シャットダウンともに正しく動作することを確認できたら、/etc/rc.localの最終行(exit 0)の前の行に /usr/local/bin/resetbutton.py & を追加し、リブートしましょう(※1)。Raspberry Pi起動時に、リブート/シャットダウンスクリプトを自動起動することができます。

※1
/etc/rc.localを書き換えて自動起動させた場合、スクリプトの入力ミスやタクトスイッチに不具合があると、最悪の場合リブートをくり返す可能性があります。Win32DiskImagerなどを使って、事前にシステムのバックアップをとっておきましょう。


※2
拙宅のB+/2 Bでは正しく作動しましたが、古いB+だとエラーが出たり、オンボード Power LEDが点滅しないかもしれません。sudo rpi-updateでファームウェアを更新したり、aptitudeやapt-getで導入済みパッケージの更新を行ってみてください。



入門 Python 3

入門 Python 3

  • 作者: Bill Lubanovic
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2015/12/01
  • メディア: 単行本(ソフトカバー)



実践 Python 3

実践 Python 3

  • 作者: Mark Summerfield
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2015/12/01
  • メディア: 単行本(ソフトカバー)






Raspberry Pi 2(Jessie)でradikoを受信する[crontab編] [Raspberry Pi]

前エントリで構築したradiko受信環境。コマンドラインで実行するぶんには問題ないのですが、crontab設定でハマってしまったため、そのあたりについても備忘録を残しておきます。

ハマッたのは次の2点。

1) cronのデフォルトパスに/usr/local/binが通っていない。
2) コマンドオプションの%をエスケープする必要がある。

これらを解決するには、crontab -eで次のように記述します。パスを追記し、%の前に\(または半角円記号)を加える必要があります。#で始まる行はコメントです。
# 月曜日7時から60分間TOKYO FMを録音(~/radio/filename_年月日_時分.m4a)
00 7 * * 1 /usr/local/bin/radiko.sh -d ~/radio -f filename_`date +\%y\%m\%d_\%H\%M` -t 60 FMT > /dev/null 2>&1

もしくは環境変数を設定して、次のように記述しても可。
PATH=/usr/local/bin:/usr/bin:/bin
# 月曜日7時から60分間TOKYO FMを録音(~/radio/filename_年月日_時分.m4a)
00 7 * * 1 radiko.sh -d ~/radio -f filename_`date +\%y\%m\%d_\%H\%M` -t 60 FMT > /dev/null 2>&1

さらに、録音ディレクトリやdate~の記述も環境変数に書いておくとスッキリします。date~を環境変数に記述する場合、%のエスケープは不要です。
PATH=/usr/local/bin:/usr/bin:/bin
RECDIR=~/radio
RECDATE="date +%y%m%d_%H%M"
# 月曜日7時から60分間TOKYO FMを録音(~/radio/filename_年月日_時分.m4a)
00 7 * * 1 radiko.sh -d $RECDIR -f filename_`date $RECDATE` -t 60 FMT > /dev/null 2>&1




Eleduino Raspberry Pi 2 (1GB)Base Kit (New Raspberry Pi 2 +Case+Heatsink)

Eleduino Raspberry Pi 2 (1GB)Base Kit (New Raspberry Pi 2 +Case+Heatsink)

  • 出版社/メーカー: Eleduino
  • メディア: エレクトロニクス









Raspberry Pi 2(Jessie)でradikoを受信する [Raspberry Pi]

Raspberry Pi 2 Model B+Raspian 8.0(Jessie)でradiko再生・録音環境を構築しました。おもに Machuu / Raspberry Piでradikoの再生、録音 に記載されている方法を参考にしましたが、Jessieではひと工夫必要だったため導入過程を備忘録として残しておきます。

※以下の作業はrootで行っています。su - でrootユーザーへ切り替えて作業するか、各コマンドの冒頭に sudo を付加して実行してください。
※radiko配信番組の録音・再生は私的利用に限定してください。


■リポジトリ追加と公開鍵のインストール
2015年12月13日現在、Jessieではデフォルトでffmpegをインストールすることができないため、deb-multimediaリポジトリの追加と、公開鍵のインストールを行いました。テキストエディタにviを使用していますが、各自お好きなエディタをお使いください。
なお、公開鍵インストール時に警告表示されますが、無視して意地でも先に進んじゃいましょう。自己責任で。
$ vi /etc/apt/sources.list

  # /etc/apt/sources.list に次の2行を追加
  deb http://www.deb-multimedia.org jessie main non-free
  deb-src http://www.deb-multimedia.org jessie main non-free

$ aptitude update
$ aptitude install deb-multimedia-keyring
$ aptitude update


■必要なパッケージとスクリプトをインストールする
radiko受信に必要なもろもろのパッケージをインストールします。radiko再生/録音スクリプト radio.sh は /usr/local/bin へ移動したほうが使い勝手がよさげです。
$ aptitude install rtmpdump ffmpeg mplayer swftools wget libxml2-utils
$ wget https://gist.githubusercontent.com/soramugi/836952a6b09e540eb6a3/raw/81182ff0a1f5003077a479e0e947b66fb5d3b99e/radiko.sh
$ chmod 755 radiko.sh
$ mv radiko.sh /usr/local/bin


■受信テストを行う
環境構築が済んだら、受信テストを行います。radiko参加放送局一覧を参照し、radikoで聴取可能な地元局を指定してください。以下は、関東地方でTOKYO FMを受信する例です。
$ radiko.sh -p FMT

ヘッドホン端子にスピーカーを接続した際、スピーカーから音が出ないことがあります。この場合は、次のコマンドを実行してオーディオ出力先を切り替えます。最後のパラメータで出力先を、0(自動)、1(ヘッドホン端子)、2(HDMI端子)のいずれかに設定できます。
$ amixer cset numid=3 1

音量設定方法1。alsamixer起動後、カーソルキー上下で行えます。終了はESC。
$ alsamixer

音量設定方法2。amixerを用いると、コマンド一発で音量設定できます(nn%を任意の値に変えてください)。現在値はamixer sget で取得可能。
$ amixer sget PCM
Simple mixer control 'PCM',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -4919 [50%] [-49.19dB] [on]
$ amixer sset PCM 90%
Simple mixer control 'PCM',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -663 [90%] [-6.63dB] [on]


■録音/再生テストを行う
続いて、録音/再生テストを行います。(ホームディレクトリ)/radioを作成し、そこへTOKYO FMの番組をファイルネーム「test.m4a」として1分間録音。その後、mplayerでtest.m4aを再生します。
$ mkdir ~/radio
$ radiko.sh -d ~/radio -f test -t 1 FMT
$ mplayer ~/radio/test.m4a

※TIPS
-f ファイル名_`date +%y%m%d_%H%M` とすることで、ファイル名に「_年月日_時分」を追加できます。


※備考
radiko.shではflv録音・m4a変換を/var/tmpで行ったあと、m4aファイルを-dで指定したディレクトリへ移動しています。/var/tmpがRAMディスク上にある場合は、/etc/fstabを修正して十分な容量を確保しておくことをおすすめします。1分あたり録音と変換に約720KBを要するため、1時間番組なら44MB程度は必要です。 もしくはradiko.shを編集し、「wkdir='/var/tmp'」を容量に余裕のあるドライブへ変更しておくのが吉。



■radiko.shの起動パラメータについて
radiko.shをパラメータなしで起動し、表示されるUsageを参照してください。なお、radiko.sh配布元である
まっつんぶろぐ/radikoの録音・再生(ArchLinux)に詳細な使用方法や、cronを用いた予約録音方法が解説されています。


■参考サイト
・Muchuu/Raspberry Piでradikoの再生、録音
・まっつんぶろぐ/radikoの録音・再生(ArchLinux)
・S2/Raspberry Piのサウンドを試したら音が出なかった話
・Installing Ffmpeg on Debian GNU/Linux Version 8.0 (Jessie)


Eleduino Raspberry Pi 2 (1GB)Base Kit (New Raspberry Pi 2 +Case+Heatsink)

Eleduino Raspberry Pi 2 (1GB)Base Kit (New Raspberry Pi 2 +Case+Heatsink)

  • 出版社/メーカー: Eleduino
  • メディア: エレクトロニクス









Raspberry PiでDDNS(MyDNS)を更新する [Raspberry Pi]

これまで玄箱で走らせていた、DDNS更新用Perlスクリプト「updateip.pl」を改変し、Raspberry Piで走らせることにしました。
※updateip.pl作者であるBBBさんのサイト(http://userweb.mmtr.or.jp/~bbb/)は現在リンク切れ。

このスクリプトはグローバルIPアドレスに変更があったときのみ更新を行うため、DNSサーバーの負荷を軽減できます。

改変内容は次のとおりです。

・MyDNSの更新専用とし、オリジナル版で呼び出していたgdipc.plを不要とした。

・w3m呼出箇所を、wgetを使用するように変更。

・IPアドレス更新時のメール通知機能追加。


下記設置方法を参考にしてご使用ください。

1) 下のスクリプトを /usr/ddns/update_mydns.pl へ保存する。

2) sudo chmod 755 /usr/ddns/update_mydns.pl としてアクセス権を変更する。

3) テキストエディタ(vi、nano等)でスクリプトを修正する。
・MyDNSアカウントとパスワードを、$USER、$PASSに設定。
・メール通知を使用する場合は、$UPDATE_NOTICE、$MAIL_TO、$MAIL_FROMを設定する。別途MTAの導入も必要(ssmtp、nullmailer、postfixなど)。

4) sudo crontab -e としてcrontabを起動し、下記2行を追加する。
2-59/10 * * * * perl /usr/ddns/update_mydns.pl
00 3 * * * rm -f /tmp/PRV_IP.dat

上記(4)の設定で、毎時2分から10分おきにグローバルIPアドレスをチェックし、IPアドレス変更時にはMyDNSの更新を行います。また、毎日午前3時に/tmp/PRV_IP.datを削除し、午前3時2分には必ずMyDNSの更新を行います。
※DDNSサーバへのアクセス集中を避けるため毎時0分ではなく、毎時2分更新としています。

これらの設定は使用環境に応じて適宜変更してください。





Raspberry Pi2 Model B ボード&ケースセット (Standard, Clear)-Physical Computing Lab

Raspberry Pi2 Model B ボード&ケースセット (Standard, Clear)-Physical Computing Lab

  • 出版社/メーカー: TechShare
  • メディア: エレクトロニクス



これ1冊でできる!ラズベリー・パイ 超入門 改訂第2版 Raspberry Pi Model B/B+/2対応

これ1冊でできる!ラズベリー・パイ 超入門 改訂第2版 Raspberry Pi Model B/B+/2対応

  • 作者: 福田 和宏
  • 出版社/メーカー: ソーテック社
  • 発売日: 2015/04/04
  • メディア: 単行本



Raspberry Pi ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。