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”);
分离设备
如果要分离而不是替换设备,请使用 Device
或 Device.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.status
为 SUCCESS
或者 ERROR
。您可以使用 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]; } }); }
使用自动重新连接
如果广播意外停止而未调用 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);