

# IVS iOS 广播 SDK 入门 \| 低延迟直播功能
<a name="broadcast-ios-getting-started"></a>

本文档将引导您完成 Amazon IVS 低延迟直播功能 iOS 广播 SDK 入门所涉及的步骤。

## 安装库
<a name="broadcast-ios-install"></a>

我们建议您通过 Swift 程序包管理器集成广播 SDK。（或者，您可以手动将框架添加至项目。）

### 建议：集成广播 SDK（Swift 程序包管理器）
<a name="broadcast-ios-install-swift"></a>

1. 从 [https://broadcast.live-video.net/1.41.0/Package.swift](https://broadcast.live-video.net/1.41.0/Package.swift) 下载 Package.swift 文件。

1. 在您的项目中，创建一个名为 AmazonIVSBroadcast 的新目录并将其添加到版本控制中。

1. 将下载的 Package.swift 文件放到新目录中。

1. 在您的 Xcode 项目中，转到**文件 > 添加软件包依赖项**，然后选择**添加本地...**

1. 导航到并选择您创建的 AmazonIVSBroadcast 目录，然后选择**添加软件包**。

1. 当系统提示**选择 AmazonIVSBroadcast 的软件包产品**时，请通过在**添加到目标**部分中设置应用程序目标来将 **AmazonIVSBroadcast** 选为**软件包产品**。

1. 选择**添加软件包**。

### 替代方法：手动安装框架
<a name="broadcast-ios-install-manual"></a>

1. 最新版本下载链接：[https://broadcast.live-video.net/1.41.0/AmazonIVSBroadcast.xcframework.zip](https://broadcast.live-video.net/1.41.0/AmazonIVSBroadcast.xcframework.zip)。

1. 提取归档的内容。`AmazonIVSBroadcast.xcframework` 包含适用于设备和模拟器的开发工具包。

1. 通过以下方法嵌入 `AmazonIVSBroadcast.xcframework`：将其拖动到应用程序目标的 **General**（常规）选项卡中的 **Frameworks, Libraries, and Embedded Content**（框架、库和嵌入式内容）部分中。  
![应用程序目标 General（常规）选项卡上的 Frameworks, Libraries, and Embedded Content（框架、库和嵌入式内容）部分：](http://docs.aws.amazon.com/zh_cn/ivs/latest/LowLatencyUserGuide/images/iOS_Broadcast_SDK_Guide_xcframework.png)

## 实施 IVSBroadcastSession.Delegate
<a name="broadcast-ios-implement-ivsbroadcastsessiondelegate"></a>

实施 `IVSBroadcastSession.Delegate`，它允许您接收状态更新和设备更改通知：

```
extension ViewController : IVSBroadcastSession.Delegate {
   func broadcastSession(_ session: IVSBroadcastSession,
                         didChange state: IVSBroadcastSession.State) {
      print("IVSBroadcastSession did change state \(state)")
   }

   func broadcastSession(_ session: IVSBroadcastSession,
                         didEmitError error: Error) {
      print("IVSBroadcastSession did emit error \(error)")
   }
}
```

## 请求权限
<a name="broadcast-ios-permissions"></a>

您的应用必须请求权限才能访问用户摄像头和麦克风。（这并非特定于 Amazon IVS；需要访问摄像头和麦克风的任何应用程序都需要这样做。）

我们在此处检查用户是否已授予权限，如果没有，对他们提出要求：

```
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: // permission already granted.
case .notDetermined:
   AVCaptureDevice.requestAccess(for: .video) { granted in
       // permission granted based on granted bool.
   }
case .denied, .restricted: // permission denied.
@unknown default: // permissions unknown.
}
```

如果您希望分别访问摄像头和麦克风，则需要对 `.video` 和 `.audio` 媒体类型进行此操作。

您还需要将 `NSCameraUsageDescription` 和 `NSMicrophoneUsageDescription` 的条目添加到 `Info.plist`。否则，尝试请求权限时，您的应用程序将崩溃。

## 禁用应用程序空闲计时器
<a name="broadcast-ios-disable-idle-timer"></a>

您可以自由选择，但我们建议您这样做。它可以防止您的设备在使用广播开发工具包时进入睡眠状态，这会中断广播。

```
override func viewDidAppear(_ animated: Bool) {
   super.viewDidAppear(animated)
   UIApplication.shared.isIdleTimerDisabled = true
}
override func viewDidDisappear(_ animated: Bool) {
   super.viewDidDisappear(animated)
   UIApplication.shared.isIdleTimerDisabled = false
}
```

## （可选）设置 AVAudioSession
<a name="broadcast-ios-setup-avaudiosession"></a>

默认情况下，广播开发工具包将设置您的应用程序的 `AVAudioSession`。如果您想自己管理此工具包，请将 `IVSBroadcastSession.applicationAudioSessionStrategy` 设置为 `noAction`。如果不控制 `AVAudioSession`，广播开发工具包无法在内部管理麦克风。要将麦克风与 `noAction` 选项结合使用，您可以创建 `IVSCustomAudioSource` 并通过 `AVCaptureSession`、`AVAudioEngine` 或提供 PCM 音频样本的其他工具提供您自己的样本。

如果您手动设置 `AVAudioSession`，您至少需要将类别设置为 `.record` 或者 `.playbackAndRecord`，并将其设置为 `active`。如果要从蓝牙设备录制音频，还需要指定 `.allowBluetooth` 选项：

```
do {
   try AVAudioSession.sharedInstance().setCategory(.record, options: .allowBluetooth)
   try AVAudioSession.sharedInstance().setActive(true)
} catch {
   print("Error configuring AVAudioSession")
}
```

我们建议让开发工具包为您处理此问题。否则，如果要在不同的音频设备之间进行选择，则需要手动管理这些端口。

## 创建广播会话
<a name="broadcast-ios-create-session"></a>

广播接口为 `IVSBroadcastSession`。将其初始化，如下所示：

```
let broadcastSession = try IVSBroadcastSession(
   configuration: IVSPresets.configurations().standardLandscape(),
   descriptors: IVSPresets.devices().frontCamera(),
   delegate: self)
```

另请参阅 [创建广播会话（高级版）](broadcast-ios-use-cases.md#broadcast-ios-create-session-advanced)

## 设置 IVSImagePreviewView 进行预览
<a name="broadcast-ios-set-imagepreviewview"></a>

如果要显示活动摄像机设备的预览，请将设备的预览 `IVSImagePreviewView` 添加到您的视图层次结构：

```
// If the session was just created, execute the following 
// code in the callback of IVSBroadcastSession.awaitDeviceChanges 
// to ensure all devices have been attached.
if let devicePreview = try broadcastSession.listAttachedDevices()
   .compactMap({ $0 as? IVSImageDevice })
   .first?
   .previewView()
{
   previewView.addSubview(devicePreview)
}
```

## 开启广播
<a name="broadcast-ios-start"></a>

您在 `GetChannel` 操作的 `ingestEndpoint` 响应字段中接收的主机名的前面应为 `rtmps://`，后面为 `/app`。完整 URL 应采用以下格式：`rtmps://{{ ingestEndpoint }}/app`

```
try broadcastSession.start(with: IVS_RTMPS_URL, streamKey: IVS_STREAMKEY)
```

 iOS 广播 SDK 仅支持 RTMPS 采集（不支持不安全的 RTMP 采集）。

## 停止广播
<a name="broadcast-ios-stop"></a>

```
broadcastSession.stop()
```

## 管理生命周期事件
<a name="broadcast-ios-lifecycle-events"></a>

### 音频中断
<a name="broadcast-ios-audio-interruptions"></a>

在多种情况下，广播开发工具包将不具有音频输入硬件的独占访问权限。您需要处理的一些示例情况如下：
+ 用户接收电话或 FaceTime 通话
+ 用户激活 Siri

Apple 可以轻松地响应这些事件，方法是订阅 `AVAudioSession.interruptionNotification`：

```
NotificationCenter.default.addObserver(
   self,
   selector: #selector(audioSessionInterrupted(_:)),
   name: AVAudioSession.interruptionNotification,
   object: nil)
```

然后您可以使用类似方法来处理事件：

```
// This assumes you have a variable `isRunning` which tracks if the broadcast is currently live, and another variable `wasRunningBeforeInterruption` which tracks whether the broadcast was active before this interruption to determine if it should resume after the interruption has ended.

@objc
private func audioSessionInterrupted(_ notification: Notification) {
   guard let userInfo = notification.userInfo,
         let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
         let type = AVAudioSession.InterruptionType(rawValue: typeValue)
   else {
      return
   }
   switch type {
   case .began:
      wasRunningBeforeInterruption = isRunning
      if isRunning {
         broadcastSession.stop()
      }
   case .ended:
      defer {
         wasRunningBeforeInterruption = false
      }
      guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
      let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
      if options.contains(.shouldResume) && wasRunningBeforeInterruption {
         try broadcastSession.start(
            with: IVS_RTMPS_URL,
            streamKey: IVS_STREAMKEY)
      }
   @unknown default: break
   }
}
```

### 应用程序进入后台
<a name="broadcast-ios-app-to-background"></a>

不允许 iOS 中的标准应用程序在后台使用摄像机。在后台进行视频编码也有限制：由于硬件编码器受到限制，因此只有前台应用程序才能访问。因此，广播开发工具包会自动终止其会话并将其 `isReady` 属性设置为 `false`。当您的应用程序即将再次进入前台时，广播开发工具包会将所有设备重新连接到其原始 `IVSMixerSlotConfiguration` 条目。

广播开发工具包通过响应 `UIApplication.didEnterBackgroundNotification` 和 `UIApplication.willEnterForegroundNotification` 完成此操作。

如果您正在提供自定义图像源，您应该准备好处理这些通知。在终止流之前，您可能需要执行额外的步骤来停用它们。

请参阅[使用后台视频](broadcast-ios-use-cases.md#broadcast-ios-background-video)以获取在应用程序处于后台时启用串流的解决方法。

### 媒体服务丢失
<a name="broadcast-ios-media-services-lost"></a>

在极少数情况下，iOS 设备上的整个媒体子系统将崩溃。在这种情况下，我们无法再广播。您的应用程序对这些通知作出适当响应。至少应订阅以下通知：
+ [mediaServicesWereLostNotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/1616457-mediaserviceswerelostnotificatio) - 通过停止广播并完全取消分配您的 `IVSBroadcastSession` 进行响应。广播会话使用的所有内部组件都将失效。
+ [mediaServicesWereResetNotification](https://developer.apple.com/documentation/avfaudio/avaudiosession/1616540-mediaserviceswereresetnotificati) - 通过通知用户他们可以再次广播进行响应。根据您的使用案例，您可在此时重新自动开始广播。