Raspberry Pi をDLNAサーバーに

Raspberry Pi をDLNAサーバーに

DLNA
(Divital Living Network Alliance)

異なるメーカーのAV機器を
LANを介して相互接続できるようにした規格

最近のネット対応TVのほとんどは
DLNA機能が備わっているため
DLNA対応NASをLANに追加すれば
NASに保存した動画や音楽を離れたTVなどでも再生できる

これを利用して Raspberry Pi へDLNAサーバーをインストールすれば
TVなどからRasberrt Pi にアクセスして動画などをみることができる

起動ディスクに使っているSDカードだと容量が少ないけどUSBに外付けHDDをつければ、
この問題も解決できる

まずは Raspberry PI にDLNAサーバーインストール
インストールするのはMiniDLNA

[shell]
sudo apt-get install minidlna
[/shell]
でインストール

次にDLNAサーバーの設定
動画や音声ファイルを保存するディレクトリを作成する

現在ホームディレクトリにいるので、ここへ作成する

 mkdir Video Music Photo

そして、作成したディレクトリにSFTPでメディアを転送する

クライアントソフトは Filezilla を利用
音楽なら Music
動画なら Video
写真なら Photo
に転送する

次に設定ファイルを編集する

sudo vim /etc/minidlna.conf 

で変更できるけどバックアップとってから編集したほうが無難

26行めの
media_dir=/var/lib/minidlna
が保存先を指定しているので

#media_dir=/var/lib/minidlna
media_dir=V,/home/pi/Video
media_dir=A,/home/pi/Music
media_dir=P,/home/pi/Photo

とする
#のついているのはコメントアウト

これで設定できたのでDLNAサーバーの起動

sudo /etc/init.d/minidlna start

で起動できる

設定ファイルを書き換えた場合

sudo /etc/init.d/minidlna force-reload

で設定ファイルを再読み込みする

起動できたら、まずは ipod touch でアクセス

しかしアクセスできても再生できないので
権限を確認
-rw-r–r–
となっているので
chmod 755 で変更したけど結果は変わらず

原因を調べるため
raspberry pi minidlna で検索

RPi miniDLNA


を元にログをチェック

less /var/log/minidlna.log 

で確認すると

inotify.c:195: warn: WARNING: Inotify max_user_watches [8192] is low or close to the number of used watches [8] and I do not have permission to increase this limit.  Please do so manually by writing a higher value into /proc/sys/fs/inotify/max_user_watches.

となっていたので

sudo sysctl fs.inotify.max_user_watches=81920

を実行し

sudo /etc/init.d/minidlna force-reload

で miniDLNAを再起動

しかしまだ再生はできなかった
どうやらログをみるとポート関連の問題のよう

minidlna.c:1006: warn: HTTP listening on port 8200

とりあえずポート確認するため
ubuntu で

nmap 192.168.1.198

で確認

結果は

