Supersonicで自前のGoogleMusicを実現する!

Supersonicっていうと、あれか、普通はゲームを想像するよね。
https://play.google.com/store/apps/details?id=com.kuuasema.supersonic

でも今日のネタは、別のSupersonic。


ちなみに、このネタは、"Android Advent Calendar裏(12/28) http://androidadvent.blogspot.jp/ のために書かれたものです。同日の表は、@mstssk さんです。

GoogleMusic使ってる?

GoogleMusic使ってますか?
日本からだと使えないよね...
なんか、アプリは日本からでも落とせるようになったのに、サービスは受けられないとか意味わかんない。
まぁ、手元では使えてるけど(^^;。


使ってると超便利だ。
データを持ち歩く必要がない。つまりPlayerにデータを詰め込んで持ち歩く必要がない。
Playerの容量を気にしなくてもいい。
「あ、あれ聞きたい」と思った時に、電話を開いて、自分の全ライブラリにアクセスして、検索してその曲を再生できる。
最高じゃないか!
ネットワークにつながってればだけど(^^;。


ただ、無料で登録できる楽曲数に制限がある。
2万曲だっけ?
そんなのすぐに埋まっちゃうよ。
有料で容量追加して使うというのもイマイチ。


あと、接続できるデバイス数の制限もある。
1アカウントで最大10台。
登録の取り消しできるのは年間4台。
ハイペースで端末を買い占め、さらに買い換えるAndroiderには、ちょっとつらい制限だよね。


んでもって、日本からはまだ公式には使えない。
この12月19日に、"Scan and Match"が開始されて、ますます日本でのサービスが遠のいた気がする。
http://d.hatena.ne.jp/kinneko/20121219/p13
ダウンロードは手持ちのものと同じレートだけど、ストリームが320kってのは、コンテンツホルダはどう考えるのか。
それが問題。
日本でのサービス開始は、まだまだ先になりそう。


自由に使えるのは、いつの日だろうか?
そんなの待ってられない!
制限事項もうざい!
お金も使いたくない!
と、いうわけで、代案を探す旅に出た。

Winampは便利だよね。

Winampは便利だよね。
Androidでは使ったことないけど(^^;。
どうやら、PCとAndroidが同じネットワークにいたら、WiFiペアリング機能で双方向同期できるみたい。
でも、やりたいのはこれじゃない。
とても、自前のGoogleMusicとは呼べない。

Subsonicは知ってる?

Subsonicは有名だから知ってるかな?
http://www.subsonic.org/
Javaで書かれたストリーミング鯖。
いろんな環境から楽曲再生が可能。
ライセンスはGPL
でも、アプリからの再生は30日の機能制限あり。
ミニマムで10EUR寄付すればライセンスキーが発行される。
制限のないプレミアム版は20EUR。決済はPaypal
アプリは無料。広告が付くみたい。
Subsonic Music Streamer
https://play.google.com/store/apps/details?id=net.sourceforge.subsonic.androidapp
Subsonicなら、自前のGoogleMusicは実現できるけど、妙な制限ついて、なんかこれもイマイチ。

Supersonicは知らないか(^^;

Subsonicの互換品というか、同じ機能のオープンな実装がある。
Supersonic: https://github.com/Mach5/supersonic/wiki
なんかよく見ると、Subsonicのフォークのように見えるな。
裏ネタにふさわしいグレーな感じ〜(^^;。
ライセンスはGPL。つまり、ライセンス的にはフォークに問題はない。
パッケージ配布は以下で。
https://github.com/Mach5/supersonic/downloads
Mac(dmg)/Win(exe)/debとtgzが用意されている。
ソースは、gitでも取れる。
https://github.com/Mach5/supersonic.git
これを入れてみよう。

鯖マシンの用意

鯖には、QNAPの2ドライブNASを使うことにした。
Atom D510 1.66GHz。RAMは2GB。
前に、この日記で、OSQA鯖とか、redmine鯖とか立ててみるのに使ったやつ。
http://d.hatena.ne.jp/kinneko/20120107/p1
http://d.hatena.ne.jp/kinneko/20110527
これに、Ubuntu Serverを入れる。
まず、インストールUSBメモリを作る。

MacBook:Downloads kinneko$ dd if=ubuntu-12.04-server-amd64.iso of=/dev/disk2
1401432+0 records in
1401432+0 records out
717533184 bytes transferred in 1139.944426 secs (629446 bytes/sec)

これ挿しこんでブート、インストールを行なう。
起動時にF11キーを押しておくと、起動デバイスを選択できる画面に出る。
リストから、さしこんだUSBメモリを選択して起動する。
taskselでも特に何も指定しない。ミニマムインストールで。
インストール後は、コンソールからsshを使えるようにして、あとはヘッドレスでリモートから作業に切り替える。

Supersonic鯖のインストール

Supersonicのインストール方法は、「SubsonicのページをSupuersonicに読み替えて使ってね」というお茶目な内容。
http://www.subsonic.org/pages/installation.jsp
フォークだから、ほとんど同じってことかね。


とりあえず、Ubuntuでパッケージ提供されていないか検索してみる。

supersonic@supersonic:~$ apt-cache search supersonic

ないようだ。


今回はターゲットはUbuntuマシンなので、配布サイトから以下のパッケージを入れる。

supersonic@supersonic:~$ wget https://github.com/downloads/Mach5/supersonic/supersonic-4.7.beta1.deb

約33MBのパッケージが落ちてきた。


パッケージ情報を確認してみる。

supersonic@supersonic:~$ dpkg --info supersonic-4.7.beta1.deb
 new debian package, version 2.0.
 size 34155054 bytes: control archive= 858 bytes.
      24 bytes,     1 lines      conffiles            
     657 bytes,    19 lines      control              
     287 bytes,    16 lines   *  postinst             #!/bin/sh
     124 bytes,     9 lines   *  postrm               #!/bin/sh
     119 bytes,     8 lines   *  preinst              #!/bin/sh
     119 bytes,     8 lines   *  prerm                #!/bin/sh
 Package: supersonic
 Version: 4.7.beta1
 Section: Multimedia
 Priority: optional
 Depends: default-jre-headless
 Recommends: lame, ffmpeg
 Architecture: all
 Maintainer: Timo Reimann <devel@foo-lounge.de>
 Description: A web-based music streamer, jukebox and Podcast receiver
  Supersonic is a web-based music streamer, jukebox and Podcast receiver,
  providing access to your music collection wherever you are. Use it
  to share your music with friends, or to listen to your music while away
  from home.
  .
  An app for Android is also available.
  .
  Java 1.6 or higher is required to run Supersonic.
  .
  Supersonic can be found at https://github.com/Mach5/supersonic

依存関係は"default-jre-headless"だけが設定されている。
推奨に" lame, ffmpeg"が上がっているのは、トランスコートしてストリームするための機能で必要だから。
Java1.6ってのが条件だけど、OpenJDKのJREでいいよね。


Ubuntu鯖は、ミニマムインストールの状態なので、default-jre-headlessと依存しているパッケージを入れておく。

supersonic@supersonic:~$ sudo apt-get install default-jre-headless
(snip)
The following NEW packages will be installed:
  ca-certificates-java default-jre-headless icedtea-6-jre-cacao
  icedtea-6-jre-jamvm java-common libavahi-client3 libavahi-common-data
  libavahi-common3 libcups2 libjpeg-turbo8 libjpeg8 libnspr4 libnss3
  libnss3-1d openjdk-6-jre-headless openjdk-6-jre-lib tzdata-java
The following packages will be upgraded:
  tzdata
1 upgraded, 17 newly installed, 0 to remove and 98 not upgraded.
Need to get 34.7 MB of archives.
After this operation, 92.9 MB of additional disk space will be used.
(snip)

いろいろ入った。
default-jre-headlessって便利だな。メタパッケージかな? おぼえておこう。


supersonicをインストール。

supersonic@supersonic:~$ sudo dpkg -i supersonic-4.7.beta1.deb 
Selecting previously unselected package supersonic.
(Reading database ... 49569 files and directories currently installed.)
Unpacking supersonic (from supersonic-4.7.beta1.deb) ...
Setting up supersonic (4.7.beta1) ...
 Adding system startup for /etc/init.d/supersonic ...
   /etc/rc0.d/K99supersonic -> ../init.d/supersonic
   /etc/rc1.d/K99supersonic -> ../init.d/supersonic
   /etc/rc6.d/K99supersonic -> ../init.d/supersonic
   /etc/rc2.d/S99supersonic -> ../init.d/supersonic
   /etc/rc3.d/S99supersonic -> ../init.d/supersonic
   /etc/rc4.d/S99supersonic -> ../init.d/supersonic
   /etc/rc5.d/S99supersonic -> ../init.d/supersonic
Starting Supersonic... Done.
Started Supersonic [PID 2725, /var/supersonic/supersonic_sh.log]
Processing triggers for ureadahead ...

おや、sysvinitだ。
Debianと共用のパッケージだからしょうがないか。
upstartUbuntuでも、最低限の互換性はあったように思うので、大丈夫かな。
鯖はすでに自動起動している。


インストールされたファイルを確認する。

supersonic@supersonic:~$ dpkg -L supersonic
/.
/var
/var/supersonic
/var/supersonic/transcode
/var/supersonic/transcode/lame
/var/supersonic/transcode/ffmpeg
/usr
/usr/share
/usr/share/supersonic
/usr/share/supersonic/supersonic.sh
/usr/share/supersonic/supersonic-booter-jar-with-dependencies.jar
/usr/share/supersonic/supersonic.war
/usr/share/doc
/usr/share/doc/supersonic
/usr/share/doc/supersonic/copyright
/etc
/etc/default
/etc/default/supersonic
/etc/init.d
/etc/init.d/supersonic

少ないね。
lameffmpegはバイナリを内蔵している。
パッケージでsuggestになってたのは、入ってないってわけじゃないのか。
いろいろと、ダサいパッケージだ(^^;。

Supersonic鯖の設定

デフォルト設定内容を確認、変更する。
defaultディレクトリ下に設定ファイルを置くとか、debとしては普通じゃないな。

supersonic@supersonic:~$ sudo vi /etc/default/supersonic 
SUBSONIC_ARGS="--max-memory=100"
SUBSONIC_USER=root

コメントを除き、有効な設定は2つだけ。
SUBSONIC_USERは、rootで起動されたらたまらないので、supersonicにしておく。
SUBSONIC_ARGSには、以下の3つが設定できる。

  • --port=80 (HTTP時の使用ポート。デフォルト80)
  • --https-port=443 (HTTPS時の使用ポート。デフォルト443)
  • --max-memory=120 (Java memory heap size。デフォルト120MB)

設定では、--max-memoryのみ100MBの設定がされている。
ユーザー権限での起動にしたので、well known portは使えない。8080と8443に変更する。

SUBSONIC_ARGS="--port=8080 --https-port=8443 --max-memory=120"
SUBSONIC_USER=supersonic


起動ユーザーを変更したので、現在起動してしまっている環境では動作しない。
できたファイル類のパーミッションを変更しておく。
すでに、一度起動しているというか、今動いているので、自動生成されるファイルはできてしまっている。

supersonic@supersonic:~$ sudo ls -l /var/supersonic/
total 56
drwxr-xr-x 2 root root  4096 Dec 20 16:44 db
drwxr-xr-x 3 root root  4096 Dec 20 16:44 jetty
drwxr-xr-x 7 root root  4096 Dec 20 16:44 lucene2
-rw-r--r-- 1 root root 17659 Dec 20 16:49 subsonic.log
-rw-r--r-- 1 root root   124 Dec 20 16:44 subsonic.properties
-rw-r--r-- 1 root root   360 Dec 20 16:44 supersonic.args
-rw-r--r-- 1 root root 10436 Dec 20 16:45 supersonic_sh.log
drwxr-xr-x 2 root root  4096 Dec 20 16:44 transcode

jetty/にはWebUI用のXMLが、lucene2/には曲のメタデータができているようだ。
めんどくさいので、最初からなかったものは消しておこう。

supersonic@supersonic:~$ sudo service supersonic stop
supersonic@supersonic:~$ sudo rm -r /var/supersonic/jetty /var/supersonic/lucene2 /var/supersonic/db
supersonic@supersonic:~$ sudo rm /var/supersonic/subsonic.log /var/supersonic/subsonic.properties /var/supersonic/supersonic.args /var/supersonic/supersonic_sh.log
supersonic@supersonic:~$ sudo chown supersonic.supersonic -R /var/supersonic 

鯖を再起動する。

supersonic@supersonic:~$ sudo service supersonic start
Starting Supersonic... Done.
Started Supersonic [PID 3038, /var/supersonic/supersonic_sh.log]

Supersonic鯖の動作状態の変更

ほかにもいろいろ設定はありそうだけど、スタティックな設定ファイルには細かい設定はない。
しょうがないので、Web設定画面を開く。
port 8080でブラウザからアクセスしてみたら、8443に飛ばされて、ログイン画面が出た。
初回なので、

Supersonic is not secured. Please log in with username and password "admin", or click here. Then change password immediately.

などと出てきている。
admin.adminで入れるのね。
"Getting started"画面では、
1. Change administrator password.
2. Set up media folders.
3. Configure network settings.
の3つのメニューが出る。順に設定する。

管理者パスワードの変更

"Change administrator password."のリンクをたどると、パスワードの変更画面が出る。


英語なので、わかんない人もいると思うので、いろいろする前に、まず日本語表示にしてしまうか。
Personal -> Languageのドロップダウンで"日本語(日本)"を選んで、"Save"ボタンを押す。
"Getting started"に戻ってくるけど、ここは英語のまま。
翻訳されていない部分だと思われる。まぁ、よくあることです。


再度パスワード変更画面に。あら不思議、ここは日本語になっていますよ。
"パスワードの変更"をチェックすると、パスワード入力画面が出てくるので変更。
Emailには特になにも入れない。保存ボタンを押す。
画面がリフレッシュされるが、選択が「新しいユーザー」になっているのがわかる。
なんかしようとしたら、ログイン画面になったので、新しいパスワードで再ログインする。
"Getting started"がまた出る。
1はなくなっていない...
これってスタティックに出しているだけか。
でなくするには、"Don't show this again"をクリックする必要があるようだ。
あとで、これらの設定が終わったらクリックする。

音楽フォルダの指定

"Set up media folders."をクリックする。
画面は、「音楽フォルダ」のタブをクリックしたときと同じ。
デフォルトでは、"/var/music"が音楽データ格納用の領域に指定されている。
そんなのパッケージでは作ってくれなかったのでないわな。
メディアをスキャンして、メタデータを作成するタイミングは指定できる。
しかし、inotifyなどを使ってリアルタイムでやるようにはなっていないので、最短で一日に一回だけ。
Web開くのがめんどくさい時には、鯖の再起動がいいかな。
Webからは即時スキャンボタンが押せる。
"Fast access mode"というデータのキャッシュモードが用意されている。
これはチェック入れて有効にしておくべきかな。
ディスクアクセスを最小化するというので、メモリキャッシュをやるんだろう。
チェックを入れて、保存ボタンを押す。


音楽データ用のディレクトリを掘って、パーミッションをsupersonicに変更して、サンプル用のデータをコピーしておく。

supersonic@supersonic:~$ sudo mkdir /var/music
supersonic@supersonic:~$ chown supersonic.supersonic /var/music
supersonic@supersonic:~$ ls -al /var/ | grep music
drwxr-xr-x  2 supersonic supersonic 4096 Dec 25 10:51 music
supersonic@supersonic:~$ sudo mount /dev/sdb1 /media
supersonic@supersonic:~$ sudo cp -a /media/* /var/music/
supersonic@supersonic:~$ sudo chown -R supersonic.supersonic /var/music
supersonic@supersonic:~$ sudo umount /media/

"Scan media folders now"を押す。
管理画面の左ペインにアーティストと曲数などの情報は出てきた。
アーティストをクリックすると、カバーアート付きのリスト画面が表示される。
残念ながら、日本語のID3タグ名は文字化けしている。
Webからの再生は、画面下のバーからコントロールできる。
決して使いやすいUIとは言えない。
再生をはじめると、右ペインに表示が出るのだけど、"Chat messages"というフィールドが出る。
同じ曲を再生している人に何か伝えられるのだろうか?


Web画面から使う予定はないので、WebUIについて、これ以上突っ込んでもしょうがない。
興味のある人はご自由に。

ネットワーク設定の変更

"Configure network settings."をクリック。
画面は、「Network」のタブをクリックしたときと同じ画面が出る。
Network設定では、UPnPパケットを出す機能があるようだ。
"Automatically configure your router to allow incoming connections to Subsonic"にチェックを入れて保存ボタンを押す。
下側にグレイ文字でステイタスが表示される。

Status: No router found.

あら? DATA08WはUPnPに対応していない?
調べたらデフォルト設定でオフになっていた。
UPnPステータス”を有効にして、再チャレンジ。

Status: Failed to create port forwarding. See log for details.

ログ見ろってか...
DATA08W側にはログ表示機能はWebUIには見当たらない。
supersonicのログ見る。

supersonic@supersonic:/var/supersonic$ cat /var/supersonic/subsonic.log 
(snip)
[2012-12-27 22:11:25,200] WARN NetworkService - Failed to create port forwarding.
net.sbbi.upnp.messages.UPNPResponseException: Detailed error code :402, Detailed error description :Invalid Args
	at net.sbbi.upnp.messages.ActionMessageResponseParser.startElement(ActionMessageResponseParser.java:145)
	at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
	at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
	at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:392)
	at net.sbbi.upnp.messages.ActionMessage.service(ActionMessage.java:172)
	at net.sbbi.upnp.impls.InternetGatewayDevice.addPortMapping(InternetGatewayDevice.java:388)
	at net.sourceforge.subsonic.domain.SBBIRouter.addPortMapping(SBBIRouter.java:57)
	at net.sourceforge.subsonic.service.NetworkService$PortForwardingTask.execute(NetworkService.java:146)
	at net.sourceforge.subsonic.service.NetworkService$Task.run(NetworkService.java:309)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
	at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:165)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:267)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:679)

ダメそげね。
同じ問題の報告もあるな。
http://forum.subsonic.org/forum/viewtopic.php?t=3219)


DATA08Wのほうにportを指定したConeNATを設定した。
このへんは、説明面倒だから、各自勉強してね。
ケータイから3Gでアクセスしてみる。
httpで8080にアクセスすると、httpsの8443にリダイレクトされログイン画面が表示されるのを確認した。
しかし、DATA08Wには、MACアドレスIPアドレスに固定マップする機能がないので、普通に運用するにはムリがあるね。
家のルーターなら大丈夫なので、とりあえず今はこれでよしとする。

Supersonicクライアントの導入

apkはこれ。
supersonic-android-3.3.apk ― Supersonic Android App 3.3 (APK)
https://github.com/downloads/Mach5/supersonic/supersonic-android-3.3.apk
GooglePlayでは配布していないので、野良インストールになる。
入れてみようという人が、インストールしやすいように、QRコードを貼っておく。

ちなみに、こんな感じのQRの作り方はここに書いてある。
http://d.hatena.ne.jp/kinneko/20080708/p8


入れてみたけど、これ、アイコンがSubsonicのまんまやん... orz
広告除去しただけかしらん?
裏にふさわしいブラックさになってまいりましたよ〜(^^;。
不安な人は、ソース見てから、自分でビルドしてねん。


適当に設定を行なう。設定ボタンでメニューが出るのでSettingsを押す。
"Servers"のとこには、デフォルトではSubsonic demoというデモサービスが設定されている。
それはそのままにしておいて、Unused 1を選ぶ。
4つの項目を設定する。

一番下に"Test connection"という項目があるので、設定が終わったら押してみる。
”Connection OK”と出てきたら動いている。
手元では、接続はうまくいった。


トップ画面に戻って、Select serverでsupersonicを選ぶ。
あとは、普通に使うだけ。
ちゃんと音は出てきた。


クライアント画面でも、日本語のID3タグ情報は文字化けした。
OpenJDKのLocale設定で回避できるのだろうか?
それとも、ID3パースの処理に日本語対応を入れる必要があるのか?
それはわからない。
なんか、もうこれ以上労力をかけたくない気分...
たぶん、この調子だと、ディレクトリ名に日本語含まれていても、ちゃんとパースできなさそうな予感。

おしまい

とりあえず、お金かけずに、自前鯖でGoogleMusic環境と似たようなサービスが構築できた。


日本語パースの問題はあるみたいだけど、これはみなさんの冬休みの宿題ってことで(^^;。
楽曲名は、たぶん、ID3タグをUTF8/16とかにしてやれば問題ないんじゃないだろうか。
UTF-8であることが確認できたファイル使っても、うまく表示できないね。
それをツールでid3v2に変換してもダメみたい。
と、思っていろいろ試してみたけど、iTunesで変換したものはちゃんと日本語ファイル名は表示できたですよ... orz
設定で日本語指定したり、起動スクリプトで日本語ロケール強制したりもしてみている。


あとは、DDNSの設定でもしてもらえれば、名前引きでホスト指定できて、WAN IPの変更にも対応できて、シアワセになれると思うよ。
実際のとこ、no-ipでDDNS設定して、自動で更新テストするのは終わってる。
時間切れでまとめてないけどね。


sysvinitが気持ち悪い人は、起動スクリプトをsystemd用に設定書きなおしてみるとかもいいね。


あとは、ルーターの設定は、ConeNATじゃなくて、普通にポートフォワードでやってもいいと思うよ。


アプリのデザインがイマイチなので、誰かapkを使いやすく改造してくれい。


質問などあったら、twitterで@kinnekoまでMentionしてね。


これで、雑誌原稿書けって依頼も大歓迎です。
N7ほしー。N4ほしー。
原稿なら、頑張って不具合解析と対策するですよ!(実は、もうある程度実験してあります。)
スクリーンショットも撮ってあるよ。
こちらは、はてダだと、権利面で問題あったり、上げるのめんどくさいから入れてないだけですから〜。


携帯電話とペアリングした車載のBluetoothスピーカーに、Supersonicからストリーミング受けて、快適な通勤時間になりました!