Webエンジニアの備忘録

およそ自己の作業メモとして残しております。

getUserMedia() でカメラ・マイクのブロックを個々に検知

最近詰まったので、メモっておくことにします。

ブロックによるエラーの特徴

ブラウザから getUserMedia() を用いてカメラやマイクにアクセスすると、それらのデバイスへのアクセス許可が必要になります。これがブロック状態であった時に NotAllowedError が飛んで来ます。 ただし、カメラ・マイクともにアクセスを求めた際、どちらかが利用できる状況であればブロックエラーが取得できません。

navigator.mediaDevices.getUserMedia({ audio: true, video: true })
  .then((stream) => {
    this.setState({ stream });
  .catch(err => console.log(err)); // カメラ・マイクともにブロックの場合のみ NotAllowedError を受け取る

上記のブロックを受けた場合は音声のみの動画、または音声のない動画が取得出来ます。これはこれで、プライバシーを尊重したブロックの結果なのですが、開発都合で個々のブロックをキャッチしたいケースが多々あると思います。

対応策

以下のコードが対応策を施したものです。 stream を取得したい getUserMedia を実行した後に、 マイクのみ、カメラのみの getUserMedia を実行することで、こちらが NotAllowedError エラーを取得してくれます。

navigator.mediaDevices.getUserMedia({ audio: true, video: true })
  .then((stream) => {
    this.setState({ stream });

    // マイク単体検証(ブロック有無)
    navigator.mediaDevices.getUserMedia({ audio: true })
      .then(streamTmp => streamTmp.stop())
      .catch(err => console.log(err));

    // カメラ単体検証(ブロック有無)
    navigator.mediaDevices.getUserMedia({ video: true })
      .then(streamTmp => streamTmp.stop())
      .catch(err => console.log(err));
  })
  .catch(err => console.log(err));

getUserMediaを連投して大丈夫かな、という懸念はありましたが、Android数端末、Windows等で確認したところ問題は見られませんでした。 ただ個別チェックに利用した stream は取得後すぐに止めています。( streamTmp.stop()

所感

急場しのぎではありましたが、比較的シンプルに対処ができてよかったです。 それでも、これより良い解決方法などありましたらご享受いただければ幸いです。コメントなどください。