View a markdown version of this page

IVS 即時串流最佳化 - Amazon IVS

IVS 即時串流最佳化

為確保您的使用者在使用 IVS 即時串流進行串流和觀看影片時獲得最佳體驗,您可以使用我們目前提供的各種功能,透過多種方式來改善或優化部分體驗。

簡介

針對使用者的體驗品質進行優化時,請務必考慮他們想要的體驗,這些體驗可能視乎使用者觀看的內容和網路狀況而改變。

在本指南中,我們專注於作為串流發布者或串流訂閱用戶的使用者,並且考慮了這些使用者所需的動作和體驗。

IVS SDK 可讓您設定串流的最大位元速率、影格速率和解析度。當發布者發生網路擁塞的情況時,SDK 會自動透過降低位元速率、影格速率和解析度的方式來調整和降低視訊品質。在 Android 和 iOS 上,遇到擁塞時,可以選取降級偏好設定。無論您是使用 simulcast 啟用分層編碼還是保留預設組態,依然會出現相同的行為。

適應性串流:Simulcast 分層編碼

只有下列用戶端版本才支援此功能:

  • iOS 和 Android 1.18.0+

  • Web 1.12.0+

使用 IVS 即時廣播 SDK 時,發布者可對多層影片進行編碼,訂閱用戶則會自動調整或變更為最適合其網路的品質。我們將此稱為 Simulcast 分層編碼。

Android 和 iOS 以及 Chrome 和 Edge 桌面瀏覽器 (適用於 Windows 和 macOS) 都支援 Simulcast 分層編碼。我們不支援在其他瀏覽器上進行分層編碼。

在下圖中,主持人將傳送三種影片品質 (高、中和低)。IVS 會根據可用的頻寬,將最高品質的影片轉傳給每位觀眾;這可為每位觀眾提供最佳體驗。如果觀眾 1 的網路連線從良好變更為不佳,IVS 會自動開始向觀眾 1 傳送較低品質的影片,因此觀眾 1 可持續不間斷地觀賞串流內容 (儘可能保持最佳品質)。

採用 Simulcast 分層編碼,以根據觀眾的網路連線品質來調整影片品質。

預設層級、品質和影格率

針對行動裝置和 Web 使用者提供的預設品質和層級如下:

行動裝置 (Android、iOS) Web (Chrome)

高層級 (或自訂):

  • 最大位元速率:900,000 bps

  • 影格率:15 fps

高層級 (或自訂):

  • 最大位元速率:1,700,000 bps

  • 影格率:30 fps

中層:無 (不需要,因為行動裝置上的高層和低層位元速率之間的差異較小)

中層:

  • 最大位元速率:700,000 bps

  • 影格率:20 fps

低層:

  • 最大位元速率:100,000 bps

  • 影格率:15 fps

低層:

  • 最大位元速率:200,000 bps

  • 影格率:15 fps

分層解析度

中層和低層的解析度會自動從高層縮減,以維持相同的長寬比。

如果中層和低層的解析度太接近高層,則會遭到排除。例如,如果設定的解析度為 320x180,則 SDK 也不會傳送較低的解析度層。

下表顯示不同解析度設定產生的分層解析度。列出的值適用於橫向螢幕,但可以反向套用至縱向螢幕。

輸入解析度 輸出層解析度:行動裝置 輸出層解析度:Web

720p (1280x720)

高 (1280x720)

低 (320x180)

高 (1280x720)

中 (640x360)

低 (320x180)

540p (960x540)

高 (960x540)

低 (320x180)

高 (960x540)

低 (320x180)

360p (640x360)

高 (640x360)

低 (360x180)

高 (640x360)

低 (360x180)

270p (480x270)

高 (480x270)

高 (480x270)

180p (320x180)

高 (320x180)

高 (320x180)

對於未對應於上方的自訂輸入解析度,您可以使用下列工具進行計算。

設定 Simulcast 分層編碼 (發布者)

若要使用 Simulcast 分層編碼,您必須在用戶端上啟用此功能。如果啟用此功能,您會看到發布者的上傳頻寬用量增加,觀眾的影片凍結時間可能會減少。

Android:

// Enable Simulcast StageVideoConfiguration config = new StageVideoConfiguration(); config.simulcast.setEnabled(true); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS:

// Enable Simulcast let config = IVSLocalStageStreamVideoConfiguration() config.simulcast.enabled = true let cameraStream = IVSLocalStageStream(device: camera, configuration: config) // Other Stage implementation code

Web

// Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true } }) // Other Stage implementation code

如需設定個別層的詳細資訊,請參閱每個廣播 SDK 指南中的「設定分層編碼 (發布者)」:Android、iOS 和 Web。

設定 Simulcast 分層編碼 (訂閱用戶)

