
# 2025.1.x から 2025.2.x への移行

Sora Android SDK 2025.1.x から 2025.2.x へのアップデートではいくつかの破壊的変更と SDK としての新機能があります。

このドキュメントでは、それらの変更点と移行方法について説明します。


## シグナリングの `"type": "connect"` メッセージの JSON に `multistream` 項目をデフォルトでは含めないように変更

2025.1.x まではデフォルトの挙動として `multistream: false` を connect メッセージに設定していましたが、2025.2.x 以降はデフォルトでは `multistream` 項目を含めないようにしました。

### 経緯

Sora は 2025 年 6 月のリリースでレガシーストリームが廃止され、connect メッセージの multistream 項目が廃止されました。

この変更に合わせて Sora Android SDK でも connect メッセージの multistream 項目をデフォルトで送信しない仕様に変更しました。

これに伴い、デフォルトでは `multistream` を含めない挙動にするために  `SoraMediaOption` の設定に応じて自動的に connect メッセージに `multistream: true` を設定する仕様も廃止しました。

### 影響を受けるケース

2025.1.x までは Sora Android SDK のデフォルト挙動は multistream 項目に `false` を入れて connect メッセージを送信するようになっていたため
この挙動に依存している場合は影響を受けます。

### 移行方法

2025.1.x までのデフォルト挙動と同じように connect メッセージに `multistream: false` を含ませたい場合は `SoraMediaOption.enableLegacyStream()` を呼び出してください。

```kotlin
val option = SoraMediaOption().apply {
   // 明示的に multistream を false に設定する
   enableLegacyStream()
}
```


## シグナリングの `"type": "connect"` メッセージの `multistream` を自動で true に設定する仕様を廃止

2025.1.x までは `SoraMediaOption` の設定時に条件に応じて自動的に connect メッセージに `multistream: true` を設定していましたが、
2025.2.x では本仕様を廃止しました。

