

# IVS 廣播 SDK：行動音訊模式 \| 即時串流
<a name="broadcast-mobile-audio-modes"></a>

音訊品質是任何即時媒體經驗的重要組成部分，而且不存在適用於所有使用案例的通用型音訊組態。為了確保您的使用者在收聽 IVS 即時串流時獲得最佳體驗，我們的行動 SDK 提供了多種預設音訊組態，以及視需要提供的更強大自訂功能。

## 簡介
<a name="broadcast-mobile-audio-modes-introduction"></a>

IVS 行動廣播 SDK 提供一個 `StageAudioManager` 類別。這個類別被設計成單一接觸點，用於控制兩個平台上的基礎音訊模式。在 Android 上，這可以控制 [AudioManager](https://developer.android.com/reference/android/media/AudioManager)，包括音訊模式、音訊來源、內容類型、使用情況和通訊裝置。在 iOS 上，它可控制應用程式 [AVAudioSession](https://developer.apple.com/documentation/avfaudio/avaudiosession)，以及是否啟用 [voiceProcessing](https://developer.apple.com/documentation/avfaudio/avaudioionode/3152101-voiceprocessingenabled?language=objc)。

**重要事項**：當 IVS 即時廣播 SDK 啟用時，請勿與 `AVAudioSession` 或 `AudioManager` 直接互動。因為這可能會導致音訊遺失，或是從錯誤的裝置錄製、播放音訊。

在建立第一個 `DeviceDiscovery` 或 `Stage` 物件之前，必須先設定 `StageAudioManager` 類別。

------
#### [ Android (Kotlin) ]

```
StageAudioManager.getInstance(context).setPreset(StageAudioManager.UseCasePreset.VIDEO_CHAT) // The default value

val deviceDiscovery = DeviceDiscovery(context)
val stage = Stage(context, token, this)

// Other Stage implementation code
```

------
#### [ iOS (Swift) ]

```
IVSStageAudioManager.sharedInstance().setPreset(.videoChat) // The default value

let deviceDiscovery = IVSDeviceDiscovery()
let stage = try? IVSStage(token: token, strategy: self)

// Other Stage implementation code
```

------

如果在初始化 `DeviceDiscovery` 或 `Stage` 執行個體之前，未在 `StageAudioManager` 上作任何設定，則會自動套用 `VideoChat` 預設值。

## 音訊使用案例預設集
<a name="broadcast-mobile-audio-modes-presets"></a>

即時廣播 SDK 提供三組預設值，每組都是針對常用案例量身打造，如下所述。每組預設值都涵蓋五個關鍵類別，好將各組預設值區分開來。

**音量鍵**類別是指透過裝置上的實體音量鍵使用或變更的音量類型 (媒體音量或通話音量)。請注意，這會影響切換音訊模式時的音量。例如，假設裝置設定為使用視訊聊天預設值時音量為最大值。切換到「僅訂閱」預設值，會導致與作業系統不同的音量，這可能會導致裝置上的音量大幅改變。

### 視訊聊天
<a name="audio-modes-presets-video-chat"></a>

這是預設值，專為本機裝置與其他參與者進行即時對話設計。

**iOS 的已知問題**：使用此預設值且不連接麥克風，會導致音訊透過耳機 (而不是裝置喇叭) 播放。此預設值只能與麥克風搭配使用。


| Category | Android | iOS | 
| --- | --- | --- | 
| 回音消除 | 已啟用 | 已啟用 | 
| 雜訊抑制 | 已啟用 | 已啟用 | 
| 音量鍵 | 通話音量 | 通話音量 | 
| 麥克風選擇 | 受作業系統限制。USB 麥克風可能無法使用。 | 受作業系統限制。USB 和藍牙麥克風可能無法使用。<br />同時處理輸入和輸出的藍牙耳機應能正常工作，例如 AirPods。 | 
| 音訊輸出 | 任何輸出裝置都應能正常工作。 | 受作業系統限制。有線耳機可能無法使用。 | 
| 音訊品質 | 中/低。聽起來像是在講電話，而非播放媒體。 | 中/低。聽起來像是在講電話，而非播放媒體。 | 

### 僅限訂閱
<a name="audio-modes-presets-subscribe-only"></a>

此預設值是為您訂閱其他發布參與者的計畫而設計，並非用於發布自己。它專注於音訊品質且支持所有可用的輸出裝置。


| Category | Android | iOS | 
| --- | --- | --- | 
| 回音消除 | Disabled | Disabled | 
| 雜訊抑制 | Disabled | Disabled | 
| 音量鍵 | 媒體音量 | 媒體音量 | 
| 麥克風選擇 | 不適用。此預設值不是為發布而設計。 | 不適用。此預設值不是為發布而設計。 | 
| 音訊輸出 | 任何輸出裝置都應能正常工作。 | 任何輸出裝置都應能正常工作。 | 
| 音訊品質 | 高。任何媒體類型都應該能清晰地播放，包括音樂。 | 高。任何媒體類型都應該能清晰地播放，包括音樂。 | 

### Studio
<a name="audio-modes-presets-studio"></a>

此預設值是為了高品質的訂閱而設計，同時也保持了發布能力。它需要錄製和播放硬體才能提供回音消除功能。這裡的一個使用案例就是使用 USB 麥克風和有線耳機。SDK 將保持最高品質的音訊，同時依靠這些裝置的物理分離防止回音。


| Category | Android | iOS | 
| --- | --- | --- | 
| 回音消除 | Disabled | Disabled | 
| 雜訊抑制 | Disabled | Disabled | 
| 音量鍵 | 大多數情況下的媒體音量。連接藍牙麥克風時的通話音量。 | 媒體音量 | 
| 麥克風選擇 | 任何麥克風都應該可用。 | 任何麥克風都應該可用。 | 
| 音訊輸出 | 任何輸出裝置都應能正常工作。 | 任何輸出裝置都應能正常工作。 | 
| 音訊品質 | 高。雙方應該都能發送音樂並在另一側清晰地聽到。<br />連接藍牙耳機後，音訊品質可能會因為啟用了藍牙 SCO 模式而下降。 | 高。雙方應該都能發送音樂並在另一側清晰地聽到。<br />連接藍牙耳機後，根據耳機的不同，音訊品質可能會因為啟用了藍牙 SCO 模式而下降。 | 

## 進階使用案例
<a name="broadcast-mobile-audio-modes-advanced-use-cases"></a>

除了預設值之外，iOS 和 Android 即時串流廣播 SDK 都允許設定基礎平台音訊模式：
+ 在 Android 上，設定 [AudioSource](https://developer.android.com/reference/android/media/MediaRecorder.AudioSource)、[Usage](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ALARM) 和 [ContentType](https://developer.android.com/reference/android/media/AudioAttributes#CONTENT_TYPE_MOVIE)。
+ 在 iOS 上，使用 [AVAudioSession.Category](https://developer.apple.com/documentation/avfaudio/avaudiosession/category)、[AVAudioSession.CategoryOptions](https://developer.apple.com/documentation/avfaudio/avaudiosession/categoryoptions)、[AVAudioSession.Mode](https://developer.apple.com/documentation/avfaudio/avaudiosession/mode)，以及在發布時切換是否啟用 [voice processing](https://developer.apple.com/documentation/avfaudio/avaudioionode/3152101-voiceprocessingenabled?language=objc) 的功能。

注意：使用這些音訊 SDK 方法時，可能會錯誤地設定基礎音訊工作階段。例如，在 iOS 上使用 `.allowBluetooth` 選項搭配 `.playback` 類別會建立無效的音訊組態，而且 SDK 無法錄製或播放音訊。僅在應用程式具有已驗證的特定音訊工作階段需求時使用這些方法。

------
#### [ Android (Kotlin) ]

```
// This would act similar to the Subscribe Only preset, but it uses a different ContentType.
StageAudioManager.getInstance(context)
    .setConfiguration(StageAudioManager.Source.GENERIC,
                      StageAudioManager.ContentType.MOVIE,
                      StageAudioManager.Usage.MEDIA);

val stage = Stage(context, token, this)

// Other Stage implementation code
```

------
#### [ iOS (Swift) ]

```
// This would act similar to the Subscribe Only preset, but it uses a different mode and options.
IVSStageAudioManager.sharedInstance()
    .setCategory(.playback,
                 options: [.duckOthers, .mixWithOthers],
                 mode: .default)

let stage = try? IVSStage(token: token, strategy: self)

// Other Stage implementation code
```

------

### iOS 回音消除
<a name="advanced-use-cases-ios_echo_cancellation"></a>

iOS 上的回音消除功能也可以使用 `echoCancellationEnabled` 方法透過 `IVSStageAudioManager` 獨立控制。此方法可以控制是否在 SDK 所使用的基礎 `AVAudioEngine` 的輸入和輸出節點上啟用[語音處理](https://developer.apple.com/documentation/avfaudio/avaudioionode/3152101-voiceprocessingenabled?language=objc)。請務必了解手動變更此屬性所帶來的影響：
+ 只有在 SDK 的麥克風處於作用中狀態時，才會執行 `AVAudioEngine` 屬性；這是必要的，因為 iOS 要求同時在輸入和輸出節點啟用語音處理。通常，這是透過使用 `IVSDeviceDiscovery` 傳回的麥克風來建立要發布的 `IVSLocalStageStream` 來完成。或者，可以將 `IVSAudioDeviceStatsCallback` 連接至麥克風本身來啟用麥克風，而不將其用於發布。如果在使用自訂音訊來源型麥克風 (而非 IVS SDK 麥克風) 時需要回音消除，則此替代方法非常有用。
+ 若要啟用 `AVAudioEngine` 屬性，需要使用 `.videoChat` 或 `.voiceChat` 模式。要求不同的模式會導致 iOS 的基礎音訊架構與 SDK 發生衝突，進而導致音訊遺失。
+ 啟用 `AVAudioEngine` 會自動啟用 `.allowBluetooth ` 選項。

行為可能會因裝置和 iOS 版本而異。

### iOS 自訂音訊來源
<a name="advanced-use-cases-ios_custom_audio_sources"></a>

自訂音訊來源可透過 `IVSDeviceDiscovery.createAudioSource` 與 SDK 搭配使用。連線至舞台後，IVS 即時串流廣播 SDK 仍會管理音訊播放的內部 `AVAudioEngine` 執行個體，即使未使用 SDK 的麥克風也是如此。因此，提供給 `IVSStageAudioManager` 的值必須與自訂音訊來源提供的音訊相容。

如果用於發布的自訂音訊來源是透過麥克風進行錄製，但是由主機應用程式進行管理，除非啟用 SDK 管理的麥克風，否則上述回音消除 SDK 將無法運作。若要繞過該要求，請參閱 [iOS 回音消除](#advanced-use-cases-ios_echo_cancellation)。

### 在 Android 系統上以藍牙發布
<a name="advanced-use-cases-bluetooth-android"></a>

在滿足下列條件時，SDK 會自動回復為 Android 上的 `VIDEO_CHAT` 預設值：
+ 指派的組態不會使用 `VOICE_COMMUNICATION` 使用率值。
+ 藍牙麥克風已連接至裝置。
+ 本機參與者正在發布至階段。

這是 Android 作業系統關於如何使用藍牙耳機錄製音訊的限制。

## 與其他 SDK 整合
<a name="broadcast-mobile-audio-modes-integrating-other-sdks"></a>

由於 iOS 和 Android 的每個應用程式均僅支持一種主動音訊模式，因此如果您的應用程式使用多種需要控制音訊模式的 SDK，則通常會遇到衝突。當您遇到這些衝突時，有一些常見的解決策略可嘗試，詳情如下所述。

### 對齊音訊模式值
<a name="integrating-other-sdks-match-values"></a>

使用 IVS SDK 的進階音訊組態選項或其他 SDK 功能，讓兩個 SDK 的基礎值對齊。

### Agora
<a name="integrating-other-sdks-agora"></a>

#### iOS
<a name="integrating-other-sdks-agora-ios"></a>

在 iOS 上，告訴 Agora SDK 保持 `AVAudioSession` 主動，將阻止它被 IVS 即時串流廣播 SDK 使用時遭到停用。

```
myRtcEngine.SetParameters("{\"che.audio.keep.audiosession\":true}");
```

#### Android
<a name="integrating-other-sdks-agora-android"></a>

避免在 `RtcEngine` 上呼叫 `setEnableSpeakerphone`，並於使用 IVS 即時串流廣播 SDK 發布時呼叫 `enableLocalAudio(false)`。當 IVS SDK 沒有在發布時，您可以再次呼叫 `enableLocalAudio(true)`。