🍃このブログは移転しました。
3秒後、自動的に移動します・・・。

2018年版: getUserMedia()で画面のストリームを取得する

2018年2月verです。
基本的に2017年8月に書いた記事と変わってない。NO進歩。

2017年版: getUserMedia()で画面のストリームを取得する - console.lealog();

この記事に書いてること + さらに最近調べたことをメモ。
なんかおかしかったら教えてください。

対応ブラウザ

以上。

Safariの実装は進んでるらしいが、まだ。

Chrome

これで得た`screenId`を使って`getUserMedia()`するだけ。

{
  video: {
    mandatory: {
      chromeMediaSource:   'desktop',
      chromeMediaSourceId: '', // 取れたscreenId
  },
}

`mandatory`とかいう古い感じの制約を指定するので、たとえば`width: { min: 300}`なんかは`maxWidth: 300`みたく書く必要があって、混ぜるとエラーになる。

Firefox

  • 拡張も設定も不要

`getUserMedia()`するだけ。

{
  video: { mediaSource: 'window' },
}

指定できるのはこの3つ。

  • `window`
  • `application`
  • `screen`

Chromeと違って、いつもどおりの書き方で`width`とかは指定できる。

その他

音声も送りたい

↑で書いたオブジェクトに、`{ audio: true }`を加えてご自由にどうぞ・・といけるのはFirefoxだけ。


Chromeは`{ audio: false }`しか認めてくれない。
なので別途用意しておいた音声の`MediaStreamTrack`と、画面のストリームに入ってる映像の`MediaStreamTrack`を使って、自前で新たな`MediaStream`を用意しないとダメ。

その他、画面共有されてるアプリから出てる音だけを送りたい・・みたいなのはできない。(今のところブラウザのあらゆるAPIを組み合わせてもできない)

と思ってたら、ご丁寧にTwitterで教えてもらえまして・・、

【備忘録】[getUserMedia] ChromeとElectron(とFirefox)でスクリーンキャプチャーおよびChromeとElectronで(システムまたはタブ)オーディオのキャプチャー - Qiita

この記事にあるように、Chrome拡張側でもその指定をしていれば、音声もまとめた`MediaStream`が取れるそうな。

まぁただWeb会議みたく通話しながら・・の場合は、打ち消し線のところで書いてるように、別途音声と画面の映像をマージして扱わないとダメなので、ケースに応じてかな。

`http://localhost`でもできるか

Chromeはできる。

Firefoxはデフォルトではできない。通常のカメラ映像の取得はできるのに・・。

`about:config`で、`media.navigator.permission.disabled`を`true`にすればできるようになる。
ただこのフラグ、`getUserMedia()`のパーミッションのダイアログをスキップする挙動になるので、

  • どのウィンドウを共有するとか選べない
  • デフォルトのカメラ・マイクから変更できない

というクソ仕様なので、ちょっとした挙動確認くらいにしか使えない。

画面共有を停止されたかどうか

Chromeはなんか画面の下の方に、ご丁寧に「共有を停止」みたいなUIを出してくれる。
あれで停止されると、ブラウザ外の出来事なのでどうやって拾えばいいの?ってなる。

あれを拾うには、取得した`MediaStream`もとい画面の`MediaStreamTrack`のイベントを監視する。

const [screenVideoTrack] = screenStream.getVideoTracks();

screenVideoTrack.addEventListener('ended', () => {
  // UIを戻すなりなんなり
}, { once: true });

この先の動きは?

Safariがいま実装してるように、将来的には`getUserMedia()`ではなく、`getDisplayMedia()`を使うようになるとは思う・・。

が、いつになるかわからんので気長に待ちましょう。