




# 開発ガイド

## Sora iOS SDK 全般

### Sora iOS SDK の構成要素

Sora iOS SDK は次の要素を中心に構成されます。


#### メディアチャネル

メディアチャネル ( [MediaChannel](_static/api/docs/Classes/MediaChannel.html) ) は WebRTC のメディアチャネルを表します。 Sora iOS SDK ではメディアチャネルの ID を指定して Sora に接続します。


#### ロール

ロール (`Role`) はメディアチャネルが扱う音声と映像の送受信の方向を表します。
ロールは接続 1 つにつき 1 つです。ロールの種類を次に示します。

- 送信のみ (`Role.sendonly`) は端末の音声と映像を Sora に送信します。
- 受信のみ (`Role.recvonly`) は Sora から音声と映像を受信します。
- 送受信 (`Role.sendrecv`) は送信と受信の両方を行います。


#### メディアストリーム

メディアストリーム ( [MediaStream](_static/api/docs/Protocols/MediaStream.html) ) は音声と映像のストリームを表すオブジェクトです。
マルチストリーム機能では同チャネルへの接続数と同じ数のストリームが使用されます。

メディアストリームの取得方法は 2 種類あります。

1. メディアチャネル ( [MediaChannel](_static/api/docs/Classes/MediaChannel.html) ) のプロパティから取得する

Sora への接続後、 [MediaChannel](_static/api/docs/Classes/MediaChannel.html) の以下のプロパティより接続中の [MediaStream](_static/api/docs/Protocols/MediaStream.html) の取得が行えます

- streams: 全てのメディアストリームのリスト
- senderStream: 送信されるメディアストリーム
- receiverStreams: 受信したメディアストリームのリスト
- mainStream: 先頭のメディアストリーム- 単一映像を受信のみするケース、単一映像を送信のみするケースでの利用を想定しています

2. メディアチャネル ( [MediaChannel](_static/api/docs/Classes/MediaChannel.html) ) のイベントハンドラから取得する

Sora への接続後、 [MediaChannel](_static/api/docs/Classes/MediaChannel.html) のイベントハンドラである [MediaChannelHandlers](_static/api/docs/Classes/MediaChannelHandlers.html) より追加、または削除された [MediaStream](_static/api/docs/Protocols/MediaStream.html) の取得が行えます

- onAddStream: 追加されたメディアストリーム
- onRemoveStream: 削除されたメディアストリーム

#### 映像ビュー

映像ビュー (`VideoView`) はメディアストリームの音声と映像を描画するビューオブジェクトです。いずれのロールの映像も描画できます。


### SDK のログをコンソールに出力する

`Logger` の `level` プロパティでログレベルの指定が可能です。
デフォルトのログレベルは `.info` です。

例: デバッグログを出力する


```
Logger.shared.level = .debug
```

## WebRTC

### WebRTC ライブラリのバージョンを知りたい

`WebRTCInfo` の `version` プロパティで Sora iOS SDK が使用する WebRTC のバージョンを取得できます。
メジャーバージョンがリリースブランチを表します。

### WebRTC ライブラリの API を使う

WebRTC ライブラリの API (接頭辞が `RTC` のもの) を使うには、 `WebRTC` フレームワークをインポートする必要があります。
ファイルの先頭に `import WebRTC` を記述してください。

### WebRTC ライブラリのログをコンソールに出力する

WebRTC の挙動について Sora iOS SDK より詳細なログを出力したい場合は、 `Sora` オブジェクトの `setWebRTCLogLevel()` を使ってログレベルを指定します。


```
// 最も詳細なログを表示する
Sora.setWebRTCLogLevel(.verbose)
```

### メディア制約を指定する

メディア制約は `MediaConstraints` で表されます。
`MediaConstraints` を `WebRTCConfiguration` の `constraints` プロパティにセットすることでメディア制約を指定可能です。

### ICE サーバーの URL を指定する

