2013/01/22

icecast2 で複数のストリームを流す(上)

とある、春に咲き春に散る花の名前を冠した会社の VPS を1年契約して、Ubuntu 12.04 の上で icecast2 サーバを稼働させています。

複数の異なるストリームを出したいと思っていたのですが、ちっともうまくいかず、2カ月の苦闘を経てやっときょう成功しました。超遠回りしたけど実はすごく簡単で、なぜもっと隅から隅まで設定を確認しなかったのか後悔しています。2カ月前、一番最初に試したことが一番正しい解決方法だったのに、おそらくはたった1つの設定ミスで、壮大な遠回りをしてしまいました。

その愚かな記録です。

----

サウンドカードがない VPS のマシンなので、サウンドシステムに依存しない(つまりはパイプでデータをやり取りする形で)仕組みを作っていくことにしました。大雑把にいうと次のような感じでパイプをつないでいます。

外の世界

icecast2

 ezstream  ←  ffmpeg  ←  (音を鳴らすアプリ)   … 1つのスクリプト

このうち、icecast2 はバックグラウンドで動いていて、ezstream までがクライアント系のスクリプトになっています(それぞれパイプで接続)。「音を鳴らすアプリ」は、ffmpeg に PCM の音データをパイプで渡せるものなら何でもOK。本当は aacplus を使いたいんだけど、stdin を直接 icecast2 なり shoutcast server なりに送り込んでくれる、しかもサウンドシステムにがなくても動いてくれるクライアントが ezstream 以外に見つけられなかったので、しかたなくこういう形をとっています。

(抜粋)

# 引数で実行オプション指定
# bitrateout
# portout
# channels

# プレイヤーからstdinでデータを受け取るエンコーダーの設定
# pipe:0, pipe:1 ともに "-" でよいはず

cmdEncoder="avconv -i pipe:0 -y -vn -f mp3 -b ${bitrateout} -ac ${channels} -ar 44100 pipe:1"

# icecast2 にデータを渡す ezstream のコマンド
# 入力ソースや出力先ポート、マウントポイント
# ezstream.xml で設定
cmdStreamer="ezstream -c /home/foo/icecast/ezstream_${portout}.xml"

# stdoutに PCM データを出力するプレイヤーなら
# 何でも音源になる
cmdSource="(プレイヤー実行のコマンド)"

# 単にパイプでつなぐだけwww
$cmdSource | $cmdEncoder | $cmdStreamer


で、「複数のストリームを出したい」というのは、音源は同じだけどビットレートが違うものを準備したいということでして、お恥ずかしながらこの2カ月ほど悪戦苦闘していました。

icecast2 に関しては、俺みたいなしろーとにも分かりやすい日本語で書かれたまとまった説明があーんまりなく、しかたなく英語のチュートリアルを渡り歩く感じ。自信のない読解力によると「icecast2 は複数のストリームを出せる」と書いてあり、/etc/icecast2/icecast.conf にポートとマウントポイント、ストリームの名前などを複数設定して、別々のクライアントから接続すれば何の問題もなくストリーミングを開始できるはずでした。

ところが…クライアント側のターミナルには「Failed writing」と表示が出て、icecast2 への送出に失敗してしまいます。icecast.xml などの設定を見直しても見直しても、やはりエラーが起こって、2つめ以降のクライアントを接続できません。正直、途方に暮れました。Shoutcast server のことも考えたけど、結局 stdin が使えるソースクライアントが見つからず icecast2 でやるしかないんだろう…という結論は変わりませんでした。

で、icecast.xml の「受けポート」の設定はこんな風。

<listen-socket> <port>54321</port> <!-- <bind-address>127.0.0.1</bind-address> --> <shoutcast-mount>/live24</shoutcast-mount> </listen-socket> <mount> <mount-name>/live24</mount-name> <username>source</username> <password>hackmenot</password> <stream-name>Live Streaming 24</stream-name> </mount>
普通に常識的に処理すればよさそうです。bind-address というのをまだよく理解してませんが、クライアントが localhost の範囲内ならコメントを外す必要もないんでしょう。

問題はここからだったんです。つか、icecast の設定ばかりに気を取られていたら、実は問題は ezstream の設定の方にあったんです。これにきょうのきょうまで気付いていませんでした。

実は ezstream.xml の冒頭 ezstream タグの次の行に、ストリームの URL を指定する行があるのですが、ここの

<url>http://localhost:54321/stream</url>
の設定がいけなかったようなんです。本当は、

<url>http://localhost:54321/live</url>
じゃなきゃいかんかった、ということです。マウントポイントの問題です。1つめのストリームはマウントポイントをデフォルトの /stream にしていたのですが、2つめ以降は何か別のものに変えなきゃいかんわけでして(無論、1つめから変えちゃっても構わないでしょ)、ということにも正直気付いてませんでした。ポート変えたらマウントポイントは同じでいいんでしょ?って勝手に思ってました。

さらにいけなかったのは、gedit のスコープの問題です(と他者のせいにする)。普通俺はこういう設定ファイルを編集する時に gedit を使うのですが、このファイルを見直す時に真ん中から下の方ばかり見て、この先頭の方の行をまったくチェックしていなかったのです。gedit のスコープ(見えてる範囲)から外れている最上部にそんな重要な項目があるという認識がまったくなかったのです。

ちゃんちゃん。全部、俺が悪いんです。石投げないでください。

で、これだけのことなら記録に残すことはなかったと思うのですが、ここまでやってきた試行錯誤の後始末でとんでもないトラブルを起こしてしまい(あるいは巻き込まれてしまい)、これは(まったく何の役にも立たないだろうけど)記録しとかなきゃ!と思ったので、(下)に続きます。

----

追伸:
今後の to do...

・24kbps とかなら aacplus のストリームにしたい
  ↓
・shoutcast を使いたい
  ↓
・darkice が必要
  ↓
・サウンドアダプタなしの環境で pulseaudio / jack を使いたい

ほかには…

・リレーとはいかに使用するものか追求
・外部のソースクライアントからデータを受ける方法を追求
・ストリームを再生する時のポートとマウントポイントの関係を知ること

----
(Jan.22, 2013)

0 件のコメント:

楽天モバイルを台湾で使ってみた

GWに、久しぶりに台湾に赴きました。コロナ禍の間に延命していた台湾大哥大と中華電信の回線のうち中華電信の方を失効させてしまい(なぜ中華電信だけ失効したんだろう)、今回の滞在は台湾大哥大と楽天モバイルの2回線で賄うことにしました。テザリングでAndroidスマホ1台とiPad、Ma...