IVS Android 广播 SDK 的高级用例 | 低延迟直播功能 - Amazon IVS

IVS Android 广播 SDK 的高级用例 | 低延迟直播功能

我们将在此处介绍一些高级使用案例。从上面的基本设置开始,然后在此处继续。

创建广播配置

我们将在此处创建一个带有两个混合器插槽的自定义配置,允许我们将两个视频源绑定到混合器。一个 (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 $; });

创建广播会话(高级版)

就像在基本示例中一样创建 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

迭代和连接摄像机设备

我们将通过开发工具包检测到的输入设备进行迭代。在 Android 7 (Nougat) 上,这将仅返回默认麦克风设备,因为 Amazon IVS 广播开发工具包不支持在此版本的 Android 上选择非默认设备。

找到我们想要使用的设备之后,我们就会调用 attachDevice 来连接它。连接输入设备完成后,在主线程上调用 lambda 函数。如果出现故障,您将在侦听器中收到错误。

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; } }

交换摄像机

// 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; } }

创建输入表面

若要输入应用程序生成的声音或图像数据,请使用 createImageInputSource 或者 createAudioInputSource。这两种方法都会创建和连接虚拟设备,这些设备可以像任何其他设备一样绑定到混合器。

createImageInputSource 返回的 SurfaceSource 具有 getInputSurface 方法,它会为您提供一个 Surface,可以将其与 Camera2 API、OpenGL 或 Vulkan 或可以写入到 Surface 的任何其他接口一起使用。

createAudioInputSource 返回的 AudioDevice 可以接收由音频录音机或其他方式生成的线性 PCM 数据。

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

分离设备

如果要分离而不是替换设备,请使用 DeviceDevice.Descriptor 来分离它。

session.detachDevice(currentCamera);

屏幕和系统音频捕获

Amazon IVS Broadcast SDK for Android 含有一些帮助程序,可以简化捕获设备屏幕(Android 5 及更高版本)和系统音频(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> ...

必须在 <service> 元素内命名扩展 SystemCaptureService 的类。在 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"); } }); }

若要在开始广播之前评估用户的连接,请使用 recommendedVideoSettings 方法来运行一个简短的测试。在测试运行时,您将收到多个建议,从最推荐到最不推荐的顺序排列。在此版本的开发工具包中,无法重新配置当前 BroadcastSession,因此您需要 release(),然后使用推荐的设置创建一个新的。您将继续收到 BroadcastSessionTest.Results,直到 Result.statusSUCCESS 或者 ERROR。您可以使用 Result.progress 检查进度。

Amazon IVS 支持 8.5 Mbps 的最大比特率(对于其 typeSTANDARDADVANCED 的通道),所以此方法返回的 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]; } }); }

使用自动重新连接

如果广播意外停止而未调用 stop API(例如,网络连接暂时丢失),IVS 支持自动重新连接到广播。要启用自动重新连接,请在 BroadcastConfiguration.autoReconnect 上调用 setEnabled(true)

当某些原因导致直播意外停止时,SDK 会按照线性退避策略重试最多 5 次。它通过 BroadcastSession.Listener.onRetryStateChanged 方法将重试状态通知您的应用程序。

在后台,自动重新连接在提供的直播密钥末尾附加一个以 1 开头的优先级数字,以此来使用 IVS 直播接管功能。在 BroadcastSession 实例的持续期间,每次尝试重新连接时,该数字都会增加 1。这意味着,如果设备的连接在广播期间丢失 4 次,并且每次丢失都需要重试 1-4 次,则上次直播的优先级可能介于 5 到 17 之间。因此,在 SDK 中为同一通道启用自动重新连接时,我们建议您不要使用其他设备的 IVS 直播接管。无法保证 SDK 当时使用的优先级,如果另一台设备接管,SDK 将尝试以更高的优先级进行重新连接。

使用蓝牙麦克风

要使用蓝牙麦克风设备进行广播,必须启动蓝牙 SCO 连接:

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