Starting Nmap 5.21 ( http://nmap.org ) at 2014-08-10 19:22 JST
Nmap scan report for raspberrypi (192.168.1.198)
Host is up (0.12s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
8200/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 1.23 seconds

ポートが開いているようなので
次に再生できる形式を調べることに

mp3 ファイルで実験するため

cp /usr/share/pyshared/pygame/examples/data/house_lo.mp3 Music/

で実験した結果、再生可能なことを確認

どうやら .ogg 形式が再生できないため
http://nanase.hatenablog.jp/entry/2013/11/08/193003
を参考に

sudo apt-get install mpg321 vorbis-tools

でインストール
これでもダメなので
http://linuxforums.org.uk/index.php?topic=9822.0
を元に

sudo apt-get install minidlna gstreamer0.10-ffmpeg

でさらにインストール

しかし未だに .ogg 形式ファイルの再生はできなかった

とりあえず .ogg はできないけど mp3 までなら
DLNAサーバーでの再生が可能になった

動画に関しても調べてみたけど
http://bty.sakura.ne.jp/wp/archives/377
に書いてあるように
動画ファイルはmpeg2のフォーマットじゃないと閲覧できない

raspberry pi の音声を女性にする

raspberry pi の音声を女性にする

音声データ(音響モデル)を追加すれば
別の声で喋らせることもできる

今回はMMDAjent メイちゃんの音声データを追加

http://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/

から
MMDAgent_Example-1.3.1.zip
をダウンロード

最新版は 1.4 だけど、残念ながらこれは使えない
ver1.4 以降は使えないらしい

ダウンロードできたら
SFTPでファイルを転送
今回は FileZilla で転送する

アップロードできたら

unzip MMDAgent_Example-1.3.1.zip 

で解凍

そして
/usr/share/hts-voice/

MMDAgent_Example-1.3.1/Voice/
以下のファイルをディレクトリごとコピーする

sudo cp -R MMDAgent_Example-1.3.1/Voice/* /usr/share/hts-voice/.

でコピーできる

ls /usr/share/hts-voice/mei_angry 

で確認すると

mei_bashful
mei_happy
mei_normal
mei_sad
nitech-jp-atr503-m001
となっている

nitech-jp-atr503-m001
は男性の声

女性の声は mei_ で始まるディレクトリのところ

これで音源が手に入ったので
スクリプトファイルを変更する

cp jtalk.sh jtalk.sh_bak

で念のためバックアップをとっておく

そしてファイルを変更
これなら失敗してもバックアップから戻せば直せる

とりあえず、音源を変更したいので
HV=/usr/share/hts-voice/nitech-jp-atr503-m001
のHV=の部分で指定している音源ディレクトリを変える

HV=/usr/share/hts-voice/mei_happy
として保存

これで再度

./jtalk.sh "今日はいい天気ですね"

とすると女性の高めの声になる

raspberry Pi で音声合成

raspberry Pi で音声合成

Open JTalk はオープンソースで開発されている日本語音声合成エンジンのこと

形態素解析のMeCab

形態素解析用辞書の naist-jdic

音声合成エンジン hts_engine
を使うことで英
日本語の文章を音声として出力できる

形態素解析では
文章の中から単語を最小の単位に分解し
辞書をもとに分類したりする

Raspberry Pi では 音声合成ソフトとして
AquesTalk Pi があるけど
無償で使えるのは非営利の個人だけで
それ以外はライセンス購入が必要になる

なお Open JTalk は apt-get で簡単にインストールできる

sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001 libhtsengine1

でインストールできる

さらに、今回は書籍にあったサンプルも使ってみた
http://v7.com/raspi2/
からダウンロード

ダウンロードしたファイルを
unzip sample.zip で解凍

この中にあるファイル jtalk.sh をFileZilla で
Raspberry PI へアップロード

アップしたら権限変更

chmod 755 jtalk.sh 

これでスクリプトを使うことができるようになったので

./jtalk.sh "今日はいい天気ですね"

とすると
今日はいい天気ですね
と音声がでる

つまり、
./jralk.sh “読み上げたい文章”
とすると読ませることができる

また、テキストファイルを指定して読ませることもできる

vim textfile.txt

で作成し
内容を

今日はラズベリーパイの音声入力を試した
次は音声の変更を実行してみよう

とする

これで

vim textfile.txt

とすると1行めは読まれるけど
2行めは読まれなかった

また

echo "読み上げる文章" | ./jtalk.sh 

というようにパイプを使えば
echo の文章を渡すことができる

また、コマンドをバッククオート
shift + @ で出せる ` で囲むと
コマンドの実行結果を含めることができる

よく使われるものとしては
現在時刻を読ませるという方法

echo "只今の時刻は `date +%k`時 `date +%-M` 分です" | ./jtalk.sh 

とすると現在時刻を読み上げる

今回は date の実行結果を “で囲むことで読み上げに使っている

画像のモノクロ表示

画像のモノクロ表示

画像をモノクロにすれば、白黒写真みたいなのが作れる

Bitmapのモノクロ表示は
描画用のPaintインスタンスに
ColorFilterを設定し
Canvas.drawBitmap()で描画することでできる

まずは、Bitmap画像の読み込み

loadBitmap()を定義し
画像のURIを渡せば
ContentProvider経由で取得した画像のBitmapインスタンスを返すようにする

Bitmap bitmapOriginal = loadBitmap(imageUri);

そして、モノクロ画像用のBitmapを生成

//元画像の高さ、幅の取得
int height = bitmapOriginal.getHeight();
int width = bitmapOriginal.getWidth();

//モノクロ画像用のBitmap作成
Bitmap bitmapGrayScale = Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565);

そして、モノクロのカラーフィルターを設定し
Bitmapへ描画する

Canvas c = new Canvas(bitmapGrayScale);
Paint paint = new Paint();

//彩度を0に設定
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);

//グレースケールに変換されるColorFilterインスタンス設定
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);

//Bitmapの描画
c.drawBitmap(bitmapOriginal,0,0,paint);

モノクロ表示みたいに
画像の色を変更するには
ColorFilterを使えば簡単に実現できる

今回なら
ColorMatrixを作成して
setSaturation()で彩度を0に設定し
グレースケールに変換されるColorFilterインスタンスを作成している

raspberry pi で動画、ラジオの再生

raspberry pi で動画、ラジオの再生

Raspberry Pi のGPUには
H.264 対応の動画再生支援機構があるため
CPUにさほど負担をかけず再生が可能

動画再生はデフォルトインストールされている
omxplayer
で再生可能

ちなみに、これはコマンドで行う
デスクトップ環境を起動していると表示がおかしくなるので注意

再生のしかたは

omxplayer -p -o local ファイル名

となる

-o local オプションで
オーディオ出力端子に指定している

もしHDMIなら
-o hdmi
となる

これで音声関連はOK

次にインターネットラジオ

スマホアプリの radiko が有名だけど
Raspberry Pi では mplayer を使えばラジオをきくことができる

まずは mplayer のインストール

sudo apt-get install mplayer

次に、聞きたいラジオのURLを調べる

http://www.shoutcast.com/
が人気らしいので、この中から選ぶことにする

今回は
COOLfahrenheit 93
を選択

ダウンロードアイコンを右クリックして
リンクのURLをコピーする

radio

mplayer で再生するときもコマンドで行う

mplayer -playlist 視聴したいURL

とする

今回なら

 mplayer -playlist http://yp.shoutcast.com/sbin/tunein-station.pls?id=175821

で再生できる

操作はキーボードで行える
音量をあげるなら *
音量を下げるなら /
一時停止とその解除はスペースキー
終了は esc キー
となる

日本のものもやってみたかったけど
radiko がほとんどなのでやめました

指定サイズで画像トリミング

指定サイズで画像トリミング

AndroidのBitmap処理は
android.graphics パッケージの
BitmapFactoryクラスを使う

BitmapFactory.decodeStream()で
Bitmapを読み込み
BitmapFactory.Optionsのインスタンスに読み込み時の振る舞いを設定する

指定サイズでのトリミングをするには
一旦画像をBitmapとして読み込んで
その後でトリミング領域を設定
そして
Bitmap.createBitmap()で新しいBitmapを作成する

excelとかで、ファイルを開いて
編集したら、別ファイルで保存するようなかんじ

まず、Bitmap画像の読み込み

例外発生に備え、try catchで行う

InputStream input = null;

try{

//振る舞いの設定
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

//画像の読み込み
input = getContentResolver().openInputStream(imageUri);
BitmapFactory.decodeStream(input, null, options);
int inSampleSize = calculateInSampleSize(options, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);

input.close();
input = null;

options.inJustDecodeBounds= false;
options.inSampleSize = inSampleSize;

input = getContentResolver().openInputStream(imageUri);
mSourceBitmap = BitmapFactory.decodeStream(input, null, options);

mImageView.setImageBitmap(mSourceBitmap);

}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(input != null){
try{
input.close();
}catch(IOException e){
e.printStackTrace();
}
}
}

次に、画像をトリミングしてからBitmapを作成

//幅と高さの取得
int imageWidth = mSourceBitmap.getWidth();
int imageHeight = mSourceBitmap.getHeight();

//トリミングする幅、高さ、座標の設定
int nWidth = (int)(imageWidth * 0.7f);
int nHeight = (int)(imageHeight * 0.7f);
int startX = (imageWidth - nWidth) /2;
int startY = (imageHeight - nHeight)/2;

//トリミングしたBitmapの作成
mSourceBitmap = Bitmap.createBitmap(mSourceBitmap, startX, startY, nWidth, nHeight, null, true);

Bitmap.createBitmap()の引数は
第一引数のmSourceBitmapがコピー元のBitmap

第2 の startX
第3 の startY
第4 の nWidth
第5 の nHeight
はトリミングの位置と大きさを指定している

Raspberry Pi でサウンド再生

Raspberry Pi でサウンド再生

Raspberry Pi には2種類のサウンド出力がある

HDMI
もしくは
3.5mm オーディオ出力
になる

ディスプレイへ HDMI のほうを接続しているので
今回は 3.5mm オーディオ出力のほうからサウンド再生

ちなみに今回利用したものオーディオは
LOGICOOL ステレオスピーカー Z120BW

まず、Ubuntu からリモートで操作したいので

ssh pi@192.168.1.198

でログイン

まずは音がでるかテストしたいので

 amixer cset numid=3 1


3.5mm オーディオ出力になるように指定

次に

alsamixer

で起動する

alsamixer

音量はキーボードの↑↓、もしくは数値で指定する

今回は8を入力し
8割の音の大きさに指定

指定できたら ESC キーで終了

次に、サンプルファイルを再生する

まずは wav ファイルの再生
これは aplay コマンドをつかう

aplay -q /usr/share/pyshared/pygame/examples/data/house_lo.wav 

-q オプションは画面に何も出力しないようにする

これをつけないとファイル情報が表示される

次に mp3 形式の再生だけど、これはソフトをインストールして行う
インストールするのは mpg321

sudo apt-get install mpg321 

でインストール

これもコマンドでファイルを再生する
-q オプションをつければファイル情報を表示せずに再生できる

mpg321 -q /usr/share/pyshared/pygame/examples/data/house_lo.mp3 

で再生

このコマンドは他にもオプションがあるので

 mpg321 -h

でみることができる

とりあえず、今のバージョンだと

mpg321: option requires an argument -- 'h'
High Performance MPEG 1.0/2.0/2.5 Audio Player for Layer 1, 2, and 3.
Version 0.3.2-1 (2012/03/25). Written and copyrights by Joe Drew,
now maintained by Nanakos Chrysostomos and others.
Uses code from various people. See 'README' for more!
THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!

Usage: mpg321 [options] file(s) | URL(s) | -

Options supported:
   --verbose or -v          Increase verbosity
   --quiet or -q            Quiet mode (no title or boilerplate)
   --gain N or -g N         Set gain (audio volume) to N (0-100)
   --skip N or -k N         Skip N frames into the file
   --frames N or -n N       Play only the first N frames
   -o dt                    Set output devicetype to dt
                                [esd,alsa(09),arts,sun,oss]
   --audiodevice N or -a N  Use N for audio-out
   --stdout or -s           Use stdout for audio-out
   --au N                   Use au file N for output
   --cdr N                  Use cdr file N for output
   --wav N or -w N          Use wave file N for output
   --test or -t             Test only; do no audio output
   --list N or -@ N         Use playlist N as list of MP3 files
   --random or -Z           Play files randomly until interrupted
   --shuffle or -z          Shuffle list of files before playing
   --loop N or -l N         Play files N times. 0 means until
                            interrupted
   -R                       Use remote control interface
   -3                       Restart "remote shell". Used only when in "Remote control" mode.
   -F                       Turn on FFT analysis on PCM data. Remote mode only
   -B                       Read recursively the given directories
   -S                       Report mp3 file to AudioScrobbler
   -K                       Enable Basic Keys
   -x                       Set xterm title setting
   -b                       Number of decoded frames for the output buffer
   -p hostname:port         Use proxy server
   -u username:password     Use proxy server basic authentication
   -U username:password     Use proxy server basic authentication by using environment variables
   --aggressive             Try to get higher priority
   --help or --longhelp     Print this help screen
   --version or -V          Print version information
Basic keys:                                            
* or /   Increase or decrease volume.                  
m        Mute/unmute                                   
n        Skip song.                                    

This version of mpg321 has been configured with the libao default as its default
libao output device.

となる

サンプルファイルはいくつか格納されており
/usr/share/scratch/Media/Sounds/
/usr/share/sounds/alsa/
/usr/share/pyshared/pygame/examples/data/
の中にも格納されている

ボリュームボタンの検出

ボリュームボタンの検出

ハードウェアのボリュームボタンを使えば
音量のコントロールができる

このボリュームボタンの検出するには
KeyEventクラスの
getKeyCode()で
キーコードを取得すれぱいい

KEYCODE_VOLUME_UP
なら音量アップ

KEYCODE_VOLUME_DOWN
なら音量ダウン

KEYCODE_VOLUME_MUTE
ならミュート、つまり音を消す

@Override
public boolean dispatchKeyEvent(KeyEvent event){

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP){
Toast.makeText(getApplicationContext(),"音量アップ", Toast.LENGTH_SHORT).show();
}

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN){
Toast.makeText(getApplicationContext(),"音量ダウン", Toast.LENGTH_SHORT).show();
}

if(event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_MUTE){
Toast.makeText(getApplicationContext(),"ミュートにしたよ", Toast.LENGTH_SHORT).show();
}
return super.dispatchKeyEvent(event);
}

ホームボタンの検出

ホームボタンの検出

ハードウェアのホームボタンを押したのを検出するには
onUserLeaveHint()
を使う

これを使えば
アプリがハックグラウンドになったときとか
Notificationとかの通知領域への移動
ほかのアプリに遷移したときにも使える

自動保存アプリの場合、このタイミングで保存しました
とでるとわかりやすい

とりあえず、わかりやすくトースト表示するなら

@Override
public void onUserLeaveHint(){

Toast.makeText(getApplicationContext(),"HOMEボタン押したよ", Toast.LENGTH_SHORT).show();
}

戻るボタンの検出

戻るボタンの検出

ハードウェアの戻るボタンの検出には
キーイベントの
KEYCODE_BACK
を取得すれぱ検出できる

戻るボタンを押したら検出し、トースト表示するなら

@Override
public boolean dispatchKeyEvent(KeyEvent event){

if(event.getKeyCode() == event.KEYCODE_BACK){
Toast.makeText(getApplicationContext(), "戻るボタン押したよ", Toast.LENGTH_SHORT).show();
}
return super.dispatchKeyEvent(event);
}

これで、戻るボタンを押すとトースト表示される

メモ帳アプリとかで、自動保存したときに表示するというように使える