NetBSDとGoogle Chtomecast

この記事は、NetBSD Advent Calendar 2019の2日目の記事です。

はじめに

いつだったか忘れてしまいましたが安売りをしていた時に、Google Chromecastを購入していました。 ですが、スマートフォンやPCのGoogle Chromeから投影しないといけないので、 自立しているAmazon Fire TV Stickに比べて活躍の機会があまりありませんでした。

NetBSDラップトップから画面を投影できるのであれば、HDMIケーブルで接続しなくて良いかもしれません。 今回は、NetBSD環境の画面を投影してみました。

ライブラリーを選定する

ウェブを検索してみると、以下の4つの方法が有望そうです。

後ろから2つはnode.jsのモジュールです。 これはpkgsrcではパッケージングしにくいので、上から2つを試してみました。

VLCのscreen://を試す

結果から言うと、依存しているlibmicrodnsがNetBSDに対応しておらず、ビルドできませんでした。 MCAST_JOIN_GROUPがヘッダーファイルで定義されていない場合のコードが、正しくないようです。 RFC3678を良く読まないといけないようなので、今回は断念しました。

pyChromecastを試す

pyChromecastは、pkgsrc/net/py-pychromecastに用意しました。 以下のようにインストールできます。

$ cd /usr/pkgsrc/net/py=pychromecast
$ make install
ただし、pyChromecast自体はライブラリーだけなので、サンプルプログラム等が付属する訳ではありません。 pyChromecastzeroconfというPythonのみで書かれたライブラリーのあかげで、無事に使うことができました。 pyChromecastのREADME.rstを参考に以下のようなファイルを作って実行してみました。 30秒のビデオが再生できました。
import time
import pychromecast

chromecasts = pychromecast.get_chromecasts()
cast = next(cc for cc in chromecasts if cc.device.friendly_name == "Living Room TV")
cast.wait()
print(cast.status)

mc = cast.media_controller
mc.play_media('https://www.ryoon.net/~ryoon/BigBuckBunny.mp4', 'video/mp4')
mc.block_until_active()
mc.play()
time.sleep(30)
mc.stop()
Chromecastへ映像を送る方法は分かりました。

次に画面をChromecastに送る方法を考えてみます。 自分のChromecastから見える場所にビデオストリームを置いてやれば良いはずです。 画面をキャプチャーするのは、ffmpegx11grabソースが一番手軽なように思います。 そして、ffmpegと組み合わせるとなると、一番簡単に使えるのはffserverです。 ffserverは、pkgsrc/multimediaffmpeg3を最後に削除されてしまいました。 そこで、今回はffmpeg4パッケージではなくffmpeg3を使うことにします。

さて、そもそも、Chromcastが再生できるビデオストリームとはのような仕様でしょうか? Supported Media for Google Castのページによると、 WebMコンテナーのVP8ビデオであれば再生できそうです。 解像度は、1980×1080も可能なようですが、1280×720で進めてみます。

このようなビデオを配信するffserver3の設定ファイルは以下のようになります。 サウンドは今回は配信しません。

Port 8090
BindAddress 0.0.0.0
MaxHTTPConnections 1000
MaxClients 200
MaxBandwidth 10000
CustomLog -

<:Feed screen.ffm>
File /tmp/screen.ffm
FileMaxSize 20M
<:/Feed>

<:Stream screen.webm>
Feed screen.ffm
Format webm
VideoCodec libvpx
VideoFrameRate 30
VideoSize 1280x720
VideoBitRate 512
VideoBufferSize 80
VideoGopSize 30
NoAudio
<:/Stream>
実行は以下のようにします。。
$ ffserver3 -f ffserver3-vp8.conf
これで、http://localhost:8090/screen.ffmffmpeg3コマンドでビデオを送信してやると、 http://10.81.0.117:8090/screen.webm (ここで、10.81.0.117はNetBSDラップトップのIPアドレス)でストリーミング配信されます。

これに画面の左上1280×720ピクセル分を流し込むには、以下のように実行します。

ffmpeg3 -f x11grab -r 30 -s 1280x720 -i :0.0 -vcodec vp8 -c:v libvpx -b:v 2M -threads 2 -s 1280x720 http://localhost:8090/screen.ffm

このストリーミング配信を再生するようにChromecastに指示するのは以下のようなファイルを用意します。

import time
import pychromecast

chromecasts = pychromecast.get_chromecasts()
cast = next(cc for cc in chromecasts if cc.device.friendly_name == "Living Room TV")
cast.wait()
print(cast.status)

mc = cast.media_controller
mc.play_media('http://10.81.0.117:8090/screen.webm', 'video/webm; codecs="vp8, vorbis"')
mc.block_until_active()
mc.play()
time.sleep(120)
mc.stop()
ファイル名をscreencast.pyとすると、以下のように実行します。2分間再生します。
$ python3.8 screencast.py

私の環境では、約5秒から15秒で遅れで配信することができました。 ffmpeg3コマンドのオプションを工夫することで、遅延は短くできるかもしれません。

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

MPEG 2.5

MPEG 2.5と言う表記を見掛けたのだが、どういうものか理解できなかった。 /usr/pkgsrc/audio を以下のように検索すると、 /usr/pkgsrc/audio/libmad/DESCR に、MPEG-2 extension to Lower Sam...