WebRTCに使うデバイスを選択するには（＋おまけ）

# はじめに

- この資料は、[WebRTC入門者の会(2016.11.01)](http://connpass.com/event/39679/)の発表資料です。
- WebRTCについては、前回のハンズオンの資料をごらんください。
  - [WebRTCハンズオン資料 INDEX - Qiita](http://qiita.com/yusuke84/items/de9f0f6d221acec6fc07)

---

## 自己紹介

- がねこまさし（@massie_g）
- 仕事: インフォコム(株)の調査研究チーム
    - Webの新しい技術担当
    - WebRTC, WebGL, WebVR とか
- コミュニティ
    - WebRTC Meetup Tokyo 開催協力者
    - HTML5Experts.jp エキスパート

---

## デバイス一覧の取得

利用可能な映像/音声デバイスの情報が取得できる

- navigator.mediaDevices.enumerateDevices() を利用
- Promiseを返す
    - 成功すると、デバイス情報のアレイが渡される
- 取得できるデバイス
    - オーディオ入力デバイス（マイク）
    - ビデオ入力デバイス（カメラ）
    - オーディオ出力デバイス（スピーカー）　※Chromeのみ(53～)

```js

navigator.mediaDevices.enumerateDevices()
.then(function(devices) { // 成功時
 devices.forEach(function(device) {
  // デバイスごとの処理
 });
})
.catch(function(err) { // エラー発生時
 console.error('enumerateDevide ERROR:', err);
});
```

---

## デバイス情報 MediaDeviceInfo

- デバイス情報 MediaDeviceInfo の内容
    -  deviceId （デバイスID)
    -  kind  （種類：　audioinput, videoinput, audiooutput ）
        -  ※ audiooutput は Chromeのみ
    -  label （名称）
        -  ※ 取得できる場合と、できない場合がある
    -  groupId 
        -  ※ 同一ハード機器内のデバイスでは同じになる仕様（けど、まだ？）

<img width="255" alt="devices.png" src="https://qiita-image-store.s3.amazonaws.com/0/19403/be0a4f3f-218d-c51d-b93d-1ddcf8c2b4ae.png">

---

## enumerateDevices()が使える条件
- Chrome file://〜, http://〜, https://〜
- Firefox file://〜, http://〜, https://〜

## label（名称）が取得できるケース
- Chrome https://〜 
- Firefox ユーザーがアクセスを許可している間
    - https://〜で「常に許可」したら、その後ずっと
    - 今回だけ「許可」したら、映像/音声を取得している間だけ

---

## デモ

https://mganeko.github.io/webrtcexpjp/tool/devicelist.html

## 参考：Firefoxでアクセス許可を変更

<img width="401" alt="firefox_device_permission.png" src="https://qiita-image-store.s3.amazonaws.com/0/19403/455fffe3-cc84-b69f-de07-9371d5f530e8.png">

---

### デバイスを指定して映像/音声を取得

- navigator.mediaDevices.getUserMedia()で条件（MediaStreamConstraints)を指定する

```js

  var constraints = {
    audio: {
     deviceId: audioId
    },
    video: { 
     deviceId: videoId
    }
  };

  navigator.mediaDevices.getUserMedia(
   constraints
  ).then(function(stream) {
   // 成功した時の処理
  }).catch(function(err){ // エラー時
   console.error('getUserMedia Err:', err);
  });
```

---

デモ

https://mganeko.github.io/webrtcexpjp/tool/devicelist.html


---
※ Chromeでこの形式で指定できるようになったのはごく最近（Chrome 53から?)

以前の指定形式

```js

  var constraints = {
    audio: {
     deviceId: {exact: audioId}
    },
    video: { 
     deviceId: {exact: videoId}
    }
  };
```

---

## Androidでフロント/バックカメラを指定

Android用Firefoxでは、次の指定で選択可能

```js

  // フロントカメラ（ユーザ側カメラ） ※デフォルトはこちら
  var constraints = {
    audio: true
    video: { 
     facingMode: "user" 
    }
  };
```

```js

  // バックカメラ（環境側カメラ）
  var constraints = {
    audio: true
    video: { 
     facingMode: "environment" 
    }
  };

```

※Android用Chrome54では、今現在動かない様子

---

## Fake カメラ/オーディオ

- Firefox ではFakeカメラ、Fakeオーディオが使える

```js

 var constraints = {video: true, fake: true, audio: false};
 navigator.mediaDevices.getUserMedia(
   constraints
 .then(function(stream) {
   // 成功時
 })
 .catch(function(err) {
   // エラー時
 });

```

---

## オーディオの出力先を指定する

- Chrome (54〜?)では、 videoタグ、audioタグの setSinkId() で指定可能
- Promiseを返す

```js

videoElement.setSinkId(audiId)
.then(function() {
 console.log('setSinkID Success');
})
.catch(function(err) {
 console.error('setSinkId Err:', err);
});
```

ユーザに音声出力デバイスを選択させることができる

---

## デモ

https://mganeko.github.io/webrtcexpjp/tool/devicelist.html

## ※注意
- 思わぬ大音量になることがある
- video/audioタグのボリュームを下げておくのが吉

---

## まとめ

- JavaScriptから、映像/音声デバイスの一覧を取得、デバイスを指定できる
- ユーザに利用するカメラ、マイク、スピーカー（ヘッドセット）などを選択する自由を提供できる
- 使い勝手の良いユーザーインターフェイスを提供して、魅力的なWebRTCアプリを作りましょう！

---

## おまけ captureStream()

- canvas.captureStream( fps )
    - Chrome, Firefox で利用可能
-  video.captureStream() / audio.captureStream()
    - Firefox では、video.mozCaptureStream() が使える
    - Chrome 54 では、 chrome://flags の変更で使える
        - 「試験運用版のウェブ プラットフォームの機能」　を有効に
        -  #enable-experimental-web-platform-features

<img width="603" alt="chrome_flags.png" src="https://qiita-image-store.s3.amazonaws.com/0/19403/4990239a-9bca-5c92-5043-6b06424a5e2a.png">


デモ: https://mganeko.github.io/webrtcexpjp/tool/video_to_stream_direct.html


※注意：取得したstreamの音量について

- Chrome では、capture元のvideo/audioの音量とは無関係
- Firefox では、capture元からは音が出なくなるが、音量は元のvideo/audioの音量に影響を受ける

---

## おまけ2 手動シグナリングでSDP書き換え

デモ：
https://mganeko.github.io/webrtcexpjp/basic2016/hand_signaling_modify.html

手順

- ブラウザA [StartVideo]
- ブラウザB [StartVideo]
- ブラウザA 
    - [Connect]
    - SDP 編集
    - [Set local SDP]
    - copy
- ブラウザB 
    - paste
    - [Receive remote SDP]
    - SDP 編集
    - [Set local SDP]
    - copy
- ブラウザB 
    - paste
    - [Receive remote SDP]