Windows10のWSLでX11アプリケーションを実行してみた + GStreamerを試してみた
最近、映像制御の仕事をすることになりました。
WSLを使って、作業効率をはかりたいと考えていますが、WSLは基本的にコマンドインターフェースなので、表示システムを作らなければなりません。
「Windows11にWSL2+Ubuntu20.04をインストールする」を試してみて、Golangをインストールしてみた件
すったもんだしているのですが、とりあえず、Windows10の方にX-Windowの方に、X serverを立てて表示ができたので、メモを残しておきます。
(というか、『Windows10上で、X-Windowsのサーバ動かす』という発想ができなかったので、
(gedit:5386): Gtk-WARNING **: cannot open display やらで、悩んでいました。
基本は、
Windows10のWSLでX11アプリケーションを実行してみた
の通りに実施したら動きました(実は、ここまで、手当たりしだい "sudo apt-get install" を乱発して
WSLの方から、
>export DISPLAY=:0
>gedit dummy.txt
と投入したら、X-windowsのエディタが立ち上がってきましたが、
など、たくさん問題が出ているようなので、対応を続けます(続く)
ところで、
WSLでGUIアプリを実行する
などで、自分の「上手くできなかったことを、きちんと書き残している方」のメモは本当に素晴しい。こういうメモは、普通の成功パターンしか記載していないメモの何十倍も役に立つのです。
で、まあ、それはさておき。
本命はこちら ――
GStreamer
です。
私、映像の伝送の研究は色々やってきたのですが(10~15年前)、映像そのものの研究は初めてなので、まずは、ローカルのパソコンで色々遊ぶ・・・もとい、調査することにしました。
で、今の私、GStreamerが何なのかも分かっていないのですが、「これを使え」と指示されているので、「これに突っ込んでいく」だけです。
マルチメディアフレームワークGStreamer ~ 入門編
を参考にさせて頂き、
$ export DISPLAY=:0
$ gst-launch-1.0 videotestsrc ! autovideosink
で、これが出てきました。
おお! やった!
WSLの方はこんな感じです。
$ gst-launch-1.0 filesrc location=./out.h264 ! avdev_h264 ! autovideosink
も、ちゃんと表示されるようです。映像の違いは分かりませんが。
カーネルコンパイルしたら表示されなくなりました(それが理由かは分かりません)。
$ gst-launch-1.0 -v videotestsrc ! x264enc ! avdec_h264 ! videoconvert ! autovideosink
で、表示できました。
(とりあえず、error: XDG_RUNTIME_DIR not set in the environment. だけでも潰しておこう)
ともあれ、最初の一歩は確保しました。
エラーコメントの表示対応のため、以下の設定をしておきました。
$ cd ~
$ vi .bash_profile
以下の2行を追加(正直、上の設定の意味は分からんが、とりあえずエラーは消える)。
export XDG_RUNTIME_DIR=/tmp/runtime-futa
export DISPLAY=:0
GStreamerによるレートコントロールについて調べています。
ラズパイにWEBカメラを接続してGStreamerを使った際に小一時間ハマった話
こちらに、
そして、例えば、任意のサイズやフレームレートでキャプチャを行いたい場合は、
video/x-raw,width=1280,height=720,framerate=30/1
のような指定を行います。
というような記載がありました。
$ gst-launch-1.0 videotestsrc ! autovideosink
をちょっと変更して試してみました。
$ gst-launch-1.0 videotestsrc ! videoconvert ! video/x-raw,width=1280,height=720,framerate=30/1 ! autovideosink
画面がでっかくなって表示されました。
$ gst-launch-1.0 videotestsrc ! videoconvert ! video/x-raw,width=1280,height=720,framerate=1/1 ! autovideosink
これで、1fpsの表示になりました。
で、実際に映像ファイル(start_up.mp4)を持ち込んで表示してみました。
$gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=30/1 ! autovideosink
これを、1fpsの表示に変えてみます。
$gst-launch-1.0 filesrc location=start_up.mp4 ! decodebin ! videorate ! video/x-raw,framerate=1/1 ! autovideosink
これを、1fpsのmp4ファイルとして保存してみます。
■1ftp映像に変換したもの "1ftp.mp4"
$ gst-launch-1.0 -e filesrc location=start_up.mp4 ! decodebin ! videoconvert ! videoscale ! videorate ! "video/x-raw,framerate=1/1" ! videoconvert ! x264enc bitrate=2000 ! mp4mux ! filesink location=1ftp.mp4
上記のコマンドでは、GStreamerのgst-launch-1.0
ユーティリティを使用しています。filesrc
エレメントを使用して入力ファイルを読み込み、decodebin
エレメントを使用してデコードします。その後、videoconvert
とvideoscale
エレメントを使用して動画の形式を変換し、videorate
エレメントを使用してフレームレートを変更します。最後に、x264enc
エレメントを使用してビットレートを設定し、mp4mux
エレメントを使用して新しいmp4ファイルに変換します。
ひき続き、SRTの通信実験を行ってみます。
(2)映像転送プロトコルは、現在、SRTが有力な候補
(a)タイムスタンプが付与した再送機能付きUDP(と理解)
(b)Gstreamerに標準装備されている(らしい)
で、高信頼の映像通信を実現するプロトコルのようです。
GStreamer で SRT を使用する その1
の内容をマネします。
私の場合、新規の設定をしないでも以下のコマンドが動きましたので、どっかで設定を終えてしまったのだと思います。
$ gst-launch-1.0 videotestsrc ! videoconvert ! x264enc tune=zerolatency key-int-max=30 ! mpegtsmux ! srtserversink uri="srt://:12345" latency=500
で、SRT の配信には、srtserversink を使用しているようです。
で、受信側は、VLCメディアプレーヤを用います。
※WSL2にしてカーネルコンパイルした後、
C:\Users\ebata>ipconfig
(中略)
Windows IP 構成
イーサネット アダプター vEthernet (WSL):
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: fe80::c317:ce40:f52f:1a41%40
IPv4 アドレス . . . . . . . . . . . .: 172.22.144.1
サブネット マスク . . . . . . . . . .: 255.255.240.0
デフォルト ゲートウェイ . . . . . . .:
しか使えなくなってしまったので、上記のVLCのアドレスは、
とする必要が生じました。
これで、「再生(P)ボタン」を押すと、テスト映像が表示されます。
次にWebRTCの実験を行います。
ここでは、
Go + GStreamer でお手軽 WebRTC 体験
を試させて頂きました。
GOのソースは一つだけだったので、WSL環境から行ってみました(最初、エラーの嵐だったのですが、よく考えれば、私はWSLの方にGStremaerの環境を立てていたので当然でした。
結構エラーが出てきましたので、色々対応をしていました。
sudo apt-get install libgstreamer-plugins-base1.0-dev
で、一部解決したのですが、以下のエラーが取れません。
# pkg-config --cflags -- gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 gstreamer-plugins-base-1.0 gstreamer-video-1.0 gstreamer-audio-1.0 gstreamer-plugins-bad-1.0 Package gstreamer-plugins-bad-1.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gstreamer-plugins-bad-1.0.pc' to the PKG_CONFIG_PATH environment variable
No package 'gstreamer-plugins-bad-1.0' found pkg-config: exit status 1
で、
https://github.com/notedit/gstreamer-go
に訪問してみたところ、
$ sudo apt-get install libgstreamer-plugins-bad1.0-dev
が、当たりだったようです。
で、後は上記のページの記載通りにGOプログラムを動かしたのですが、
2023/05/25 17:57:31 peer state change: failed
が登場してきて、変だなーと思ていたのですが、実はこれ成功しています。
このメッセージの上に、Goの出力の「長い文字列」が主力されていました。
これを入力して、「start session」ボタンを押下したら、以下の画面がブラウザに表示されました。
では、動作も確認できたので、ここからコードの勉強に入りましょう。
WebRTC を今から学ぶ人に向けて
の中にある、
WebRTC コトハジメ
が分かりやすい。
好奇心旺盛な人のためのWebRTC
も良い。
私はGolang使いなので、https://github.com/pion/webrtcを使いこなしたいが、膨大で手が出ない状況。今、とっかかりを探している。
とりあえず、wsl -d Ubuntu-20.04で、
ebata@DESKTOP-P6KREM0:/mnt/c/users/ebata/から、
get clone https://github.com/pion/webrtc で、インストール。
https://github.com/pion/webrtc/blob/master/examples/README.md
から、
$ cd webrtc
$ cd examples
$ go run examples.go --address :8080
で、ブラウザ http://localhost:8080で以下の画面が出てくる。
で、
のところで、"Run JavaScript"を押して、暫く(2~3分)待っていると、
という漢字で文字列が出てくるので、これを、上記のGo + GStreamer でお手軽 WebRTC 体験 のプログラムに放り込んで、同じように得られた文字列を放り込むと、
てな感じで映像が表示される。
$git clone https://github.com/pion/rtwatch.git
に挑戦。
https://github.com/pion/rtwatch の内容通りに設定するが、実行のところだけ少し違った
ebata@DESKTOP-P6KREM0:/mnt/c/users/ebata/rtwatch$ go run main.go -container-path=start_up.mp4
Video file 'start_up.mp4' is now available on ':8080', have fun!
これで、複数の、http://localhost:8080/ から同期した映像が配信されるようすが分かる。