

# IVS Android Broadcast SDK の高度なユースケース \| Low-Latency Streaming
<a name="broadcast-android-use-cases"></a>

ここでは、いくつかの高度なユースケースを紹介します。上記の基本的な設定から始まり、ここまで進んできました。

## ブロードキャスト設定の作成
<a name="broadcast-android-create-configuration"></a>

2 つのミキサースロットを持つカスタム設定を作成し、2 つの動画ソースをミキサーにバインドできます。1 つの画面 (`custom`) は全画面表示で、右下にある別の小画面 (`camera`) の後ろに配置されます。`custom` スロットには、位置、サイズ、またはアスペクトモードを設定しないことに注意してください。これらのパラメータは設定しないので、スロットはサイズと位置の動画設定を使用します。

```
BroadcastConfiguration config = BroadcastConfiguration.with($ -> {
    $.audio.setBitrate(128_000);
    $.video.setMaxBitrate(3_500_000);
    $.video.setMinBitrate(500_000);
    $.video.setInitialBitrate(1_500_000);
    $.video.setSize(1280, 720);
    $.mixer.slots = new BroadcastConfiguration.Mixer.Slot[] {
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                // Do not automatically bind to a source
                slot.setPreferredAudioInput(
                           Device.Descriptor.DeviceType.UNKNOWN);
                // Bind to user image if unbound
                slot.setPreferredVideoInput(
                           Device.Descriptor.DeviceType.USER_IMAGE);
                slot.setName("custom");
                return slot;
            }),
            BroadcastConfiguration.Mixer.Slot.with(slot -> {
                slot.setzIndex(1);
                slot.setAspect(BroadcastConfiguration.AspectMode.FILL);
                slot.setSize(300, 300);
                slot.setPosition($.video.getSize().x - 350,
                        $.video.getSize().y - 350);
                slot.setName("camera");
                return slot;
            })
    };
    return $;
});
```

## ブロードキャストセッションの作成 (詳細バージョン)
<a name="broadcast-android-create-session-advanced"></a>

