IVS Broadcast SDK: 混合デバイス - Amazon IVS

IVS Broadcast SDK: 混合デバイス

混合デバイスは、複数の入力ソースを取得して単一の出力を生成するオーディオおよびビデオデバイスです。混合デバイスは、複数の画面上 (ビデオ) の要素およびオーディオトラックを定義および管理できる強力な機能です。カメラ、マイク、スクリーンキャプチャ、アプリで生成されたオーディオとビデオなど、複数のソースからのビデオとオーディオを組み合わせることができます。移行機能を使用して IVS にストリーミングするビデオ周辺にこれらのソースを移動させて、ストリーミングの途中でソースに追加およびソースを削除することができます。

混合デバイスは画像およびオーディオの形式で存在します。混合イメージデバイスを作成するには、次のものを呼び出します。

Android のDeviceDiscovery.createMixedImageDevice()

iOS の IVSDeviceDiscovery.createMixedImageDevice()

返されたデバイスは、他のデバイスと同様に BroadcastSession (低レイテンシーストリーミング) または Stage (リアルタイムストリーミング) にアタッチできます。

用語

IVS Broadcast 混合デバイスの用語。
言葉 説明

デバイス

オーディオまたは画像入力を生成するハードウェアまたはソフトウェアコンポーネント。デバイスの例としては、マイク、カメラ、Bluetooth ヘッドセット、画面キャプチャやカスタム画像入力などの仮想デバイスがあります。

混合デバイス

他の Device と同様に、DeviceBroadcastSession にアタッチできるますが、Source オブジェクトの追加を可能にする追加の API を使用します。混合デバイスにはオーディオまたは画像を複合する内部ミキサーがあり、単一の出力オーディオおよびイメージストリームを生成します。

混合デバイスはオーディオまたは画像のいずれかの形式で存在します。

混合デバイスの設定

混合デバイスの設定オブジェクト。混合イメージデバイスの場合、寸法やフレームレートなどのプロパティが設定されます。混合オーディオデバイスの場合、チャンネル数が設定されます。

ソース

画面上のビジュアルエレメントの位置と、オーディオミックス内のオーディオトラックのプロパティを定義するコンテナです。混合デバイスは、ゼロ以上のソースで設定できます。ソースには、ソースのメディアの使用方法に影響する設定が与えられます。上のイメージには、4 つのイメージソースが示されています。

  • 左下、カメラ入力あり

  • 右上にムービー入力あり

  • 右下に Amazon IVS のロゴが入っています

  • フルスクリーンのバックグラウンドイメージ

ソース設定

混合デバイスに入るソースの設定オブジェクト。完全な設定オブジェクトは以下のように表記されています。

トランジション

スロットを新しい位置に移動したり、そのプロパティの一部を変更するには、MixedDevice.transitionToConfiguration() を使用します。このメソッドには次のものがあります。

  • ソースの次の状態を表す新規のソース設定。

  • ビデオのタイムラインを基準にして、アニメーションにかかる時間を指定するデュレーション。デュレーションを 0 に設定すると、ミックスされる次のフレームでトランジションが行われます。

  • アニメーションが完了したことを通知するオプションのコールバック。コールバックは、アニメーションを連鎖させるのに便利です。

混合オーディオデバイス

設定

Android のMixedAudioDeviceConfiguration

iOS の IVSMixedAudioDeviceConfiguration

名前 説明

channels

整数

オーディオミキサーからの出力チャネルの数。有効な値:1、2。1 はモノラルオーディオで、2 はステレオオーディオです。デフォルト: 2。

ソース設定

Android のMixedAudioDeviceSourceConfiguration

iOS の IVSMixedAudioDeviceSourceConfiguration

名前 説明

gain

浮動小数点数

オーディオゲイン。これは乗数であるため、1 を超える値であればゲインが増加し、1 より小さい値であれば減少します。有効な値: 0 ~ 2。デフォルト: 1。

混合イメージデバイス

設定

Android のMixedImageDeviceConfiguration

iOS の IVSMixedImageDeviceConfiguration

名前 説明

size

Vec2

ビデオキャンバスのサイズ。

targetFramerate

整数

混合デバイスの 1 秒あたりのターゲットフレーム数。平均として、この値を満たす必要がありますが、特定の状況 (CPU や GPU の負荷の高さなど) でシステムのフレーム数が低下する場合があります。

transparencyEnabled

ブール値

イメージソース設定で alpha プロパティを使用してブレンドできます。これを true に設定すると、メモリおよび CPU の消費量が増加します。デフォルト: false

ソース設定

Android のMixedImageDeviceSourceConfiguration

iOS の IVSMixedImageDeviceSourceConfiguration

名前 説明

alpha

