Electronでカメラを使おう

なぜか知りませんが、全然説明がなくて、その上どハマりしたので書いておきます。 また、2020/6月時点での情報です。時代が進むにつれ、APIの形も変わると思いますので、情報が古くなっている可能性があります。

  • Electron@^9.0.0

ウェブアプリでカメラを使う

ウェブアプリでカメラを使うには、WebRTCのいち機能である getUserMedia を使います。 video タグにカメラの映像を流し込むのは、以下のようなコードで可能です。

// constraintsは要求するデバイスの条件を指定できる。解像度とか、フレームレートとか。上限下限とか。
const constraints = { video: true, audio: false };
const stream = await navigator.mediaDevice.getUserMedia(constraints);
// videoという変数にvideoタグのエレメントが入っているものとする
video.srcObject = stream;

video.src = URL.createUrlObject(stream) とかやってるやつは古いので、無視していいです。

また、ウェブカメラが複数あるなどして、ユーザーに選択させたい場合は以下のようにデバイスをリストアップすることも可能ですし、リストアップしたデバイスを指定して getUserMedia することも可能です。

const devices = await navigator.mediaDevices.enumerateDevices();
const stream = await navigator.mediaDevice.getUserMedia({ 
  video: { 
    deviceId: { 
      exact: devices[0].deviceId 
    } 
  } 
});

ここまでは、ふつうのウェブの話なので、とくに問題ありません。 問題はElectronでカメラを利用する場合です。

Electronでウェブカメラを利用する場合の問題点

Macではカメラアクセスのためにプライバシーの設定を突破する必要があるが、罠が多い。

これです。

プライバシーの設定を突破する

こんなんいるなんて、調べても全然出てこなかった! 最新のmacOSは結構厳しいので、そういうのが必要なのだろう思いながら調べてたんですが、全然それに言及してる人がいなくて、結構困りました。

const status = systemPreferences.getMediaAccessStatus("camera");
await systemPreferences.askForMediaAccess("camera");

しかし、これも罠があります。

ターミナルからアプリを起動する

みなさまにおかれましては、Electronアプリを起動するとき、 yarn electron . みたいなコマンドを叩いていらっしゃることでしょう。VSCodeのターミナルや、Intellijのターミナルから起動してるのではないですか?

上記プライバシーの設定を有効にした上でVSCodeIntellijからアプリを起動しようとすると、黙ってアプリがクラッシュします。 これもめちゃめちゃハマったんですが、VSCodeIntellijから立ち上げたプロセスはVSCodeIntellijに紐づくらしく、カメラへのアクセスを要求する者がVSCodeIntellijになります。Electronの肩代わりをしてくれるのですね。 しかし、こいつが罠で、VSCodeIntellijはカメラアクセスを要求可能にする設定が入ってないらしく、要求自体が不正であるということで、アプリがクラッシュするのですね。

そこで、どうするかというと、ふつうのターミナルから起動するようにします。 そうすると、きちんと ターミナルがカメラのアクセスを要求しています みたいなダイアログが表示されます。

ということで、Electronからウェブカメラを利用する方法でした。 以上です。よろしくお願いします。