[基本の例](broadcast-android-getting-started.md#broadcast-android-create-session)で行ったように `BroadcastSession` を作成しますが、ここでカスタム設定を提供します。デバイスアレイにも `null` を提供します。それらを手動で追加します。

```
// Create a broadcast-session instance and sign up to receive broadcast
// events and errors.
Context ctx = getApplicationContext();
broadcastSession = new BroadcastSession(ctx,
                       broadcastListener,
                       config, // The configuration we created above
                       null); // We’ll manually attach devices after
```

## カメラデバイスの繰り返し処理とアタッチ
<a name="broadcast-android-attach-camera"></a>

SDK が検出した入力デバイスを繰り返し処理します。Android 7（Nougat）では、これはデフォルトのマイクデバイスのみを返します。これは、Amazon IVS Broadcast SDK はこのバージョンの Android でデフォルト以外のデバイスの選択をサポートしていないためです。

使用したいデバイスを見つけたら、`attachDevice` を呼び出してアタッチします。入力デバイスの接続が完了すると、メインスレッドで Lambda 関数が呼び出されます。エラーが発生した場合、Listener でエラーが発生します。

```
for(Device.Descriptor desc: BroadcastSession.listAvailableDevices(getApplicationContext())) {
    if(desc.type == Device.Descriptor.DeviceType.CAMERA &&
            desc.position == Device.Descriptor.Position.FRONT) {
        session.attachDevice(desc, device -> {
            LinearLayout previewHolder = findViewById(R.id.previewHolder);
            ImagePreviewView preview = ((ImageDevice)device).getPreviewView();
            preview.setLayoutParams(new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.MATCH_PARENT,
                    LinearLayout.LayoutParams.MATCH_PARENT));
            previewHolder.addView(preview);
            // Bind the camera to the mixer slot we created above.
            session.getMixer().bind(device, "camera");
        });
        break;
    }
}
```

## カメラのスワップ
<a name="broadcast-android-swap-cameras"></a>

```
// This assumes you’ve kept a reference called "currentCamera" that points to
// a front facing camera
for(Device device: BroadcastSession.listAvailableDevices()) {
   if(device.type == Device.Descriptor.DeviceType.CAMERA &&
          Device.position != currentCamera.position) {
        // Remove the preview view for the old device.
        // setImagePreviewTextureView is an example function 
        // that handles your view hierarchy.
        setImagePreviewView(null);
        session.exchangeDevices(currentCamera, device, camera -> {
             // Set the preview view for the new device.
             setImagePreviewView(camera.getPreviewView());
             currentCamera = camera;
        });
        break;
   }
}
```

## 入力サーフェスを作成する
<a name="broadcast-android-create-input-surface"></a>

アプリが生成するサウンドや画像データを入力するには、`createImageInputSource` または `createAudioInputSource` を使用します。どちらの方法も、他のデバイスと同様にミキサにバインドできる仮想デバイスを作成してアタッチします。

`createImageInputSource` が返す `SurfaceSource` には `getInputSurface` メソッドが含まれます。このメソッドは、Camera2 API、OpenGL、Vulkan、または Surface に書き込みできるその他のもので使用できる `Surface` を提供します。

`createAudioInputSource` が返す`AudioDevice` は、AudioRecorder またはその他の手段によって生成された線形 PCM データを受信できます。

```
SurfaceSource source = session.createImageInputSource();
Surface surface = source.getInputSurface();
session.getMixer().bind(source, “custom”);
```

## デバイスのデタッチ
<a name="broadcast-android-detach-device"></a>

デバイスをデタッチし、交換しない場合は、`Device` または `Device.Descriptor` を使用してデタッチします。

```
session.detachDevice(currentCamera);
```

## 画面およびシステムオーディオキャプチャ
<a name="broadcast-android-screen-audio-capture"></a>

Amazon IVS Broadcast SDK for Android には、デバイスの画面（Android 6 以降）とシステムオーディオ（Android 10 以降）のキャプチャの簡素化に役立ちます。これらを手動で管理する場合は、カスタム画像入力ソースとカスタムオーディオ入力ソースを作成できます。

画面およびシステムオーディオのキャプチャセッションを作成するには、最初にアクセス許可リクエストのインテントを作成する必要があります。

```
public void startScreenCapture() {
    MediaProjectionManager manager =
                         (MediaProjectionManager) getApplicationContext()
                         .getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    if(manager != null) {
        Intent intent = manager.createScreenCaptureIntent();
        startActivityIfNeeded(intent, SCREEN_CAPTURE_REQUEST_ID);
    }
}
```

この機能を使用するには、`com.amazonaws.ivs.broadcast.SystemCaptureService` を拡張するクラスを提供する必要があります。それらのメソッドをオーバーライドする必要はありませんが、サービス間の潜在的な衝突を避けるためにクラスが必要になります。

また、Android マニフェストにいくつかの要素を追加する必要があります。

```
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application ...>
    <service android:name=".ExampleSystemCaptureService"
         android:foregroundServiceType="mediaProjection" 
         android:isolatedProcess="false" />
</application>
...
```

`SystemCaptureService` を拡張するクラスは、`<service>` 要素で名前を付ける必要があります。Android 9 以降では、`foregroundServiceType` は `mediaProjection` でなければなりません。

アクセス許可のインテントを受け取ると、画面とシステムオーディオのキャプチャセッションの作成に進めます。Android 8 以降では、ユーザーの通知パネルに表示される通知を提供する必要があります。Amazon IVS Broadcast SDK for Android は、便利なメソッド `createServiceNotificationBuilder` を提供します。代わりに、独自の通知を提供することもできます。

```
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode != SCREEN_CAPTURE_REQUEST_ID
       || Activity.RESULT_OK != resultCode) {
        return;
    }
    Notification notification = null;
    if(Build.VERSION.SDK_INT >= 26) {
        Intent intent = new Intent(getApplicationContext(),
                                   NotificationActivity.class);
        notification = session
                         .createServiceNotificationBuilder("example",
                                            "example channel", intent)
                         .build();
    }
    session.createSystemCaptureSources(data,
                  ExampleSystemCaptureService.class,
                  Notification,
                  devices -> {
        // This step is optional if the mixer slots have been given preferred
        // input device types SCREEN and SYSTEM_AUDIO
        for (Device device : devices) {
            session.getMixer().bind(device, "game");
        }
    });
}
```

## 推奨されるブロードキャスト設定の取得
<a name="broadcast-android-recommended-settings"></a>

ブロードキャストを開始する前にユーザーの接続を評価するには、`recommendedVideoSettings` メソッドを使用して簡単なテストを実行します。テストが実行されると、最も推奨されるものから順に、さまざまな推奨事項が表示されます。このバージョンの SDK では、現在の `BroadcastSession` を再構成することはできないため、`release()` してから、推奨設定で新しいものを作成する必要があります。　 `Result.status` が `SUCCESS` または `ERROR` になるまで、`BroadcastSessionTest.Results` を受け取り続けます。進捗状況を確認するには `Result.progress` を使用します。

Amazon IVS は、最大ビットレート 8.5 MBps (`type` が `STANDARD` または `ADVANCED` のチャネルの場合) をサポートしているため、このメソッドが返す `maximumBitrate` が 8.5 MBps を超えることは一切ありません。ネットワークパフォーマンスのわずかな変動を考慮するために、このメソッドが返す奨励される `initialBitrate` はテストで測定した実際のビットレートよりわずかに小さくなります。 (通常、使用可能な帯域幅の 100% を使用することはお勧めできません。) 

```
void runBroadcastTest() {
    this.test = session.recommendedVideoSettings(RTMPS_ENDPOINT, RTMPS_STREAMKEY,
        result -> {
            if (result.status == BroadcastSessionTest.Status.SUCCESS) {
                this.recommendation = result.recommendations[0];
            }
        });
}
```

## Auto-Reconnect の使用
<a name="broadcast-android-auto-reconnect"></a>

IVS は、ネットワーク接続が一時的に失われた場合など、ブロードキャストが `stop` API を呼び出すことなく予期せず停止した場合に、ブロードキャストへの自動再接続をサポートします。自動再接続を有効にするには、`BroadcastConfiguration.autoReconnect` で `setEnabled(true)` を呼び出します。

何らかの原因でストリームが予期せず停止した場合、SDK は線形バックオフ戦略に従って最大 5 回再試行します。`BroadcastSession.Listener.onRetryStateChanged` メソッドを使用して、再試行状態をアプリケーションに通知します。

自動再接続では、指定されたストリームキーの末尾に 1 で始まる優先度番号を追加することによって、バックグラウンドで IVS [ストリーム引き継ぎ](streaming-config.md#streaming-config-stream-takeover)機能が使用される仕組みになっています。`BroadcastSession` インスタンスの期間中、再接続が試行されるたびに、その数は 1 ずつ増分されます。つまり、ブロードキャスト中にデバイスの接続が 4 回失われ、各損失で 1～4 回の再試行が必要になった場合、最後にアップしたストリームの優先度は 5～17 の範囲で設定できます。このため、*SDK で同じチャネルの自動再接続が有効になっている間は、別のデバイスからの IVS ストリーム引き継ぎを使用しないことをお勧めします*。その時点で SDK が使用している優先度は保証されないため、別のデバイスが引き継いだ場合、SDK はより高い優先度を使用して再接続を試みます。

## Bluetooth マイクの使用
<a name="broadcast-android-bluetooth-microphones"></a>

Bluetooth マイクデバイスを使用してブロードキャストするには、Bluetooth SCO 接続を開始する必要があります。

```
Bluetooth.startBluetoothSco(context);
// Now bluetooth microphones can be used
…
// Must also stop bluetooth SCO
Bluetooth.stopBluetoothSco(context);
```