IVS Web Broadcast SDK での発行とサブスクライブ | Real-Time Streaming - Amazon IVS

IVS Web Broadcast SDK での発行とサブスクライブ | Real-Time Streaming

このドキュメントでは、IVS Real-Time Streaming Web Broadcast SDK を使用してステージに発行とサブスクライブを行うためのステップについて説明します。

概念

リアルタイム機能の根底には、ステージストラテジーイベントという 3 つのコアコンセプトがあります。設計目標は、実際に動作する製品を構築するのに必要となるクライアント側ロジックの量を最小限に抑えることです。

ステージ

Stage クラスは、ホストアプリケーションと SDK 間の主要な相互作用のポイントです。これはステージそのものを表し、ステージへの参加とステージからの退出に使用されます。ステージの作成と参加には、コントロールプレーンからの有効で有効期限内のトークン文字列 (token として表示) が必要です。ステージへの参加と退出は簡単です。

const stage = new Stage(token, strategy) try { await stage.join(); } catch (error) { // handle join exception } stage.leave();

方針

StageStrategy インターフェースは、ホストアプリケーションがステージの望ましい状態を SDK に伝える方法を提供します。shouldSubscribeToParticipantshouldPublishParticipantstageStreamsToPublish の 3 つの関数を実装する必要があります。以下で、すべて説明します。

定義済みのストラテジーを使用するには、それを Stage コンストラクターに渡します。以下は、参加者の Web カメラをステージに公開し、すべての参加者にサブスクライブするというストラテジーを使用したアプリケーションの完全な例です。必要な各ストラテジー機能の目的は、以下のセクションで説明します。

const devices = await navigator.mediaDevices.getUserMedia({ audio: true, video: { width: { max: 1280 }, height: { max: 720 }, } }); const myAudioTrack = new LocalStageStream(devices.getAudioTracks()[0]); const myVideoTrack = new LocalStageStream(devices.getVideoTracks()[0]); // Define the stage strategy, implementing required functions const strategy = { audioTrack: myAudioTrack, videoTrack: myVideoTrack, // optional updateTracks(newAudioTrack, newVideoTrack) { this.audioTrack = newAudioTrack; this.videoTrack = newVideoTrack; }, // required stageStreamsToPublish() { return [this.audioTrack, this.videoTrack]; }, // required shouldPublishParticipant(participant) { return true; }, // required shouldSubscribeToParticipant(participant) { return SubscribeType.AUDIO_VIDEO; } }; // Initialize the stage and start publishing const stage = new Stage(token, strategy); await stage.join(); // To update later (e.g. in an onClick event handler) strategy.updateTracks(myNewAudioTrack, myNewVideoTrack); stage.refreshStrategy();

参加者へのサブスクライブ

shouldSubscribeToParticipant(participant: StageParticipantInfo): SubscribeType

リモート参加者がステージに参加すると、SDK はその参加者に対して希望するサブスクリプションの状態についてホストアプリケーションに問い合わせます。使用できるオプションは NONEAUDIO_ONLY、および AUDIO_VIDEO です。この関数の値を返す場合、ホストアプリケーションは公開の状態、現在のサブスクリプションの状態、またはステージ接続の状態を考慮する必要はありません。AUDIO_VIDEO が返された場合、SDK はリモート参加者が公開するまで待ってからサブスクライブし、プロセス全体でイベントを作成してホストアプリケーションを更新します。

次に示すのは実装の例です。

const strategy = { shouldSubscribeToParticipant: (participant) => { return SubscribeType.AUDIO_VIDEO; } // ... other strategy functions }

これは、ビデオチャットアプリケーションなど、すべての参加者が互いに常に可視化されているホストアプリケーション向けのの完全な実装です。

より高度な実装も可能です。例えば、CreateParticipantToken でトークンを作成するときに、アプリケーションが role 属性を提供しているとします。アプリケーションは、StageParticipantInfoattributes プロパティを使用して、サーバーが提供する属性に基づいて、参加者に対して選択的にサブスクライブできます。

const strategy = { shouldSubscribeToParticipant(participant) { switch (participant.attributes.role) { case 'moderator': return SubscribeType.NONE; case 'guest': return SubscribeType.AUDIO_VIDEO; default: return SubscribeType.NONE; } } // . . . other strategies properties }

これを使用すると、モデレーターは、自身は視聴の対象とならずに、すべてのゲストを監視できるステージを作ることができます。ホストアプリケーションでは、追加のビジネスロジックを使用して、モデレータがお互いを見えるようにしても、ゲストには見えないようにすることができます。

参加者へのサブスクライブの設定

subscribeConfiguration(participant: StageParticipantInfo): SubscribeConfiguration

リモート参加者がサブスクライブしている場合 (「参加者へのサブスクライブ」を参照)、SDK はホストアプリケーションにその参加者のカスタムサブスクライブ設定についてクエリします。この設定はオプションであり、ホストアプリケーションがサブスクライバーの動作の特定の側面を制御できるようにします。設定できる内容の詳細については、SDK リファレンスドキュメントの「SubscribeConfiguration」を参照してください。

次に示すのは実装の例です。

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

この実装では、サブスクライブしたすべての参加者のジッターバッファ最小遅延を MEDIUM のプリセットに更新します。

shouldSubscribeToParticipant を使用した、より高度な実装も可能です。指定された ParticipantInfo を使用して、特定の参加者のサブスクライブ設定を選択的に更新できます。

デフォルトの動作を使用することをお勧めします。カスタム設定は、特定の動作を変更したい場合にのみ指定します。

公開

shouldPublishParticipant(participant: StageParticipantInfo): boolean

ステージに接続すると、SDK はホストアプリケーションにクエリを実行し、特定の参加者を公開とすべきかどうかを確認します。これは、提供されたトークンに基づいて公開する権限を持つローカル参加者においてのみ呼び出されます。

次に示すのは実装の例です。

const strategy = { shouldPublishParticipant: (participant) => { return true; } // . . . other strategies properties }

これは、ユーザーは常に公開状態としたい標準的なビデオチャットアプリケーション用です。オーディオとビデオをミュートまたはミュート解除して、すぐに不可視または可視にできます。(公開/非公開も使用できますが、この方法では大幅に遅くなります。可視性を頻繁に変更したいユースケースには、ミュート/ミュート解除が適しています。)

公開するストリームの選択

stageStreamsToPublish(): LocalStageStream[];

公開時には、これを使用して公開するオーディオストリームとビデオストリームが決定されます。これについては、後ほど「メディアストリームの公開」で詳しく説明します。

ストラテジーの更新

このストラテジーは動的であることを意図しており、上記の関数のいずれかから返される値はいつでも変更できます。たとえば、ホストアプリケーションがエンドユーザーがボタンをタップするまで公開したくない場合、shouldPublishParticipant (hasUserTappedPublishButton など) から変数を返すことができます。その変数がエンドユーザーの相互作用に基づいて変更されたら、stage.refreshStrategy() を呼び出して、変更されたもののみを適用して、最新の値のストラテジーを照会する必要があることを SDK に通知します。SDK は、shouldPublishParticipant 値が変更されたことを確認すると、公開プロセスを開始します。SDK クエリとすべての関数が以前と同じ値を返す場合、refreshStrategy 呼び出しによってステージが変更されることはありません。

shouldSubscribeToParticipant の戻り値が AUDIO_VIDEO から AUDIO_ONLY に変更され、以前にビデオストリームが存在していた場合は、戻り値が変更されたすべての参加者のビデオストリームが削除されます。

通常、ホストアプリケーションは、適切に管理するために必要なすべての状態について考慮する必要はありません。ステージは以前のストラテジーと現在のストラテジーの違いを最も効率的に適用するストラテジーを使用します。このため、stage.refreshStrategy() の呼び出しはストラテジーが変わらない限り何もしないため、低コストなオペレーションとみなすことができます。

イベント

Stage インスタンスはイベントエミッターです。stage.on() を使用して、ステージの状態がホストアプリケーションに伝達されます。ホストアプリケーションの UI の更新は、通常、イベントによって完全にサポートされます。イベントは次のとおりです。

stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_LEFT, (participant) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_PUBLISH_STATE_CHANGED, (participant, state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_SUBSCRIBE_STATE_CHANGED, (participant, state) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => {}) stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_REMOVED, (participant, streams) => {}) stage.on(StageEvents.STAGE_STREAM_ADAPTION_CHANGED, (participant, stream, isAdapting) => ()) stage.on(StageEvents.STAGE_STREAM_LAYERS_CHANGED, (participant, stream, layers) => ()) stage.on(StageEvents.STAGE_STREAM_LAYER_SELECTED, (participant, stream, layer, reason) => ()) stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => {}) stage.on(StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED, (participant, stream) => {})

これらのイベントのほとんどには、対応する ParticipantInfo が用意されています。

イベントによって提供される情報がストラテジーの戻り値に影響することは想定されていません。たとえば、shouldSubscribeToParticipant の戻り値は、STAGE_PARTICIPANT_PUBLISH_STATE_CHANGED が呼び出されても変化しない想定です。ホストアプリケーションが特定の参加者をサブスクライブする場合は、その参加者の公開状態に関係なく、目的のサブスクリプションタイプを返す必要があります。SDK は、ステージの状態に基づいて、望ましいストラテジーの状態が適切なタイミングで実行されるようにする役目を担います。

メディアストリームを公開する

マイクやカメラなどのローカルデバイスは、上記の「デバイスからの MediaStream の取得」で説明したのと同じ手順で取得されます。この例では、MediaStream を使用して SDK による公開に使用される LocalStageStream オブジェクトのリストを作成しています。

try { // Get stream using steps outlined in document above const stream = await getMediaStreamFromDevice(); let streamsToPublish = stream.getTracks().map(track => { new LocalStageStream(track) }); // Create stage with strategy, or update existing strategy const strategy = { stageStreamsToPublish: () => streamsToPublish } }

スクリーン共有を公開する

アプリケーションでは、多くの場合、ユーザーの Web カメラに加えてスクリーン共有を公開する必要があります。スクリーン共有を公開するには、特にスクリーン共有のメディアを公開するためには、ステージ用の追加のトークンを作成する必要があります。getDisplayMedia を使用し、解像度を最大 720p に制限します。その後、ステップはカメラをステージに公開するのと似ています。

// Invoke the following lines to get the screenshare's tracks const media = await navigator.mediaDevices.getDisplayMedia({ video: { width: { max: 1280, }, height: { max: 720, } } }); const screenshare = { videoStream: new LocalStageStream(media.getVideoTracks()[0]) }; const screenshareStrategy = { stageStreamsToPublish: () => { return [screenshare.videoStream]; }, shouldPublishParticipant: (participant) => { return true; }, shouldSubscribeToParticipant: (participant) => { return SubscribeType.AUDIO_VIDEO; } } const screenshareStage = new Stage(screenshareToken, screenshareStrategy); await screenshareStage.join();

参加者を表示、削除する

サブスクライブが完了すると、STAGE_PARTICIPANT_STREAMS_ADDED イベントを通じて StageStream オブジェクトの配列を受け取ります。このイベントでは、メディアストリームを表示する際に役立つ参加者情報も提供します。

stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { let streamsToDisplay = streams; if (participant.isLocal) { // Ensure to exclude local audio streams, otherwise echo will occur streamsToDisplay = streams.filter(stream => stream.streamType === StreamType.VIDEO) } // Create or find video element already available in your application const videoEl = getParticipantVideoElement(participant.id); // Attach the participants streams videoEl.srcObject = new MediaStream(); streamsToDisplay.forEach(stream => videoEl.srcObject.addTrack(stream.mediaStreamTrack)); })

参加者がストリームの公開を停止したり、配信登録を解除したりすると、削除されたストリームを使用して STAGE_PARTICIPANT_STREAMS_REMOVED 関数が呼び出されます。ホストアプリケーションは、これをシグナルとして使用して、参加者のビデオストリームを DOM から削除する必要があります。

STAGE_PARTICIPANT_STREAMS_REMOVED は、以下を含む、ストリームが削除される可能性のあるすべてのシナリオで呼び出されます。

  • リモート参加者は公開を停止します。

  • ローカルデバイスがサブスクリプションを解除するか、サブスクリプションを AUDIO_VIDEO から AUDIO_ONLY に変更します。

  • リモート参加者がステージを退出します。

  • ローカルの参加者がステージを退出します。

STAGE_PARTICIPANT_STREAMS_REMOVED はすべてのシナリオで呼び出されるため、リモートまたはローカルの離脱操作中、 UI から参加者を削除するためのカスタムのビジネスロジックは必要ありません。

メディアストリームをミュート、ミュート解除する

LocalStageStream オブジェクトには、ストリームをミュートするかどうかを制御する setMuted 関数があります。この関数は、stageStreamsToPublish ストラテジー関数から返される前または後にストリームで呼び出すことができます。

重要: refreshStrategy を呼び出した後に新しい LocalStageStream オブジェクトインスタンスが stageStreamsToPublish によって返された場合、新しいストリームオブジェクトのミュート状態がステージに適用されます。新しい LocalStageStream インスタンスを作成するときは、想定どおりのミュート状態を維持するように注意してください。

リモート参加者のメディアミュート状態の監視

参加者がビデオまたはオーディオのミュート状態を変更すると、変更されたストリームのリストで STAGE_STREAM_MUTE_CHANGED イベントがトリガーされます。StageStreamisMuted プロパティを使用して、次の UI を適宜更新してください。

stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => { if (stream.streamType === 'video' && stream.isMuted) { // handle UI changes for video track getting muted } })

また、StageParticipantInfo でオーディオまたはビデオがミュートされているかどうか関する状態情報を参照することもできます。

stage.on(StageEvents.STAGE_STREAM_MUTE_CHANGED, (participant, stream) => { if (participant.videoStopped || participant.audioMuted) { // handle UI changes for either video or audio } })

WebRTC 統計を取得する

公開中のストリームまたはサブスクライブ中のストリームの最新の WebRTC 統計を取得するには、StageStreamgetStats を使用してください。これは、await または promise の連鎖によって統計を取得できる非同期メソッドです。その結果、すべての標準統計を含むディクショナリである RTCStatsReport ができあがります。

try { const stats = await stream.getStats(); } catch (error) { // Unable to retrieve stats }

メディアの最適化

最高のパフォーマンスを得るには、getUserMedia および getDisplayMedia を制限して呼び出すことをお勧めします。

const CONSTRAINTS = { video: { width: { ideal: 1280 }, // Note: flip width and height values if portrait is desired height: { ideal: 720 }, framerate: { ideal: 30 }, }, };

次の LocalStageStream コンストラクターに渡される追加オプションを使用して、メディアをさらに制限できます。

const localStreamOptions = { minBitrate?: number; maxBitrate?: number; maxFramerate?: number; simulcast: { enabled: boolean } } const localStream = new LocalStageStream(track, localStreamOptions)

上記のコードについて

  • minBitrate はブラウザが使用することが予想される最小ビットレートを設定します。ただし、ビデオストリームの複雑度が低いと、エンコーダがこのビットレートよりも低くなる可能性があります。

  • maxBitrate はこのストリームでブラウザが超えないと予想される最大ビットレートを設定します。

  • maxFramerate はこのストリームでブラウザが超えないと予想される最大フレームレートを設定します。

  • simulcast オプションは Chromium ベースのブラウザでのみ使用できます。これにより、ストリームの 3 つのレンディションレイヤーを送信できます。

    • これにより、サーバーは、ネットワークの制限に基づいて、他の参加者に送信するレンディションを選択できます。

    • simulcast が maxBitrate および/または maxFramerate の値とともに指定された場合、maxBitrate が内部 SDK の 2 番目に高レイヤーのデフォルト maxBitrate 値である 900 kbps を下回らない限り、これらの値を念頭に置いて最上位のレンディションレイヤーが設定されることが想定されています。

    • maxBitrate が 2 番目に高いレイヤーのデフォルト値と比較して低すぎるように指定された場合は、simulcast は無効になります。

    • simulcast のオンとオフを切り替えるには、shouldPublishParticipant が false を返し、refreshStrategy を呼び出し、shouldPublishParticipant が true を返し、refreshStrategy をもう一度呼ぶ組み合わせにより、メディアを再パブリッシュする必要があります。

参加者属性を取得

CreateParticipantToken オペレーションリクエストで属性を指定した場合、StageParticipantInfo プロパティに属性が表示されます。

stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => { console.log(`Participant ${participant.id} info:`, participant.attributes); })

補足拡張情報 (SEI)

補足拡張情報 (SEI) NAL ユニットは、フレーム整列メタデータを動画と一緒に保存するために使用されます。H.264 ビデオストリームに公開およびサブスクライブするときに使用できます。SEI 挿入機能は IVS Web Broadcast SDK (モバイル SDK ではない) でのみ使用可能です。SEI ペイロードがサブスクライバーに届くという保証はありません (特にネットワーク状況が悪い場合)。SEI ペイロードは H.264 フレーム構造内にデータを直接保存するため、この機能はオーディオのみのストリームでは利用できません。

SEI ペイロードの挿入

公開元クライアントは、inBandMessaging を有効化するようにビデオの LocalStageStream を設定し、その後に insertSeiMessage メソッド呼び出すことで、公開されているステージストリームに SEI ペイロードを挿入できます。inBandMessaging を有効にすると、SDK のメモリ使用量が増加することに注意してください。

ペイロードは ArrayBuffer タイプである必要があります。ペイロードサイズは 0 KB より大きく 1 KB 未満のサイズにする必要があります。挿入される SEI メッセージの 1 秒あたりの数が 10 KB/秒を超えない必要があります。

const config = { inBandMessaging: { enabled: true } }; const vidStream = new LocalStageStream(videoTrack, config); const payload = new TextEncoder().encode('hello world').buffer; vidStream.insertSeiMessage(payload);

SEI ペイロードの反復

オプションで repeatCount を指定して、送信される次の N 個のフレームで SEI ペイロードの挿入を反復します。これは、ビデオの送信に使用される下層 UDP トランスポートプロトコルが原因で発生する可能性のある特有の損失を軽減するために役立つ場合があります。この値は 0~30 の値にする必要があることに注意してください。受信クライアントには、メッセージを重複除外するロジックが必要です。

vidStream.insertSeiMessage(payload, { repeatCount: 5 }); // Optional config, repeatCount must be between 0 and 30

SEI ペイロードの読み取り

サブスクライブするクライアントは、次の例に示すように、サブスクライバー (複数可) SubscribeConfiguration を設定して inBandMessaging を有効にし、StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED イベントをリッスンすることで、H.264 動画を公開しているパブリッシャー (存在する場合) から SEI ペイロードを読み取ることができます。

const strategy = { subscribeConfiguration: (participant) => { return { inBandMessaging: { enabled: true } } } // ... other strategy functions } stage.on(StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED, (participant, seiMessage) => { console.log(seiMessage.payload, seiMessage.uuid); });

サイマルキャストによるレイヤードエンコーディング

サイマルキャストによるレイヤードエンコーディングは、パブリッシャーが複数の異なるビデオの品質レイヤーを送信し、サブスクライバーがそれらのレイヤーを動的または手動で変更できるようにする IVS リアルタイムのストリーミング機能です。この機能は、「ストリーミング最適化」ドキュメントで詳しく説明されています。

レイヤードエンコーディングの設定 (パブリッシャー)

パブリッシャーとしてサイマルキャストによるレイヤードエンコーディングを有効にするには、インスタンス化時に LocalStageStream に次の設定を追加します。

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

カメラデバイスの入力解像度に応じて、「ストリーミングの最適化」の「デフォルトレイヤー、品質、フレームレート」セクションで定義されているように、設定された数のレイヤーがエンコードされて送信されます。

また、必要に応じて、サイマルキャスト設定内から個々のレイヤーを設定できます。

import { SimulcastLayerPresets } from ‘amazon-ivs-web-broadcast’ // Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true, layers: [ SimulcastLayerPresets.DEFAULT_720, SimulcastLayerPresets.DEFAULT_360, SimulcastLayerPresets.DEFAULT_180, } })

または、最大で 3 つのレイヤー用に独自のカスタムレイヤー設定を作成することもできます。空のアレイを指定するか、値を指定しない場合、上記のデフォルトが使用されます。レイヤーは、次の必須プロパティで説明されています。

  • height: number;

  • width: number;

  • maxBitrateKbps: number;

  • maxFramerate: number;

プリセットから、個々のプロパティを上書きするか、まったく新しい設定を作成できます。

import { SimulcastLayerPresets } from ‘amazon-ivs-web-broadcast’ const custom720pLayer = { ...SimulcastLayerPresets.DEFAULT_720, maxFramerate: 15, } const custom360pLayer = { maxBitrateKbps: 600, maxFramerate: 15, width: 640, height: 360, } // Enable Simulcast let cameraStream = new LocalStageStream(cameraDevice, { simulcast: { enabled: true, layers: [ custom720pLayer, custom360pLayer, } })

個々のレイヤーを設定するときにトリガーできる最大値、制限、エラーについては、SDK リファレンスドキュメントを参照してください。

レイヤードエンコーディングの設定 (サブスクライバー)

サブスクライバーとして、レイヤードエンコーディングを有効にするために必要なものはありません。パブリッシャーがサイマルキャストレイヤーを送信している場合、デフォルトでサーバーによってレイヤー間で動的に適応され、サブスクライバーのデバイスおよびネットワークの状態に基づいて最適な品質が選択されます。

あるいは、パブリッシャーが送信している明示的なレイヤーを選択するには、以下に説明するいくつかのオプションがあります。

オプション 1: 初期レイヤー品質の選択

subscribeConfiguration 戦略を使用すると、サブスクライバーとして受信する初期レイヤーを選択できます。

const strategy = { subscribeConfiguration: (participant) => { return { simulcast: { initialLayerPreference: InitialLayerPreference.LOWEST_QUALITY } } } // ... other strategy functions }

デフォルトでは、サブスクライバーは常に最初に最低品質のレイヤーが送信されます。これにより、徐々に最高品質のレイヤーにまで拡大します。エンドユーザーの帯域幅の消費量が最適化され、ビデオ再生に最適な時間が実現されるため、より貧弱なネットワーク上のユーザーに対して初期ビデオフリーズが軽減されます。

これらのオプションは InitialLayerPreference で利用できます。

  • LOWEST_QUALITY — サーバーは、最初に最低品質のビデオレイヤーを配信します。帯域幅の消費とメディアの時間が最適化されます。品質はビデオのサイズ、ビットレート、フレームレートの組み合わせとして定義されます。例えば、720p ビデオは 1080p ビデオよりも品質が低くなります。

  • HIGHEST_QUALITY — サーバーは、最初に最高品質のビデオレイヤーを配信します。品質が最適化されますが、メディアの時間が長くなる場合があります。品質はビデオのサイズ、ビットレート、フレームレートの組み合わせとして定義されます。例えば、1080p ビデオは 720p ビデオよりも高品質です。

注: 初期レイヤー設定 (initialLayerPreference の呼び出し) を反映させるには、再サブスクライブが必要です。これらの更新はアクティブなサブスクリプションに適用されないためです。

オプション 2: ストリームに優先されるレイヤー

ストリームが開始されたら、preferredLayerForStream 戦略メソッドを使用できます。この戦略メソッドは、参加者およびストリーム情報を公開します。

戦略メソッドは、次の内容として返すことができます。

  • RemoteStageStream.getLayers が返す内容に直接的に基づくレイヤーオブジェクト

  • StageStreamLayer.label に基づく、レイヤーオブジェクトのラベル文字列

  • レイヤーを選択せず、動的適応が優先されることを示す未定義または null

例えば、次の戦略ではユーザーが常に最低品質のビデオレイヤーを選択するようにします。

const strategy = { preferredLayerForStream: (participant, stream) => { return stream.getLowestQualityLayer(); } // ... other strategy functions }

レイヤーの選択をリセットして動的適応に戻るには、戦略で null または未定義を返します。この例では、appState は可能なアプリケーションの状態を表すダミー変数です。

const strategy = { preferredLayerForStream: (participant, stream) => { if (appState.isAutoMode) { return null; } else { return appState.layerChoice } } // ... other strategy functions }

オプション 3: RemoteStageStream レイヤーヘルパー

RemoteStageStream には、レイヤーの選択について決定し、対応する選択をエンドユーザーに表示するために使用できるいくつかのヘルパーがあります。

  • レイヤーイベント - StageEvents に加え、RemoteStageStream オブジェクト自体にはレイヤーおよびサイマルキャストの適応変更を伝えるイベントがあります。

    • stream.on(RemoteStageStreamEvents.ADAPTION_CHANGED, (isAdapting) => {})

    • stream.on(RemoteStageStreamEvents.LAYERS_CHANGED, (layers) => {})

    • stream.on(RemoteStageStreamEvents.LAYER_SELECTED, (layer, reason) => {})

  • レイヤーメソッドRemoteStageStream には、ストリームおよび提示されるレイヤーに関する情報を取得するために使用できるいくつかのヘルパーメソッドがあります。これらのメソッドは、preferredLayerForStream 戦略で提供されるリモートストリームに加え、StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED を介して公開されるリモートストリームで利用できます。

    • stream.getLayers

    • stream.getSelectedLayer

    • stream.getLowestQualityLayer

    • stream.getHighestQualityLayer

詳細については、「SDK リファレンスドキュメント」の「RemoteStageStream」クラスを参照してください。LAYER_SELECTED の理由として UNAVAILABLE が返された場合、これはリクエストされたレイヤーが選択できなかったことを示します。代わりにベストエフォートの選択が行われ、ストリームの安定性を維持するために、通常は低品質のレイヤーが選択されます。

ネットワーク問題の処理

ローカルデバイスのネットワーク接続が失われると、SDK はユーザーアクションなしで内部で再接続を試みます。場合によっては、SDK が正常に動作せず、ユーザーアクションが必要なる可能性があります。

大まかに、ステージの状態は STAGE_CONNECTION_STATE_CHANGED イベントを介して処理できます。

stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => { switch (state) { case StageConnectionState.DISCONNECTED: // handle disconnected UI return; case StageConnectionState.CONNECTING: // handle establishing connection UI return; case StageConnectionState.CONNECTED: // SDK is connected to the Stage return; case StageConnectionState.ERRORED: // SDK encountered an error and lost its connection to the stage. Wait for CONNECTED. return; } })

通常、SDK は内部的に復旧しようとするため、ステージに正常に参加した後に発生するエラー状態を無視できます。SDK が ERRORED 状態を報告し、ステージが長時間 (30 秒以上) CONNECTING 状態のままである場合、おそらくネットワークから切断されています。

IVS チャネルにステージをブロードキャストする

ステージをブロードキャストするには、IVSBroadcastClient セッションを作成してから、前述の SDK による通常のブロードキャスト手順に従います。次のように、STAGE_PARTICIPANT_STREAMS_ADDED を介して公開された StageStream のリストを使用して、ブロードキャスト ストリーム構成に適用できる参加者メディア ストリームを取得できます。

// Setup client with preferred settings const broadcastClient = getIvsBroadcastClient(); stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { streams.forEach(stream => { const inputStream = new MediaStream([stream.mediaStreamTrack]); switch (stream.streamType) { case StreamType.VIDEO: broadcastClient.addVideoInputDevice(inputStream, `video-${participant.id}`, { index: DESIRED_LAYER, width: MAX_WIDTH, height: MAX_HEIGHT }); break; case StreamType.AUDIO: broadcastClient.addAudioInputDevice(inputStream, `audio-${participant.id}`); break; } }) })

オプションで、ステージを合成して IVS 低レイテンシーチャネルにブロードキャストすることで、より多くの視聴者に届けることもできます。「IVS 低レイテンシーストリーミングユーザーガイド」の「Amazon IVS ストリームでの複数のホストの有効化」を参照してください。