浮動小数点数

スロットのアルファ。これは、画像内のアルファ値との乗法です。有効な値: 0 〜 1。0 は完全に透明で、1 は完全に不透明です。デフォルト: 1。

aspect

AspectMode

スロットでレンダリングされたイメージのアスペクト比モード。有効な値:

  • Fill — 画像のアスペクト比を維持しますが、スロットを埋めます。必要に応じて画像がトリミングされます。

  • Fit — 画像のアスペクト比を維持しますが、画像全体をスロットに収めます。必要に応じて、スロットにレターボックスまたはピラーボックスが付いている場合があります。値が設定されている場合、レター/ピラーボックスは fillColor の中に位置されます。それ以外の場合は透明になります (画像の背後にあるキャンバスの色が黒の場合、黒で表示される場合があります)。

  • None — イメージのアスペクト比を維持しないでください。イメージは、スロットの寸法に合わせてスケールされます。

デフォルト: Fit

fillColor

Vec4

スロットおよび画像のアスペクト比が一致しない場合に aspect Fit と使用する塗りつぶしカラー。フォーマットは (赤、緑、青、アルファ) です。有効な値 (チャネルごとに): 0 〜 1。デフォルト: (0、0、0、0)。

position

Vec2

キャンバスの左上隅からの相対で、スロット位置 (ピクセル) です。スロットの原点も左上です。

size

Vec2

スロットのサイズ (ピクセル単位)。この値を設定すると、matchCanvasSizefalse に設定されます。デフォルト: (0、0)。ただし、matchCanvasSize のデフォルトは true であるため、スロットのレンダリングサイズはキャンバスサイズであり、(0、0) ではありません。

zIndex

浮動小数点数

スロットの相対的な順序。zIndex 値が高いスロットは、zIndex 値が低いスロットの上に描画されます。

混合イメージデバイスの作成と設定

ミキシング用のブロードキャストセッションの設定。

ここでは、このガイドの冒頭にあるシーンに似たシーンを作成し、次の 3 つの画面上の要素を使用します。

  • カメラの左下のスロット。

  • ロゴオーバーレイ用の右下のスロット。

  • 映画の右上のスロット。

キャンバスの原点は左上隅で、これはスロットでも同じであることに注意してください。したがって、スロットを (0、0) に配置すると、スロット全体が見えるように左上隅に配置されます。

iOS

let deviceDiscovery = IVSDeviceDiscovery() let mixedImageConfig = IVSMixedImageDeviceConfiguration() mixedImageConfig.size = CGSize(width: 1280, height: 720) try mixedImageConfig.setTargetFramerate(60) mixedImageConfig.isTransparencyEnabled = true let mixedImageDevice = deviceDiscovery.createMixedImageDevice(with: mixedImageConfig) // Bottom Left let cameraConfig = IVSMixedImageDeviceSourceConfiguration() cameraConfig.size = CGSize(width: 320, height: 180) cameraConfig.position = CGPoint(x: 20, y: mixedImageConfig.size.height - cameraConfig.size.height - 20) cameraConfig.zIndex = 2 let camera = deviceDiscovery.listLocalDevices().first(where: { $0 is IVSCamera }) as? IVSCamera let cameraSource = IVSMixedImageDeviceSource(configuration: cameraConfig, device: camera) mixedImageDevice.add(cameraSource) // Top Right let streamConfig = IVSMixedImageDeviceSourceConfiguration() streamConfig.size = CGSize(width: 640, height: 320) streamConfig.position = CGPoint(x: mixedImageConfig.size.width - streamConfig.size.width - 20, y: 20) streamConfig.zIndex = 1 let streamDevice = deviceDiscovery.createImageSource(withName: "stream") let streamSource = IVSMixedImageDeviceSource(configuration: streamConfig, device: streamDevice) mixedImageDevice.add(streamSource) // Bottom Right let logoConfig = IVSMixedImageDeviceSourceConfiguration() logoConfig.size = CGSize(width: 320, height: 180) logoConfig.position = CGPoint(x: mixedImageConfig.size.width - logoConfig.size.width - 20, y: mixedImageConfig.size.height - logoConfig.size.height - 20) logoConfig.zIndex = 3 let logoDevice = deviceDiscovery.createImageSource(withName: "logo") let logoSource = IVSMixedImageDeviceSource(configuration: logoConfig, device: logoDevice) mixedImageDevice.add(logoSource)

Android