若要設定訂閱用戶接收哪些層,請參閱相應即時串流 SDK 指南中的「Simulcast 分層編碼」小節:

可以透過訂閱用戶組態定義 InitialLayerPreference。這會決定最初提供的影片品質以及 preferredLayerForStream,而後者又決定在影片播放期間選取的層。在進行層變更、調整變更或層選擇時,有事件和串流方法可用來發出通知。

串流組態

本節將探討您可以對影片和音訊串流做出的其他組態設定。

變更影片串流位元速率

若要變更影片串流的位元速率,請使用下列組態範例。

Android:

StageVideoConfiguration config = new StageVideoConfiguration(); // Update Max Bitrate to 1.5mbps config.setMaxBitrate(1500000); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS:

let config = IVSLocalStageStreamVideoConfiguration(); // Update Max Bitrate to 1.5mbps try! config.setMaxBitrate(1500000); let cameraStream = IVSLocalStageStream(device: camera, configuration: config); // Other Stage implementation code

Web

let cameraStream = new LocalStageStream(camera.getVideoTracks()[0], { // Update Max Bitrate to 1.5mbps or 1500kbps maxBitrate: 1500 }) // Other Stage implementation code

變更影片串流影格率

若要變更影片串流的影格率,請使用下列組態範例。

Android:

StageVideoConfiguration config = new StageVideoConfiguration(); // Update target framerate to 10fps config.targetFramerate(10); ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config); // Other Stage implementation code

iOS:

let config = IVSLocalStageStreamVideoConfiguration(); // Update target framerate to 10fps try! config.targetFramerate(10); let cameraStream = IVSLocalStageStream(device: camera, configuration: config); // Other Stage implementation code

Web

// Note: On web it is also recommended to configure the framerate of your device from userMedia const camera = await navigator.mediaDevices.getUserMedia({ video: { frameRate: { ideal: 10, max: 10, }, }, }); let cameraStream = new LocalStageStream(camera.getVideoTracks()[0], { // Update Max Framerate to 10fps maxFramerate: 10 }) // Other Stage implementation code

優化音訊位元速率與立體聲支援

若要變更音訊串流的位元速率與立體聲設定,請使用下列組太範例。

Web

// Note: Disable autoGainControl, echoCancellation, and noiseSuppression when enabling stereo. const camera = await navigator.mediaDevices.getUserMedia({ audio: { autoGainControl: false, echoCancellation: false, noiseSuppression: false }, }); let audioStream = new LocalStageStream(camera.getAudioTracks()[0], { // Optional: Update Max Audio Bitrate to 96Kbps. Default is 64Kbps maxAudioBitrateKbps: 96, // Signal stereo support. Note requires dual channel input source. stereo: true }) // Other Stage implementation code

Android:

StageAudioConfiguration config = new StageAudioConfiguration(); // Update Max Bitrate to 96Kbps. Default is 64Kbps. config.setMaxBitrate(96000); AudioLocalStageStream microphoneStream = new AudioLocalStageStream(microphone, config); // Other Stage implementation code

iOS:

let config = IVSLocalStageStreamConfiguration(); // Update Max Bitrate to 96Kbps. Default is 64Kbps. try! config.audio.setMaxBitrate(96000); let microphoneStream = IVSLocalStageStream(device: microphone, config: config); // Other Stage implementation code

變更訂閱用戶抖動緩衝區最低延遲

若要變更訂閱參與者的抖動緩衝區最低延遲,可以使用自訂 subscribeConfiguration。抖動緩衝區會決定播放開始之前要儲存的封包數量。最低延遲代表應儲存最少的資料量。變更最低延遲有助於在面臨封包遺失/連線問題時能更彈性地進行播放。

但是,增加抖動緩衝區大小也會增加播放開始之前的延遲。增加最低延遲可提供更高的彈性,代價是會影響影片播放的時間。請注意,在播放期間增加最低延遲會有類似的影響:播放會短暫暫停,以便填滿抖動緩衝區。

如果需要更多彈性,建議您先從 MEDIUM 的最低延遲預設值開始,並在播放開始之前設定訂閱組態。

請注意,只有在參與者為僅訂閱時,才會套用最低延遲。如果參與者自行發布,則不會套用最低延遲。這樣做是為了確保多個發布者可以彼此交談,而不會產生額外的延遲。

下列範例使用 MEDIUM 的最低延遲預設值。請參閱 SDK 參考文件,了解所有可能的值。

Web

const strategy = { subscribeConfiguration: (participant) => { return { jitterBuffer: { minDelay: JitterBufferMinDelay.MEDIUM } } // ... other strategy functions }

Android:

@Override public SubscribeConfiguration subscribeConfigrationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) { SubscribeConfiguration config = new SubscribeConfiguration(); config.jitterBuffer.setMinDelay(JitterBufferConfiguration.JitterBufferDelay.MEDIUM()); return config; }

iOS:

func stage(_ stage: IVSStage, subscribeConfigurationForParticipant participant: IVSParticipantInfo) -> IVSSubscribeConfiguration { let config = IVSSubscribeConfiguration() try! config.jitterBuffer.setMinDelay(.medium()) return config }

在階段之間切換時縮短影片播放時間

應用程式可能會讓使用者瀏覽即時串流的摘要。使用者加入一個階段,撥動至另一個串流,離開目前階段,然後快速加入下一個階段。為每個階段轉換建立新連線需要建立新的網路連線,這可能會增加視訊可用前的等待時間。

使用 RealTimeConnection 在使用者瀏覽串流時保持一個網路連線開啟。建立連線一次,選擇性地在加入第一個階段之前進行連線,並跨階段重複使用。每個階段仍會使用自己的參與者字符,並維護自己的參與者、串流和生命週期。

在瀏覽工作階段期間,在超過個別階段生命週期的物件中建立並保留 RealTimeConnection,例如應用程式協調器、導覽控制器或檢視模型。請勿為每個階段轉換建立並中斷連線。

Android:

下列範例會將 RealTimeConnection 生命週期新增至 Android 範例中使用的 MainViewModel。檢視模型實作 Stage.Strategy 和 StageRenderer。

private var realTimeConnection: RealTimeConnection? = null private var stage: Stage? = null private fun setupConnection(connectionToken: String) { try { val connection = RealTimeConnection(getApplication(), connectionToken) // Establish the shared transport before the first Stage join. connection.connect() realTimeConnection = connection } catch (error: BroadcastException) { Log.e("BasicRealTime", "Unable to create the RealTimeConnection", error) } } private fun joinStage(participantToken: String) { val realTimeConnection = realTimeConnection ?: return try { stage?.leave() stage?.release() val stage = Stage( getApplication(), participantToken, realTimeConnection, this ) stage.addRenderer(this) stage.join() this.stage = stage } catch (error: BroadcastException) { Log.e("BasicRealTime", "Unable to join the Stage", error) } } override fun onCleared() { stage?.leave() stage?.release() stage = null realTimeConnection?.disconnect() realTimeConnection?.release() realTimeConnection = null super.onCleared() }

呼叫 connect() 是選用的。如果您加入階段時未開啟連線,SDK 會自動開啟連線。在加入下一個階段之前呼叫 connect(),以預先建立連線並縮短影片播放時間。雖然範例一次只能連接到一個階段,但 RealTimeConnection 可以同時連接到多個階段。

當應用程式不再需要 RealTimeConnection 時,呼叫 release()。釋放後即無法重複使用。

iOS:

下列範例假設應用程式會在使用者開始多階段流程時取得連線字符,並為使用者加入的每個階段取得參與者字符。

private var realTimeConnection: IVSRealTimeConnection? private var stage: IVSStage? private func setupConnection(connectionToken: String) throws { let connection = try IVSRealTimeConnection(token: connectionToken) // Establish the shared transport before the first Stage join. try connection.connect() realTimeConnection = connection } private func joinStage(participantToken: String) throws { guard let realTimeConnection else { return } stage?.leave() let stage = try IVSStage( token: participantToken, on: realTimeConnection, strategy: self ) stage.addRenderer(self) try stage.join() self.stage = stage } private func endStageTransitionFlow() { stage?.leave() stage = nil realTimeConnection?.disconnect() realTimeConnection = nil }

呼叫 connect() 是選用的。如果您加入階段時未開啟連線,SDK 會自動開啟連線。在加入下一個階段之前呼叫 connect(),以預先建立連線並縮短影片播放時間。雖然範例一次只能連線到一個階段,但 IVSRealTimeConnection 可以同時連線到多個階段。

當階段使用 IVSRealTimeConnection 時,請保持對此項目的強式參考。呼叫 disconnect() 會離開任何使用該連線的階段。

建議的最佳化

案例 建議
文字串流或移動速度緩慢的內容,例如簡報或幻燈片 採用 Simulcast 分層編碼,或以較低的影格率設定串流。
具有動作或大量移動的串流 採用 Simulcast 分層編碼。
具有對話或很少動作的串流 採用 Simulcast 分層編碼,或選擇純音訊 (請參閱 Web 版、Android 版和 iOS 版即時串流廣播 SDK 指南中的「訂閱參與者」)。
使用者以有限的資料串流 採用 Simulcast 分層編碼,或者如果您想要降低所有人的資料使用量,請設定較低的影格速率並手動降低位元速率。
使用者瀏覽即時串流的摘要,並快速從一個階段移至下一個階段 重複使用 RealTimeConnection 進行瀏覽工作階段。在第一個階段加入之前呼叫 connect(),以預先建立連線。