适用于 iOS 的相机设备指南

摄像头设备类型通过以下两种特征实现:PushAvStreamTransportTrait,用于使用基于推送的协议处理音频和视频流传输;WebRtcLiveViewTrait,用于提供控制直播和对讲的功能。 对于具有摄像头功能的实现,门铃设备类型也使用这些特征。

Home API 设备类型 特征 Swift 示例应用 使用场景

相机

GoogleCameraDeviceType

home.matter.6006.types.0158

可拍摄静态图像或视频的设备。摄像头可能具有以下功能:无障碍直播、双向对讲或检测事件。

必需的特征
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

相机

门铃

GoogleDoorbellDeviceType

home.matter.6006.types.0113

一种通过门外的按钮启动的设备,可发出声音和/或视觉信号,用于引起门另一侧的人的注意。门铃可能具有无障碍直播、双向对讲或检测事件等功能。

必需的特征
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

门铃

开始直播

如需开始直播,请将会话描述协议 (SDP) 字符串发送到 WebRtcLiveViewTrait 特征的 startLiveView(offerSdp:) 方法,该方法会返回三个值:

  • 会话的 SDP。
  • 会话时长(以秒为单位)。
  • 会话 ID,可用于延长或终止会话。
public func sendOffer(offerSdp: String) async throws 
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval) 
{
  do {
    Logger.info("Sending StartLiveView command...")
    let response = try await liveViewTrait.startLiveView(
      offerSdp: offerSdp
    )
    Logger.info("Received StartLiveView response: \(response)")
    return (
      answerSdp: response.answerSdp,
      mediaSessionId: response.mediaSessionId,
      liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
    )
  } catch {
    Logger.error("Failed to send StartLiveView command: \(error)")
    throw error
  }
}

延长直播

直播具有预设时长,超过该时长后直播会过期。如需延长有效直播的时长,请使用 extendLiveView(mediaSessionId:optionalArgsProvider:) 方法发出延期请求:

public func extendLiveView(mediaSessionId: String) async throws {
  do {
    Logger.info("Extending live view...")
    let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
    Logger.info("Extended live view for \(extendedDuration.liveSessionDurationSeconds) seconds.")
  } catch {
    Logger.error("Failed to extend live view: \(error)")
    throw error
  }
}

启用和停用录制功能

如需启用相机的录制功能,请将 TransportStatusEnum.Active 传递给 PushAvStreamTransportTrait 特征的 setTransportStatus(transportStatus:optionalArgsProvider:) 方法。如需停用录制功能,请传递 TransportStatusEnum.Inactive。 在以下示例中,我们将这些调用封装在一个使用 Boolean 切换录制功能的调用中:

public func toggleIsRecording(isOn: Bool) {
  self.uiState = .loading

  guard let pushAvStreamTransportTrait else {
    Logger.error("PushAvStreamTransportTrait not found.")
    return
  }
  Task {
    do {
      Logger.debug("Toggling onOff to \(isOn ? "ON" : "OFF")...")
      try await pushAvStreamTransportTrait.setTransportStatus(
        transportStatus: isOn ? .active : .inactive)
      if isOn {
        do {
          self.player = try self.createWebRtcPlayer()
        } catch {
          Logger.error("Failed to initialize WebRtcPlayer: \(error)")
          self.uiState = .disconnected
          return
        }
        await self.player?.initialize()
        self.uiState = .live
      } else {
        self.player = nil
        self.uiState = .off
      }
    } catch {
      Logger.error("Failed to toggle onOff: \(error)")
    }
  }
}

检查录制功能是否已启用

如需确定摄像头的录制功能是否已启用,请检查是否有任何连接处于活动状态。以下示例定义了两个函数来实现此目的:

public func isDeviceRecording() -> Bool {
  guard let pushAvStreamTransportTrait else {
    Logger.error("PushAvStreamTransportTrait not found.")
    return false
  }
  guard
    let hasActiveConnection =
      pushAvStreamTransportTrait
      .attributes
      .currentConnections?
      .contains(where: { $0.transportStatus == .active })
  else {
    return false
  }
  return hasActiveConnection
}

启动和停止 TalkBack

如需启动 TalkBack,请调用 WebRtcLiveViewTrait 特征的 startTalkback(mediaSessionId:optionalArgsProvider:) 方法。如需停止,请使用 stopTalkback(mediaSessionId:)

public func toggleTwoWayTalk(isOn: Bool, mediaSessionId: String) async throws {
  do {
    Logger.info("Toggling twoWayTalk to \(isOn ? "ON" : "OFF")...")
    if isOn {
      try await liveViewTrait.startTalkback(mediaSessionId: mediaSessionId)
    } else {
      try await liveViewTrait.stopTalkback(mediaSessionId: mediaSessionId)
    }
  } catch {
    throw HomeError.commandFailed("Failed to toggle twoWayTalk: \(error)")
  }
}