autofs+davfsマウントでmpd再生できるシステムを作ってみた。(備忘録) - takobozu/NanoPi-NEO2 GitHub Wiki
概要
以前、mpdに備わっているstorage plugin(webdav)を使って音楽再生するシステムを作った。しかし、そこでぼやいていたと思うが音楽フォルダ、ファイルの文字化けがひどく、
だめだ、こりゃ!
状態だった。そこで今回はリベンジとして、mpdのstorage pluginは使わず、davfsというファイルシステムを使ってQNAPのwebdavサーバーにアクセスし音楽再生するシステムを作ってみた。苦労はしたが、無事音出しができた。今回は、autofsを使ってcantataなどで音楽再生をしようとすると、autofsの機能によりwebdavサーバーの共有フォルダをdavfsマウントして再生を開始するシステムづくりの備忘録である。例によって俺にしかわからないと思う。備忘録だし。QNAPのwebdavの設定の仕方はここを参照。
システムづくりの留意点
kernel build
カーネルのmenuconfigで以下のところにチェック
File system ---> [*]FUSE(Filesystem in Userspace) support
buildroot
make menuconfig
autofsとdavfsは必須なのでチェックを忘れないように。
Target package ---> Filesystem and flash utilities --->[*]autofs [*]davfs2
make busybox-menuconfig
Linux System Utilities ---> [*]mount [*]Support mount helpers(これにチェックをいれとけとhelpにかかれていたので)
各種設定ファイル
/etc/davfs2/secrets
QNAPのwebdavサーバーの情報を書いておくもの。本システムでは、microSDカードにおいておき、起動とともにこのディレクトリにコピーされるようにしてある。気をつけなければならないのは、このファイルの権限だ。chmod で600に設定しておかないとdavfsマウントができなくなるので注意が必要。本システムでは起動スクリプトで権限設定をしている。内容は以下のような感じでテキストエディタで編集して保存する。
http://192.168.xxx.xxx/Multimedia/music takobozu xxxx
それぞれの項目はスペースかTABで開けておく。
http://~ はQNAP(webdavサーバー)の共有ディレクトリ
takobozu はQNAPのローカルユーザー名で共有ディレクトリへアクセスできる権限をもっているもの
xxxx はQNAPのtakobozuのログインパスワード
/etc/auto.master
autofsのための設定ファイル。ダイレクトマッピングにより行うため、以下のようにエディタで編集して保存する。
/- /etc/auto.misc --timeout=60 --ghost
/etc/auto.misc
autofsのための設定ファイル。ダイレクトマッピングにより行うため、以下のようにエディタで編集して保存する。
/mnt/music -fstype=davfs,ro :http\://$IP/$MUSICDIR
/mnt/music はNanoPi-NEO2上のマウントポイント。ここに、davfsによりQNAPの共有ディレクトリがマウントされる。
-fstype= はファイルシステムの種類 roは読み込み専用でマウントするという意味。
:http://~ はQNAPの共有ディレクトリだ。http\:のように:の前に\でエスケープすること。$IPはQNAPのipアドレス、$MUSICDIRは共有ディレクトリパスだ。本システムでは、上記の/etc/davfs2/secretsファイルの情報から、$IP,$MUSICDIRの2つの変数の中に格納されるように起動スクリプトを書いてある。(正規表現になれていないから、ほんと苦労した。)
システムの置き場所
バックアップのため今回作成したシステムをここにおいておく。
使い方を簡単に
-
起動ディスクの作り方はこことここを参照。u-boot.itbとsunxi-spl.binはここにおいてあるものを使えばいい。
-
secretsファイルは上記で述べたとおり自分の環境にあわせてエディタで編集して他のファイルと一緒にmicroSDカードに転送する。
-
NanoPi-NEO2にカードをセットして起動するとdhcpサーバーがあるLAN環境なら、ipアドレスをもらってネットに接続できる状態になるはずだ。
-
NanoPi-NEO2のipアドレスを確認してほしい。telnetでログインできるようにしてあるので root,パスワードなしでログインできる。俺はipadのNetwork Analyzer Liteと言うやつを使ってipアドレスを調べている。
-
cantataなどで上記で確認したipアドレスでNanoPi-NEO2の再生システムにアクセスする。最初は、databaseを作るため、cantataなら”データベースの更新”をクリックするとおそらくdatabaseが作られるはず(QNAPのアクセスランプが忙しそうに点滅するからわかる。)
-
更新が終了すると”フォルダ”タブのところに自分の共有ディレクトリ内の音楽フォルダ、ファイルがあるはず。
-
cifsマウントによる音楽再生システムで述べたと思うが、このままNanoPi-NEO2の電源を落としてしまうとせっかく作ったデータベースが吹き飛んでしまう。そこで、telnetでログインしているなら、/etc/poweroff.shを実行してこのシステムを終了する。すると、microSDカード上に "database"というファイルができているはずだ。次回の起動からは、このdatabaseファイルをルートファイルシステムに取り込んで起動するためデータベースの更新をする必要はない。
-
QNAPなどNAS上の音楽データを追加したり削除したりしてデータベースを更新してシステムを終了するときは上記のように/etc/poweroff.shを実行して終了すること。データベースの更新がなければ、いきなり電源を落としても何ら問題はない。ただ、今はデータベース更新が終わらないというけったいな不具合がある。解決できるかなあ。
-
これは注意だが、上記secretsファイルに記載する共有ディレクトリだが階層は2階層にしか対応していない。それ以外だと正常に動作しないのであしからず。(例えば QNAPのipアドレス/Multimedia/musicのような感じね。1階層の場合はQNAPのipアドレス/Multimedia/と最後に/をいれること。)
-
まあ、このシステムを使うような人はいないと思うが。不具合もあるので使わないほうがいい。笑
その後の感想
databaseの更新が途中で止まるので、思い切って音楽ファイル名、フォルダ名から日本語を排除する荒療治に取り掛かった。cifsでは問題なくてもwebdavでは問題がある、これはファイル名、フォルダ名の付け方に原因があると思い、Nameryとかいうファイル名を一括変換できるソフトなど使ってとにかく日本語を排除することを心掛けた。これでなんとかdatabase構築に成功した。ただ、
なんで、こんなに長い時間かかるんじゃい!
と短気な方には耐えられないであろうくらいdatabaseを作るのに時間がかかった。2時間を超えたからね。cifsマウントでは長くて、30分くらいだったように記憶している。とにかく、こんなに待たされることはない。まあ、davfs2.confの設定や、webdavサーバーの設定で速くなるのかもしれないが。ほとんどの人は実用性がないと判断するんじゃないかな。 今まで、cifs(過去にはnfsも経験済み),sshfs,davfsと様々なマウントの仕方でシステムを作ってみたが色々勉強になった。俺の耳ではマウントの方法や、upnpなどと比較して音にそんなに違いがあるとは思わなかった。フォルダ名やファイル名にわざわざ文字化けするかもしれないものを使わないようにしたおかげでおそらく以前試した、storage plugin(webdav)でも文字化けはせずdatabaseの構築はできると思う。タグ打ちさえちゃんと日本語で出来て表示が正しくできればそれでいいわけだし。
色々試せたことで、非常に勉強になったし、linuxの難しさ、面白さを改めて感じた次第である。
珍現象?
databaseをつくることには成功したが、反映されていないファイルがチラホラあった。それらに共通するのが
容量の大きなファイル
だ。たとえばdsdのファイルなど容量が250MBを超えるものはことごとくdatabaseに反映されない(cantataから見えない)。wavでも250MBを超えるものは見事に反映されていなかった。 windows用のCarotDAVという(webdav)davfsクライアントを使って共有ディレクトリにアクセスして確認したが、容量の大きいファイルもすべてちゃんと確認できるし、ダウンロードもできる。NanoPi-NEO2のシステムから共有ディレクトリをdavfsマウントしてその容量の大きなファイルを見にいったがちゃんと確認できた。なのにdatabaseの更新を何度かけても容量の大きなファイルは反映されない。 そこで以前作ったsshfsマウントでmpd再生するシステムに切り替え、databaseの更新をかけたら見事に更新され、今まで見えなかった容量の大きなファイルもcantataから確認できるようになった。うーん、なんだろな、これ。
知らぬ間にメモリ再生をやっていた!
このautofs+davfsのmpd再生システムの挙動について自分なりに色々観察してわかったことを書いておこう。
htopを見ていて、発見
このシステムで音楽を再生しながら、何気なくhtopを見ていた。cantataの再生ボタンをクリックすると、eth0が走っているcpu1の使用率がドーンと跳ね上がると同時にMemの部分がどんどん膨れ上がりあるところで止まった。再生していた曲が終わりに近づくとまたcpu1の使用率がドーンと跳ね上がり、Memが解放されたと思ったらまた値が増加した。曲の長さによって、Memの大きさも変わる。これは明らかにメモリ再生ではないか!えー、俺、そんなつもりなかったのに。w
databaseの更新ができない容量の大きいファイルの謎も解明
これもhtopを見ながらcantataでデータベースの更新をやったときに気づいた。曲の再生をしているときと同じ挙動(上記)を繰り返していたのだ。databaseの更新をするためにわざわざNAS上の音楽データをメモリ上に読み込んでいたのだ。だからdatabaseの更新にやたら時間がかかったわけだ。 そして、250MB以上のファイルがdatabaseに反映されない理由もわかった。このシステムはルートファイルシステムにcpio(initramfs)を使っている。digififanさんによると、このcpioは実メモリの半分をデフォルトで確保するそうだ。NanoPi-NEO2の実メモリは512MBなので256MBが実質フリーに使えるメモリとなる。だから、このサイズ以上のファイルをメモリ上にロードしようとしても不可能なのでdatabase自体も作成されなかったというわけだ。NanoPi-NEO2のメモリがもっと大きければ(例えば2GBとかね)それだけ大きな容量のファイルをメモリ上に一気に読み込めるということだ。これ、yungさんに教えてあげたら喜ばれるかもしれん。だっていちいち手動でメモリに音楽ファイルを転送する必要がないわけだから。
やったぜ、メモリ再生
こういうのを瓢箪から駒というんだろう。別にそんなことをやる気はなかったのに、素人があーでもないこーでもないと勉強になると思ってやっていたことからこんな再生ができるようなシステムができていた、そんな顛末だ。とにかくこのdavfsというやつ、もうちょっと突っ込んで勉強した方がいいかもしれん。こうやってドツボにはまっていくわけだ。 今現在、このシステムでは256MBを超える音楽ファイルを再生しようとするともちろん再生できず一瞬のノイズとともに次の音楽ファイルにスキップする。cifs,sshfsマウントのようなわけにはいかないのであしからず。ただし、メモリ上に読み込める音楽ファイルの再生は完璧、何の問題もない。それに音質は。。。。しばらく音楽を楽しもう。
色々なファイルを再生していてわかったこと
音楽データ1ファイルあたりの大きさは200MB未満に抑えた方がスムーズに再生されるようだ。203MBあるflacファイルなんか再生できなくはないがちょっとノイズがでて再生がいったん止まったりすることもあるので。まあ、今後も色々なサイズのものを再生してみてどんな挙動をするかを観察していく。
大きなファイルの問題
このシステムは音楽データを一曲ずつすべて取り込んでから再生するので、シベリウスの交響曲第2番の第3楽章と第4楽章の間のように全く無音の部分がないようなものだと、第4楽章のような大きなファイル(wavだと200MB以上になる)は取り込むのに若干時間をようするので、無音状態が発生する。flacで半分くらいに圧縮(100MBくらい)にするとこの問題はなくなる。(全曲をflacにするのではなく第4楽章だけ圧縮するのもいいね。w)又は、この交響曲全体を1つのwavにしてこれを一気に取り込めるくらいのメモリ容量があれば問題はなくなる、、がNanoPi-NEO2のメモリ容量だとうーん、今のところ無理。
大きなファイルの切り替わり時のノイズの問題
このシステムで200MB前後の大きさの音楽ファイルを連続して再生させると曲と曲の間にどうしてもプツとノイズが走っていたのだが以下の点に留意することで問題がなくなった。今回の試したアルバムの構成は以下の通りである。
ノイズがでなくなるようにした方法
- NanoPi-NEO2はGBetherなのだが、QNAPとの間にルータを2個通したりしていたので1つのgigabit対応のルーター(あるいはスイッチングハブ)を介してQNAPとNanoPi-NEO2を接続するようにした。(できればQNAPとNanoPi-NEO2は直結するのがベストだろう)
- mpd.confで audio_buffer_sizeを8192に,buffer_before_playを70%に設定した。
試聴したアルバムの構成
以下はすべて24bit,192kHz,flacだ。
- 1トラック目 193MB 5:23
- 2トラック目 122MB 3:30
- 3トラック目 160MB 4:16
- 4トラック目 180MB 5:12
- 5トラック目 171MB 5:00
- 6トラック目 157MB 4:27
- 7トラック目 190MB 5:23
- 8トラック目 106MB 3:08
- 9トラック目 120MB 3:26
- 10トラック目 134MB 3:48
以下は24bit,44.1kHz,wavだ(第4トラックだけ24bit,44.1kHz,flac)
- 1トラック目 151MB 9:45
- 2トラック目 206MB 13:20
- 3トラック目 97MB 6:19
- 4トラック目 76MB 13:06
なぜ4トラック目だけflacにしたか?以前にも述べたが3トラック目と4トラック目の間が全く無音部分がないものはノイズがでるんだが今回の対策兼4トラック目だけflacにすることで、切り替えノイズが全くなく再生できるようになった。
あと、16bit,44.1kHz,wav,246MB、約20分ほどの再生時間だが、中に12トラック含まれておりcueシートを読み込むタイプのものも一気にメモリに取り込まれ再生に成功した。もちろんノイズなし。
一応バックアップのためmpd.confを上記のように修正したものを後でアップする。
あるパターンで曲を再生しようとすると再生できなくなる問題に対する対処
このシステムはカーネルもルートファイルシステムもすべてメモリに読み込まれる、これを頭においておかないといけない。このシステムにログインしていくらルートファイルシステムをいじってもそれはメモリ上のものをいじっているにすぎず、電源を落としたとたん、いじった痕跡はすべて跡形もなく消失する。
このシステムでマウントに使用しているdavfsの挙動をコントロールしているのが/etc/davfs2/davfs2.confだ。このファイルの中身を見てみるとcache_sizeというのがある。僕は最初、このシステムのデフォルトである、50MBのままにしてあった。こうするとどうなるかというと、曲の再生が終わったあとでもそのファイルは/var/cache/davfs2/マウントディレクトリ に残り続ける。例えば1曲目から5曲目までそれぞれのサイズが10MBの音楽ファイルを再生していったとしよう。cantataの再生ボタンをクリックするとまず1曲目のファイルがメモリにロードされその後再生が開始される。1曲目が終わり2曲目に差し掛かろうとすると2曲目のファイルがメモリにロードされその後再生が開始される。このメモリにロードされたファイルは上で決めたcache_sizeになるまでメモリに存在しつづける。具体的には5曲目の再生が終わったあとも1曲目から5曲目は/var/cache/davfs2/マウントディレクトリ以下につまり本システムではメモリに残り続けるわけだ。ここで6曲目の再生が開始されるとどうなるかというと、6曲目のファイルサイズにもよるが、上のファイルサイズ50MBになるようにメモリに先にロードされたファイルから順次削除されていく。
それなら1曲目から50MBの音楽ファイルならどうだろうか。例えば、60MBとか。もちろん、cantataで再生を開始すればちゃんとメモリにロードされる。そして2曲目がどんなファイルサイズの音楽ファイルであろうとメモリにロードされると1曲目のファイルはメモリから削除される。例えば、2曲目が10MBであれば1曲目の60MBはメモリからいなくなり、10MBは2曲目の再生が終わってもメモリに残る。なら、2曲目がまた60MBならどうか?もちろんこれでも1曲目の60MBは2曲目が読み込まれると同時に削除され、2曲目の60MBがメモリに残るわけだ。
さて、もしこのようなパターンの再生が行われたときこのシステムはどうなるか。
- 1曲目10MB
- 2曲目30MB
- 3曲目250MB
1曲目、2曲目とも問題なく音楽は再生される。問題は3曲目だ。1曲目、2曲目を足しても50MB以下なのでこの2つのファイルはメモリにキャッシュされたままだ。そして3曲目の読込が開始される。すると、256MBのcacheサイズに達するとはじかれたようにまた最初から3曲目を読み込もうとする、また256MBに達するとまた最初から3曲目を読み込もうと、、、この無限ループを繰り返すことになる。以前も話したが、NanoPi-NEO2は実メモリが512MBしかなく、ルートファイルシステム(initramfs)がカーネルも含めて実メモリの半分を確保する。残りが256MBがフリーのメモリ空間なのだかどうもこの壁にぶち当たるためこのような挙動になるようだ。
この問題に対処するためdavfs2.confのcache_sizeを0に設定した。これにより、メモリにロードされたファイルを再生するというメモリ再生には違いないが、次の曲がロードされると同時にそれ以前にロードされたファイルが消去されていれば上記のようなことにはならないというわけだ。 もちろん、上の256MBの壁を忘れてはならない。このサイズを超える音楽ファイルは再生が無理なのは当然だ。
256MBの制約はあるが快適に再生できるシステムとなった。このcache_size 0 にしたrootfs.cpio.gzはこれを書いている時点ですでにアップロード済みだ。
雑感
このシステムでdatabaseを作らせるとあほ程時間がかかるため、cifsなどで作ったdatabaseを流用した方がいい。あと、やはりメモリが大きいシングルボードコンピュータ(俺はNUCでもシステムつくれるからね。)の方がサイズの大きなファイルを取り込めるのでここでのノウハウを生かして色々作っていきたいと思う。
もういっちょ、不思議でもなんでもないが面白い挙動のご報告
上記で、cache_size 0の変更を加えたことを述べたが、このシステムで以下のようなファイルを再生すると、うーん、それはなあ、って挙動をする。
1つのファイルでcueでトラックを読み取るもの。
例として手元にある246MBあるwavファイル(cue付き)のものがあるのでそれで確認した。cantataでcueファイルを選択してキューに加えるとプレイキュー上では12トラックに分割されて表示される。再生を開始し、曲の再生が次トラックにいくたびに246MBすべてのファイルがメモリに再ロードされる。これは当然で次のトラックを再生しようとしてもそのトラックだけのファイルはなくそれを含むwavファイルがあるだけなのでそのファイル全体をメモリに取り込みなおすしかないわけ(不具合でもなんでもない、当然の挙動だ)俺のコレクションはトラック毎にファイルが分かれているものがほとんどなのでこんな無駄のことにはならないのだが。こういう一つのファイルをcue分割で読み込む形式でファイルをコレクションしている人は、davfs2.confのcache_sizeを0ではなくメモリに取り込めるサイズギリギリに設定すれば、曲が切り替わるたびにメモリに再ロードみたいなことは起こらない。ただ、このcache_sizeを設定すると上記にある問題にぶつかる可能性がでてくる。だから
(メモリに取り込めるファイルサイズの上限)- (すでにcache_dirにあるwav+cueファイルのサイズ)> (次に再生できるwav+cueファイルのサイズ)
という不等式を厳格に守らないとこのシステムは再生できなくなるというわけだ。まあ、こんなこと考えながら音楽鑑賞は楽しめないかもね。笑
もちろん、このシステムの状態のまま(cache_size 0)でもcantataでcueファイルを選択するのではなく、wavファイルを選択してキューに加えるとトラックは分割されて見えないが1トラック目から行儀よく最後まで聴きたいということであれば、トラックが進むごとにメモリにwavファイル全体を再ロードといった挙動にはならないので、念のため。
高音(特に弦の音の)キツさを解消
どうも、弦の音色が美しくないというか、耳をつんざくような高音に悩まされていた。うーん、upnpのときはこんなことなかったのになあ、と思いながらこれで諦めていてはこのシステムに申し訳ない。そこで設定を思い切っていじってみることにした。
Timer frequencyの変更
upnpではTimer frequencyを250MHzしていたがこれを1000MHzにした。驚いたのは、耳をつんざくような高音がなくなったことだ。これはkernelをビルドしなおしたものをここにアップした。
kernel.sched_rt_runtime_usの変更
upnpではkernel.sched_rt_runtime_usを970000にしていたがこれも上下に振って変化を確認した。800000まで下げるとあの耳をつんざくような根音が再現された。990000以上だと耳をつんざくことはあまりないがちょっと美しくないかな。ということで980000で落ち着いた。これが今のところこのシステムから出てくる音では俺好み。この変更をしたルートファイルシステム(rootfs.cpio.gz)もここアップした。
2018/09/15 変更内容
microSDカードに主なconfファイルを置くようにした。
以前までにmicroSDカードにはこのようなファイルがあった。
Image___boot.scr___rootfs.cpio.gz___secrets___sun50i-h5-nanopi-neo2.dtb___database(mpdに作らせるとできる)
ここに以下のディレクトリ、ファイルを追加した。
conf(ディレクトリ)---dhcpcd.conf___mpd.conf___sysctl.conf
dhcpcd.conf
このシステムではdhcpcdが走るようにしてあったが再起動の都度ipアドレスが変わると鬱陶しいのでipアドレスを固定できるようした。dhcpcd.confの中身をエディタ等で見ると最後の方に
interface eth0
static ip_address=192.168.xxx.xxx/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
という部分があるので自分の環境にあわせて書き直し、再起動(本システムではrebootコマンドで再起動できる)すると設定が反映される。 dhcpサーバーからipアドレスをもらえる状態に戻したければ、上記4行をコメントアウト(各行の先頭に#をつける)してrebootするともとに戻る。
dhcpcdはシステム起動後20秒経過するとkillするように設定してあるがこれをするとdroppedされるパケットが発生する。(徐々に増える)dhcpcdをkillしなければdroppedは生じない。原因がdhcpcdをkillすることにあるとわかっているので気にしない。
mpd.conf
これはいわずもがなだろう。エディタで変更してrebootすれば変更が反映される。
sysctl.conf
カーネルの挙動を色々変えられるものだが、kernel.sched_rt_runtime_usを変えて遊びたいためにここに置くようにした。エディタで追加、変更してrebootすればそれらが反映される。
ethtoolの追加
ethtoolを追加したのは、offloadの設定を変更を試したかったからだ。offloadとは簡単に言うとcpuにさせることをethernetに肩代わりさせることでcpu負荷をさげるようにすることだ。ネットで調べると色々なことが言われているが真偽のほどはよくわからないので実際に音に影響があるかどうかを試したかった。本システムの2018/09/15時点での設定はtx off rx off(チェックサムオフロードをオフ)にしている。
ここに変更したファイル等をおいてある。
segmentation fault networkで悩まされる
eth0をdhcpcdを使わず、完全に固定ipで設定するようにルートファイルシステムをビルドしなおしてハマった。
segmentation fault network
というエラーでeth0が認識されないのだ。dhcpcdを使っていたときもこのエラーが出ていたのだが、なぜかeth0が認識されていたので気づかなかった。かなりしんどかったが原因が分かった。それが
busybox
だった。このバージョンが1.29.0以上をビルドして組み込むとこのエラーがでる。そこで1.28.4(1.28.xの最終バージョン)までさかのぼってようやくeth0が認識され、ipアドレスもinterfacesに設定したとおりに反映されるようになった。buildrootで最新のものばかりでビルドを繰り返しているとこのようなことに遭遇する。仕方のないことだ。
2018/09/21 変更内容
dhcpcdを走らせるのをやめ固定ipの設定ができるようにした。
ここのconfディレクトリにinterfacesを追加した。 この設定ファイルの雛形を自分の環境に合うように編集して保存しておくと起動時にこの設定が読み込まれる。dhcpcd.confは廃止した。
dma-controllerとmpdのcpu affinityを変更した。
具体的には、mpdのスレッドはすべてcpu3で処理されるようにした。dma-controllerは従来cpu2で処理されるようにしていたが、これもcpu3で処理されるようにした。
mpd.confの内容の一部を変更した。
audio_buffer_sizeを8192から4096へ、buffer_before_playを70%から40%へ変更した。あとoutputスレッドの優先度を54から99に変更した。
しばらくこの設定でいく。
(2018年9月25日追記)
ハイレゾのような1ファイルあたりの容量が大きいやつをメインに再生する場合は、
audio_buffer_size 8192
buffer_before_play 70%
のままがいい。
いやー、参った
これまで色々中身をいじりながら音の変化を確認してきたが、2018/09/21の変更点でかなり音が変化し俺好みの音となった。今は、es9023搭載のdacで聴いている。メモリ再生は、INTEL NUCでやったことがあるが音についてはここまで感動はしなかった。どんなシングルボードコンピュータを使おうがdacを使おうが、ソフトウエアとハードウエアの環境次第でこんな音が絞り出せるのだ。まあ、こんな環境つくって音を聴いているのは俺くらいだろう。これが快感なんだよな。