廃止の経緯は [シグナリングの "type": "connect" メッセージの JSON に multistream 項目をデフォルトでは含めないように変更](2025_1_to_2025_2.html#9f84aa) の経緯に記載しています。

### 影響を受けるケース

自動的に `multistream: true` が設定される仕様に依存していた場合は影響を受ける可能性があります。

2025.1.x までで `multistream: true` が設定されていた条件:

- Sora がデフォルトでレガシーストリームを使うように設定されている、かつ SoraMediaOption が以下のいずれかの設定になっている場合- `enableAudioDownstream()` または `enableVideoDownstream()` を呼び出している、かつ `enableAudioUpstream()` または `enableVideoUpstream()` を呼び出している場合
  - `enableSpotlight()` を呼び出している場合

### 移行方法

`SoraMediaOption.enableMultistream()` を使うことで connect メッセージに `multistream: true` を含めることができます。

```kotlin
val option = SoraMediaOption().apply {
   // 明示的に multistream を true に設定する
   enableMultistream()
}
```


## WebSocket が Sora から切断された際に受信したステータスコードが 1000 以外の場合でも onError を呼び出さないように変更

2025.1.x までは、WebSocket 切断時のステータスコードが 1000 以外の場合に `onError` を呼び出していましたが、2025.2.x からは `onError` を呼び出さないように変更しました。

### 経緯

WebSocket 切断時のステータスコードが 1000 以外の場合に `onError` を呼び出す仕様でしたが、実際にはそれ以前に切断処理が実行されており `onError` を実装している Listener の参照がなくなっているため、`onError` が呼び出されるケースはほとんどありませんでした。

また、2025.2.x からは `onClose` で切断時のステータスコードと理由を取得できるようになったため、
ユーザーが Sora から受信したステータスコードと切断理由を用いて、エラーハンドリングを行うことができるようになりました。

これを踏まえ、WebSocket 切断時のステータスコードが 1000 以外の場合に `onError` を呼び出す必要はないと判断し、 `onError` を呼び出さないように変更しました。

### 影響を受けるケース

- ステータスコード 1000 以外の Sora からの切断を onError によって検知する実装を行っていた場合

### 移行方法

ステータスコード 1000 以外の Sora からの切断を検知する場合は、 `onClose` でステータスコードと切断理由を取得してエラーハンドリングを行ってください。

```kotlin
private val channelListener = object : SoraMediaChannel.Listener {

   // onError ではなく onClose でエラーハンドリングを行うようにしてください
   override fun onClose(mediaChannel: SoraMediaChannel, closeEvent: SoraCloseEvent) {
      // 実装例
      // ステータスコード 1000 以外の Sora からの切断はエラーとして扱う
      when {
          closeEvent.code != 1000 -> Log.e(TAG, "onClose: エラーにより Sora から切断されました: $closeEvent")
          else -> Log.d(TAG, "onClose: Sora から正常に切断されました: $closeEvent")
      }
   }
}
```


## SoraMediaOption.videoCodec 未設定時の動作変更

2025.1.x までは `SoraMediaOption.videoCodec` が未設定の場合、connect メッセージの `video.codec_type` に自動で VP9 が設定され送信されていましたが、
2025.2.x からは、未設定の場合は `video.codec_type` を送信しなくなりました。

`video.codec_type` が未設定の場合、VP9 がデフォルトで設定されます。

詳しくは Sora のドキュメントの [ビデオコーデック指定](https://sora-doc.shiguredo.jp/SIGNALING#d47f4d) を参照してください。

### 影響を受けるケース

- `SoraMediaOption.videoCodec` が未設定、かつ `SoraMediaOption.videoVp9Params` を設定している場合

### 移行方法

影響を受けるケースに該当する場合は、以下のように `SoraMediaOption.videoCodec` を明示的に設定することで対処できます。

```kotlin
val option = SoraMediaOption().apply {
   // videoCodec を明示的に設定する
   videoCodec = SoraVideoOption.Codec.VP9

   videoVp9Params = object {
      var profile_id: Int = 0
   }
}
```


## SoraMediaOption.audioCodec 未設定時の動作変更

2025.1.x までは `SoraMediaOption.audioCodec` が未設定の場合、connect メッセージの `audio.codec_type` に自動で OPUS が設定され送信されていましたが、
2025.2.x からは、未設定の場合は `audio.codec_type` を送信しなくなりました。

`audio.codec_type` が未設定の場合、OPUS がデフォルトで設定されます。

詳しくは Sora のドキュメントの [オーディオコーデック指定](https://sora-doc.shiguredo.jp/SIGNALING#0fcf4e) を参照してください。

### 影響を受けるケース

- `SoraMediaOption.audioCodec` が未設定、かつ `SoraMediaOption.audioOption.opusParams` を設定している場合

### 移行方法

影響を受けるケースに該当する場合は、以下のように `SoraMediaOption.audioCodec` を明示的に設定することで対処できます。

```kotlin
val option = SoraMediaOption().apply {
   // audioCodec を明示的に設定する
   audioCodec = SoraAudioOption.Codec.OPUS

   audioOption = SoraAudioOption().apply {
      opusParams = OpusParams(
         stereo = true,
         useinbandfec = true,
      )
   }
}
```


## onError(SoraMediaChannel, SoraErrorReason) を廃止

2025.1.x までは、2 種類の onError がそれぞれ異なるタイミングで発火していましたが、
2025.2.x からは `onError(SoraMediaChannel, SoraErrorReason)` が廃止され、エラー発生時のコールバックは `onError(SoraMediaChannel, SoraErrorReason, String)` のみとなりました。

これにより、2 種類の onError の実装を行う必要がなくなり、エラーハンドリングの実装が簡素化されます。

onError の詳細は、コールバックドキュメントの [onError](callback.html#e9c61c) を参照してください。

### 移行方法

以下のように両方の onError を実装している場合、2025.2.x からは `onError(SoraMediaChannel, SoraErrorReason, String)` のみを利用するように修正してください。

```kotlin
private val channelListener = object : SoraMediaChannel.Listener {

   // この onError は廃止となるため、削除してください。
   override fun onError(mediaChannel: SoraMediaChannel, reason: SoraErrorReason) {}

   // この onError を実装してください。
   // 特に message がない場合は空文字列が渡されます
   override fun onError(mediaChannel: SoraMediaChannel, reason: SoraErrorReason, message: String) {
      // エラー処理や切断処理を記述する
   }
}
```


## 解像度維持方法の fixedResolution を廃止、 DegradationPreference を追加

2025.1.x までは送信する映像の解像度維持の方法として `CameraCapturerFactory.create` の引数 `fixedResolution` に true を指定していましたが、
2025.2.x ではクライアント側の状況により設定した解像度やフレームレートを維持できなくなった場合にどのように質を下げるか制御できるパラメータ `DegradationPreference` を `SoraMediaOption` に追加し、
`fixedResolution` による解像度維持は廃止しました。

これに伴い `fixedResolution` は `CameraCapturerFactory.create` の引数から削除され、また `CameraVideoCapturerWrapper` クラスは `fixedResolution` 使用のためのラッパークラスだったため不要となり削除されました。
移行方法の内容に従い、`CameraCapturerFactory.create` 呼び出し箇所のコードを修正する必要があります。

`DegradationPreference` の指定は必須ではありません。指定しない場合(null)は、libwebrtc デフォルトの挙動として `MAINTAIN_FRAMERATE` で動作します。

### 移行方法

2025.2.x からは以下のように `CameraCapturerFactory.create` 呼び出し箇所から `fixedResolution` に該当する引数を削除してください。

```kotlin
// 実装例
override fun createCapturer(): CameraVideoCapturer? {
   // 移行前(第二引数が fixedResolution)
   return CameraCapturerFactory.create(context, true, frontFacingFirst)

   // 移行後
   return CameraCapturerFactory.create(context, frontFacingFirst)
}
```

`DegradationPreference` を使用するには `SoraMediaOption` のパラメータとして指定します。
指定できる値は以下のようになります

- `MAINTAIN_RESOLUTION`: 解像度を維持し、フレームレートを下げる
- `MAINTAIN_FRAMERATE`: フレームレートを維持し、解像度を下げる
- `BALANCED`: フレームレートと解像度のバランスを取る
- `DISABLED`: 品質調整機能を無効化

```kotlin
fun connect() {
   ...
   val mediaOption = SoraMediaOption().apply {
      ...
      // degradationPreference の指定を追加する例
      degradationPreference = SoraVideoOption.DegradationPreference.MAINTAIN_RESOLUTION
      ...
   }
}
```


## Sora からの切断理由を取得できる onClose の追加

> **注釈**
>
> この変更は破壊的変更ではありませんが、移行をおすすめします。

2025.1.x までの onClose では Sora から切断された際の理由を取得できませんでしたが、2025.2.x からは切断理由を取得できる onClose を新たに追加しました。

これにより、Sora から切断された理由が認証エラーなのか、切断 API による切断なのかなどの情報を取得できるようになります。

onClose の詳細は、コールバックドキュメントの [onClose](callback.html#a1232c) を参照してください。

### 移行方法

旧 onClose を削除して新しい onClose を追加してください。

```kotlin
private val channelListener = object : SoraMediaChannel.Listener {

   // この onClose は削除します。
   override fun onClose(mediaChannel: SoraMediaChannel) {}

   // 新しい onClose を追加します。
   override fun onClose(mediaChannel: SoraMediaChannel, closeEvent: SoraCloseEvent) {
      // 実装例
      // Sora から切断された理由をログに出力する
      when {
          closeEvent.code != 1000 -> Log.e(TAG, "onClose: エラーにより Sora から切断されました: $closeEvent")
          else -> Log.d(TAG, "onClose: Sora から切断されました: $closeEvent")
      }
      // 切断されたときの処理を記述する
   }
}
```
