Web上のオンライン会議システムなどで画面共有するさいに、Screen Capture APIが使われる。 getDisplayMedia demoで試せばすぐわかるがウィンドウ毎にキャプチャ(画面共有)できる。

興味深いのはウィンドウが下に隠れていてもキャプチャされ続けることだ。 コンポジット型ウィンドウマネージャを使う現代において下に隠れているウィンドウは再描画され続けている。 これをそのままキャプチャできるわけだ。 (古典的なキャプチャツールの xwd や ffmpeg の x11grab などでは見たままの通り上にウィンドウが乗っていたらそれがキャプチャされる)

半透明のときは勿論、そうでなくとも下のウィンドウも再描画され続けている

これを単にミラーリング的な使い方をしてみたい。

TL;DR

% gst-launch-1.0 -v ximagesrc xid=$XWINDOW_ID ! videoconvert ! autovideosink

ximagesrc

ximagesrc は何もしないとディスプレイ全体を取り込む。 一方で XID を指定して特定のウィンドウを取り込むことができる。

"xid" guint64

The XID of the window to capture. 0 for the root window (default).

XID というのは X Window の Window id のことだ。 典型的な方法としては xwininfo を使って調べる。

% xwininfo                                                                                                  ~

xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.

マウスポインタが「+」の形に変わるので、XID 調べたいウィンドウをクリックすると情報が表示される。

xwininfo: Window id: 0xc000007 "Noto Sans CJK JP"

  Absolute upper-left X:  568
  Absolute upper-left Y:  239
  Relative upper-left X:  568
  Relative upper-left Y:  239
  Width: 802
  Height: 641
  Depth: 32
  Visual: 0xc2
  Visual Class: TrueColor
  Border width: 0
  Class: InputOutput
  Colormap: 0xc000006 (not installed)
  Bit Gravity State: NorthWestGravity
  Window Gravity State: NorthWestGravity
  Backing Store State: NotUseful
  Save Under State: no
  Map State: IsViewable
  Override Redirect State: no
  Corners:  +568+239  -550+239  -550-200  +568-200
  -geometry 802x641+568+239

長々と貼り付けたが今注目するのは Window id: 0xc000007 のところだけで XID は 0xc000007 ということになる。 このとき、下記のように入力して使うことになる。

% gst-launch-1.0 -v ximagesrc xid=0xc000007 ! videoconvert ! autovideosink

なお、XID を調べるのならば wmctrl -l を実行して XID 一覧を出してそこから探しても良い。 ただこの手法だと同一のウィンドウ名(タイトル)がある場合は区別が付かない。

videoconvert ! autovideosink

コンバートをかけて、 autovideosink を指定するといい感じに出力される。

autovideosink is a video sink that automatically detects an appropriate video sink to use. It does so by scanning the registry for all elements that have “Sink” and “Video” in the class field of their element information, and also have a non-zero autoplugging rank.

こうしてウィンドウで表示されることになる。

表示されるウィンドウ

こうして表示されたウィンドウはリサイズできるが、キャプチャ対象のウィンドウはリサイズできない。 リサイズするとこの GStreamer が落ちてしまった。 リサイズする度に実行し直しが必要なようだ。

おまけ:マルチモニタ時の画面キャプチャについて

複数のモニタがつながった大きさのものがそのままキャプチャされてしまう。

マルチモニタ環境時の ximagesrc 実行結果

モニタごとに見るには範囲指定をするしかない。

例えば、一つのモニタのサイズが1920x1080ならば、この例ならばオフセットとして1920を横に付けてやればよい。

横につなげた場合の2枚目のオフセット

コマンドとしては例えば下記のようになる。

% gst-launch-1.0 -v ximagesrc startx=1920 ! videoconvert ! autovideosink

参考文献