Chienomi

Lighttpd使ってサクッとスマホでメディア再生

Live With Linux::practical

ずっと悩まされてきているのが、AndroidスマートフォンでPCのメディアファイルを再生したいということ。

基本的には音声ファイルと動画ファイルがターゲットだが、PCを使う想定であればSSHFSでおおよそ解決する。 まぁ、これもWindowsだとうまくいかない部分があるため、Linuxを要求し、そうなるとタブレットで使えるかどうかは微妙になったりするなど問題がないわけではない。

前提として、「ファイルをローカルにダウンロードして再生」であれば全く難しくないが、ここではストリーミングプレイしたいという前提があるということだ。

「おおよそ解決」は何が不完全なのかと言うと、DLsite Voice Utilsのような絶対パスを持つタイプのものはうまく再生できない。 これは、m3uプレイリストが絶対パスを持っている場合でも同様だ。

これに対する最適な方法は見つかっていない。 SSHFSはもちろんのこと、SMB, DLNAなどもAndroidスマートフォンがあまりうまく扱えず、NextCloudもすでにファイルシステム上にあるメディアファイルを一時的に共有するのには向いていない。

実はDLNAに関してはそれなりに有効そうな方法も見つけているのだが、それは別の回にしたいと思う。

結局、最適な解としては、必要なものを作るしかないのだろうと思う。 し、どういうものを作ればいいかはもうイメージにある。

しかしここではより簡易な解を求めたいと思う。

そこで登場するのがLighttpdだ。

Lighttpdについて

Lighttpd(ライティ)は安全・高速・柔軟を掲げるwebサーバーソフトウェアである。

少し前提の説明が必要になると思うのだが、Lighttpdが登場したとき、Apacheがほぼ唯一といっていいwebサーバーであった。

そしてそのApacheが2に移行していくわけだが、シングルコア・シングルプロセッサが当たり前で、サーバーリソースも非常に限られる中、マルチスレッドを前提としたApache2はtoo muchであるという見方が強く、設定が難しく保守も複雑であるため嫌がるユーザーが多かった。

そこに登場したのがLighttpdである。

シンプルな設定で使用メモリーが少なく、静的ファイルのサーブが非常に早く、FastCGIの設定も簡単。

ということで注目を集めて、Apacheから移行した人もそれなりにいたが、そこまで大人気にはならなかった印象がある。

個人的には結構好きだった。 機能的にも充実している上に使いやすい。

特徴的なポイントのひとつとして、CGIのパーミッションが問われないというのがある。 これは、Apacheのように対象のファイルをコマンドとして実行するのではなく、Lighttpd自体が関連付けられたインタープリターを起動し、その引数としてファイルを渡す方式であるためである。 このせいで、Cで書かれたCGIなどはenvに渡すなど工夫が必要。

現在でも、CGIアプリケーションを使用する場合の選択肢としてはかなり良い。 実はChienomiが動いているサーバーでもNginxの後ろにLighttpdのいる構成のサイトもある。

なぜLighttpdなのか

今までこういうときはWebrickを使っていたのに、なぜLighttpdを使うのか。

実はLighttpdを使うのが楽な理由があり

  • ディレクトリリストの機能を持っている
  • 任意の設定ファイルを指定してサーバーを起動できる
  • 設定ファイルの書き方が簡単
  • サーバー起動に必要になる前提が設定ファイルひとつだけ
  • ユーザープロセスとして起動可能

といった都合の多い要素が多い。

設定ファイルを作る

設定ファイルはパスを指定するので特に配置に制限はない。

ただ、今回の場合ひとつのサービスとして成立させるため、~/.config/reasonset/lmlighttpd以下にまとめることにする。

server.username     = "jrh"
server.groupname    = "jrh"
server.document-root    = "/home/jrh/.config/reasonset/lmlighttpd"
dir-listing.activate    = "enable"
dir-listing.encoding    = "utf-8"
index-file.names    = ( "index.html" )
server.port = 18888

$HTTP["remoteip"] !~ "192.168.1.0/24" {
  url.access-deny = ("")
}

ここでは(短時間しか起動しないこと、アクセスできるファイルの内容を鑑みて)IPアドレス制限で済ませているが、認証を必要としても良いだろう。

まずは、秘密ファイルを生成する。

print "USER:$(openssl passwd -apr1 PASSWORD)" > ~/.config/reasonset/lmlighttpd/lighttpd.user

USERPASSWORDは置き換える。

lighttpd.confの頭のほうにモジュールロードを追加。

server.modules = (
  "mod_authn_file",
  "mod_accesslog"
)

そして認証を追加する。

auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/home/jrh/.config/reasonset/lmlighttpd/lighttpd.user"
auth.require = ("/" => (
  "method" => "basic",
  "realm" => "lmlighttpd",
  "require" => "valid-user"
))

ファイルを配置する

Lighttpdをシンボリックリンクをデフォルトで許容する。

このため、~/.config/reasonset/lmlighttpd以下にシンボリックリンクでキャスストしたいファイルへのパスを用意すれば良い。

なお、仕組み上index.htmlファイルがあるディレクトリはリストされないので注意。

インデックスを用意する

手動で書いてもいいとは思うけども、Zshで

print -l *(@) | sed -e 's/^/* </' -e 's/$/>/' > index.md

とかすると簡単にファイルリストができるので、

pandoc -s index.md > index.html

とかやっておけば良い。

ユーザーユニットにする

Systemdを恐れる必要はない。

[Unit]
Description=Media serving lighttpd

[Service]
Type=simple
ExecStart=/usr/bin/lighttpd -D -f /home/jrh/.config/reasonset/lmlighttpd/lighttpd.conf

で、

systemctl --user start lmlighttpd

でOKだ。

アクセス

Linux PC側がAvahiでmdnsをキャストしているのであれば、Android端末もfoo.localのようなZeroconf名でアクセス可能。

ポート番号の指定が必要であることと、HTTPSでのアクセスはできないことに注意が必要だ。

つまり、

http://foo.local:18888

のようなアドレスにアクセスする。

Basic認証をかける場合は少しむずかしく感じるかもしれないが、

http://user@password:foo.local:18888

のようなアドレスでアクセスすると認証ダイアログなしでアクセス可能。

ただ、これはVivaldi Androidではあまりうまくいかなかった。 ブックマークに認証つきのアドレスを登録することはでき、一発でアクセスすることはできるのだが、その時点で認証情報を捨ててしまい、リンクを踏むと認証を要求されてしまう。

使い心地

メディア再生はブラウザの機能に依存しているため、Firefox Focusだとうまく動作しない。

また、Vivaldiの場合は「バックグラウンドでオーディオ再生を許可」を有効にしておかないと止まってしまう。 この設定は私が試した限り勝手にリセットされてしまうので注意が必要。

ディレクトリリストがPC向けになっていて、スマホでは拡大縮小を繰り返すことになり、プレイリストは使えないなど利便性は低いが、最低限再生はできる。