val deviceDiscovery = DeviceDiscovery(this /* context */) val mixedImageConfig = MixedImageDeviceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(1280f, 720f)) setTargetFramerate(60) setEnableTransparency(true) } val mixedImageDevice = deviceDiscovery.createMixedImageDevice(mixedImageConfig) // Bottom Left val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(20f, mixedImageConfig.size.y - size.y - 20)) setZIndex(2) } val camera = deviceDiscovery.listLocalDevices().firstNotNullOf { it as? CameraSource } val cameraSource = MixedImageDeviceSource(cameraConfig, camera) mixedImageDevice.addSource(cameraSource) // Top Right val streamConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(640f, 320f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, 20f)) setZIndex(1) } val streamDevice = deviceDiscovery.createImageInputSource(streamConfig.size) val streamSource = MixedImageDeviceSource(streamConfig, streamDevice) mixedImageDevice.addSource(streamSource) // Bottom Right val logoConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, 180f)) setPosition(BroadcastConfiguration.Vec2(mixedImageConfig.size.x - size.x - 20, mixedImageConfig.size.y - size.y - 20)) setZIndex(1) } val logoDevice = deviceDiscovery.createImageInputSource(logoConfig.size) val logoSource = MixedImageDeviceSource(logoConfig, logoDevice) mixedImageDevice.addSource(logoSource)

ソースの削除

ソースを削除するには、削除する Source オブジェクトで MixedDevice.remove を呼び出します。

トランジションのあるアニメーション

トランジション方法では、ソースの構成が新しい構成に置き換えられます。この置換は、デュレーションを 0 より高く秒単位で設定することで、時間の経過とともにアニメートできます。

アニメーション化できるプロパティ

スロット構造のすべてのプロパティをアニメートできるわけではありません。Float タイプに基づくすべてのプロパティはアニメーション化できます。その他のプロパティは、アニメーションの開始時または終了時に有効になります。

名前 アニメーション化の可否 インパクトポイント

Audio.gain

はい

Interpolated

Image.alpha

はい

Interpolated

Image.aspect

いいえ

修了

Image.fillColor

はい

Interpolated

Image.position

はい

Interpolated

Image.size

はい

Interpolated

Image.zIndex

注: zIndex は 2D 平面を 3D 空間内で移動するため、アニメーションの途中で 2 つの平面が交差したときにトランジションが発生します。これは計算できますが、開始A値と終了 zIndex 値によって異なります。トランジションをよりスムーズにするために、これを alpha と組み合わせます。

はい

不明

シンプルな例

以下では、上記の混合イメージデバイスの作成と設定で定義された設定を使用したフルスクリーンのカメラテイクオーバーの例が示されます。これは 0.5 秒でアニメーション化されます。

iOS

// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.size = CGSize(width: 1280, height: 720) cameraConfig.position = CGPoint.zero cameraSource.transition(to: cameraConfig, duration: 0.5) { completed in if completed { print("Animation completed") } else { print("Animation interrupted") } }

Android

// Continuing the example from above, modifying the existing cameraConfig object. cameraConfig.setSize(BroadcastConfiguration.Vec2(1280f, 720f)) cameraConfig.setPosition(BroadcastConfiguration.Vec2(0f, 0f)) cameraSource.transitionToConfiguration(cameraConfig, 500) { completed -> if (completed) { print("Animation completed") } else { print("Animation interrupted") } }

ブロードキャストのミラーリング

ブロードキャストでアタッチされた画像デバイスを以下の方向にミラーリングする場合 以下の条件には負の値を使用します

水平方向

スロットの幅

垂直方向

スロットの高さ

水平方向と垂直方向の両方

スロットの幅と高さの両方

ミラーリング時にスロットを正しい位置に配置するには、同じ値で位置を調整する必要があります。

以下は、ブロードキャストを水平方向と垂直方向にミラーリングする例です。

iOS

水平ミラーリング:

let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: -320, height: 720) // Add 320 to position x since our width is -320 cameraSource.position = CGPoint(x: 320, y: 0)

垂直ミラーリング:

let cameraSource = IVSMixedImageDeviceSourceConfiguration() cameraSource.size = CGSize(width: 320, height: -720) // Add 720 to position y since our height is -720 cameraSource.position = CGPoint(x: 0, y: 720)

Android

水平ミラーリング:

val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(-320f, 180f)) // Add 320f to position x since our width is -320f setPosition(BroadcastConfiguration.Vec2(320f, 0f)) }

垂直ミラーリング:

val cameraConfig = MixedImageDeviceSourceConfiguration().apply { setSize(BroadcastConfiguration.Vec2(320f, -180f)) // Add 180f to position y since our height is -180f setPosition(BroadcastConfiguration.Vec2(0f, 180f)) }

注: このミラーリングは ImagePreviewView (Android) や IVSImagePreviewView (iOS) の setMirrored 方法とは異なります。このメソッドはデバイス上のローカルプレビューにのみ影響し、ブロードキャストには影響しません。