ICE サーバーの情報は `ICEServerInfo` で表されます。
サーバーの URL をセットした `ICEServerInfo` を `WebRTCConfiguration` の `iceServerInfos` プロパティに指定します。

## シグナリング

### メタデータを指定する

[任意の JSON 値の送受信](metadata.html#3ee49a) をご確認ください。

### 送受信されたシグナリングの内容を確認する

シグナリングの内容はデバッグログを有効にするとコンソールに出力されます。
設定方法は [SDK のログをコンソールに出力する](devguide.html#e94c1e) をご確認ください。

## 接続

### Sora に接続する

大まかな手順を次に示します。
[Sora に接続する](signaling.html#39218d) も参考にしてください。

1. `Configuration` を生成します。Sora のシグナリング URL 、チャネル ID 、ロールをセットします。
2. `Sora` オブジェクトの `connect(configuration:webRTCConfiguration:handler:)` を実行します。実行後は `handler:` に渡したブロックが実行されます。
3. 接続が成功するとストリームが生成されます。このストリームは `mainStream` プロパティでアクセスできます。

### 接続試行時のタイムアウトを設定する

接続試行時のタイムアウトまでの秒数は、 `Configuration` の `connectionTimeout` プロパティで指定可能です。
`connect(configuration:webRTCConfiguration:handler:)` で接続が成立せずにタイムアウトになると、 `handler` ラベルに指定したブロックが実行されます。
このとき、ブロックの引数にタイムアウトを示すエラー (`SoraError.connectionTimeout`) が渡されます。

### 接続試行をキャンセルする

接続試行中に処理をキャンセルしたい場合は、 `connect(configuration:webRTCConfiguration:handler:)` の戻り値である `ConnectionTask` オブジェクトの `cancel()` を実行します。
すでに接続済み、またはキャンセル済みの場合は何も起こりません。

### 再接続を行う

予期しない原因で接続が解除されたときに再接続を行いたい場合は、接続解除を検知する `onDisconnectHandler` イベントハンドラを利用して実装可能です。

次に `MediaChannel` のイベントハンドラを使う例を示します:

```
mediaChannel.handlers.onDisconnectHandler = { error in
    // 予期しない接続解除の場合のみ再接続する
    if error != nil {
        // 10 秒後に再接続する
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 10) {
            Sora.shared.connect(configuration: configuration) { chan, error in
                ...
            }
        }
        return
    }
}
```

再接続を実装する際は次の点に注意してください:

- この方法による再接続とは「新しい接続」であり、接続解除前の状態を引き継ぐものではないので注意してください。Sora は再接続に対応していません。
- 同一のチャネル ID に再接続する場合、再接続を行うまでの時間が短いと、シグナリング時にチャネル ID 重複エラー (`DUPLICATED-CHANNEL-ID`) が発生する可能性があります。このエラーが頻発する場合は、ある程度時間を空けてから再接続を行ってください。現在の Sora の仕様では、待ち時間は Sora の稼働状況に依存します。運用の仕方に応じて待ち時間を調節してください。
- 接続/切断処理の連続実行してしまうとクラッシュが発生することがあります。対策について詳しくは [接続/切断処理の連続実行でクラッシュが発生する](faq.html#3cce94) をご確認ください。

### イベントハンドラを使用する

Sora iOS SDK は次のイベントハンドラを提供しています。
詳しくは [API リファレンス](api.html#72dc36) をご確認ください。

- WebSocket (`WebSocketHandlers`)
- メディアストリーム (`MediaStreamHandlers`)
- メディアチャネル (`MediaChannelHandlers`)

### 配信ストリームを取得する

配信ストリーム (端末のカメラとマイクのメディアデータを送信するストリーム) は `MediaChannel` の `senderStream` プロパティで取得できます。

### 受信ストリームのリストを取得する

受信ストリームのリストは [MediaChannel](_static/api/docs/Classes/MediaChannel.html) の `receiverStreams` プロパティで取得できます。

### 受信ストリームに紐づく Sora のコネクション ID を取得する

[MediaStream](_static/api/docs/Protocols/MediaStream.html) の `streamId` プロパティにはストリームを送信したクライアントのコネクション ID が設定されています。
受信した [MediaStream](_static/api/docs/Protocols/MediaStream.html) は [MediaChannel](_static/api/docs/Classes/MediaChannel.html) の `receiverStreams` プロパティや、 [MediaChannel](_static/api/docs/Classes/MediaChannel.html) のイベントハンドラである [MediaChannelHandlers](_static/api/docs/Classes/MediaChannelHandlers.html) から取得できます。

## 映像と音声

### 映像と音声の可否を指定する

映像なら `Configuration` の `videoEnabled` プロパティ、音声なら `audioEnable` プロパティで指定可能です。

### 映像・音声コーデックを指定する

映像コーデックなら `Configuration` の `videoCodec` プロパティ、音声コーデックなら `audioCodec` プロパティで指定可能です。

### 映像ビットレートを指定する

`Configuration` の `videoBitRate` プロパティで指定可能です。


### 送受信された映像を描画する

映像は VideoView で描画できます。
VideoView をストリームの `videoRenderer` プロパティにセットします。
詳しくは [映像を描画する](videoview.html#6bc6da) をご確認ください。

サンプルコード:

```
let config = Configuration(url:
    URL(string: "ws://192.168.0.2:5000/signaling")!,
                           channelId: "soraapp",
                           role: .sendonly)
Sora.shared.connect(configuration: config) { chan, error in
    if let error = error {
        // エラー処理
        return
    }

    // VideoView をストリームにセット
    chan!.mainStream?.videoRenderer = self.videoView
}
```

### 映像フレームを加工・編集する

[映像フレームを加工・編集する](videoview.html#65faf8) をご確認ください。

### Interface Builder で VideoView を配置する

ウィンドウに View コンポーネントを配置し、インスペクタの Custom Class の "Class" に "VideoView" を、 "Module" に "Sora" を指定します。

![image](images/quickstart/videoview_customclass.png)

### 音声をミュートする、音量を変更する

[音声の操作](audio.html#55dc00) をご確認ください。

### 映像と音声の送受信を一時的に停止する

接続中に映像または音声の送受信を一時的に停止・再開するには、 `MediaStream` の次のプロパティを利用します。

- 映像の停止と再開: `videoEnabled` プロパティ
- 音声の停止と再開: `audioEnabled` プロパティ

それぞれのプロパティに `false` をセットすると、送受信を停止します。
`true` をセットすると送受信を再開します。

### 任意の音声を送信したい

WebRTC ライブラリの制約により、 Sora iOS SDK ではマイク入力以外の音声を送信できません。ご了承ください。

## カメラとマイク

### カメラとマイクを初期化する

映像送信時、 Sora への接続に成功すると、端末のカメラとマイクが自動的に準備されます。
必ず事前に [Info.plist の設定](setup.html#153cee) をしておいてください。
無設定だとアプリケーションが強制終了します。

### マイクをミュートする

Sora iOS SDK ではマイクをミュートする API を用意していません。
`AVAudioSession` などを利用してください。

### カメラ（マイク）のアクセス権をユーザーに要求しない

カメラ（またはマイク）の初回起動時は、カメラとマイクへのアクセス権を求めるダイアログが表示されます。
ダイアログの表示に関しては次の制限があります。

- **使わないデバイスのダイアログを非表示にできない。**映像のみ、または音声のみの利用であっても、カメラとマイクに関する 2 つのダイアログが表示されます。これは libwebrtc の仕様であり、 Sora iOS SDK では変更できません。
- **ダイアログを表示するタイミングを制御できない。**ダイアログはカメラやマイクへのアクセスがあると起動されますが、アクセスがなくても表示される場合があります。これは libwebrtc の仕様であり、 iOS の仕様です。
