Android 相机设备指南

摄像头设备类型使用两个特征来实现:PushAvStreamTransport,用于使用基于推送的协议处理音频和视频流传输;WebRtcLiveView,用于提供控制直播和对讲的功能。

在尝试使用任何功能或更新属性之前,请务必先检查设备是否支持相应属性和命令。如需了解详情,请参阅控制Android上的设备

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

相机

GoogleCameraDevice

home.matter.6006.types.0158

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

必需的特征
     google PushAvStreamTransport
     google WebRtcLiveView

相机

开始直播

如需开始直播,请将会话描述协议 (SDP) 字符串发送到 WebRtcLiveView 特征的 startLiveView() 方法,该方法会返回一个 WebRtcLiveViewTrait.StartLiveViewCommand.Response,其中包含三个值:

  • 会话的 SDP。
  • 会话时长(以秒为单位)。
  • 会话 ID,可用于延长或终止会话。
suspend fun getWebRtcLiveViewTrait(cameraDevice: HomeDevice) {
 return cameraDevice.type(GoogleCameraDevice).trait(WebRtcLiveView).first {
    it?.metadata?.sourceConnectivity?.connectivityState == ConnectivityState.ONLINE
  }

}

// Start the live view
suspend fun startCameraStream(trait: WebRtcLiveView, offerSdp: String) {
  val response = trait.startLiveView(offerSdp)
  // Response contains three fields (see below)
  return response
}
  ...

// This is used to manage the WebRTC connection
val peerConnection: RTCPeerConnection = ...

   ...

val startResponse = startCameraStream(sdp)
val answerSdp = startResponse?.answerSdp
val sessionDuration = startResponse?.liveSessionDurationSeconds
val mediaSessionId = startResponse?.mediaSessionId

peerConnection.setRemoteDescription(SessionDescription.Type.ANSWER,
                                    answerSdp)

延长直播

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

// Assuming camera stream has just been started
suspend fun scheduleExtension(trait: WebRtcLiveView, mediaSessionId: String, liveSessionDurationSeconds: UShort ) {
  delay(liveSessionDurationSeconds - BUFFER_SECONDS * 1000)
  val response = trait.extendLiveView(mediaSessionId)
  // returns how long the session will be live for
  return response.liveSessionDurationSeconds
}

启动和停止 TalkBack

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

// Make sure camera stream is on
suspend fun setTalkback(isOn: Boolean, trait: WebRtcLiveView, mediaSessionId: String) {
  if(isOn) {
    trait.startTalkback(mediaSessionId)
  } else {
    trait.stopTalkback(mediaSessionId)
  }
}

启用和停用录制功能

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

// Start or stop recording for all connections.
suspend fun setCameraRecording(trait: PushAvStreamTransport, isOn: Boolean) {
  if(isOn) {
    trait.setTransportStatus(TransportStatusEnum.Active)
  } else {
    trait.setTransportStatus(TransportStatusEnum.Inactive)
  }
}

启用或停用摄像头的录制功能与开启或关闭摄像头视频相同。当摄像头视频处于开启状态时,摄像头会进行录制(用于录制事件和相关片段)。

当录制功能处于停用状态(相机视频处于关闭状态)时:

  • 根据设备类型的 connectivityState,摄像头仍可显示为在线。
  • 无法访问实时视频画面,摄像头也未检测到任何云事件。

检查录制功能是否已启用

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

// Get the on/off state
suspend fun onOffState(pushAvStreamTransport: PushAvStreamTransport) {
  return pushAvStreamTransport
    .currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false
}

// Check if the camera's recording capability is enabled
fun PushAvStreamTransport.recordModeActive(): Boolean {
  return currentConnections?.any { it.transportStatus == TransportStatusEnum.Active } ?: false
}

另一种检查方法是使用带有谓词的 findTransport() 函数:

// Fetch the current connections
suspend fun queryRecordModeState(trait: PushAvStreamTransport) {
  return trait.findTransport().let {
      it.transportConfigurations.any { it.transportStatus == TransportStatusEnum.Active
    }
}

音频设置

您可以通过 Home API 控制各种摄像头音频设置。

开启或关闭麦克风

如需开启或关闭设备的麦克风,请使用内置的 setMicrophoneMuted Kotlin 函数更新 CameraAvStreamManagement 特征的 microphoneMuted 属性:

// Turn the device's microphone on or off
suspend fun turnOffMicrophone(disableMicrophone: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setMicrophoneMuted(disableMicrophone) }
}

开启或关闭录音功能

如需为设备开启或关闭音频录制功能,请使用内置的 setRecordingMicrophoneMuted Kotlin 函数更新 CameraAvStreamManagement 特征的 recordingMicrophoneMuted 属性:

// Turn audio recording on or off for the device
suspend fun turnOffAudioRecording(disableAudioRecording: Boolean, trait: CameraAvStreamManagement) {
  trait.update { setRecordingMicrophoneMuted(disableAudioRecording) }
}

调整音箱音量

如需调整设备的扬声器音量,请使用内置的 setSpeakerVolumeLevel Kotlin 函数更新 CameraAvStreamManagement 特征的 speakerVolumeLevel 属性:

// Adjust the camera speaker volume
suspend fun adjustSpeakerVolume(volume: Int, trait: CameraAvStreamManagement) {
  trait.update { setSpeakerVolumeLevel(volume.toUbyte()) }
}

其他设置

您还可以通过 Home API 控制各种其他摄像头设置。

更改图片方向

可以旋转摄像头图像(视频)的方向。视频只能旋转 180 度。

如需更改相机的图像方向,请使用内置的 setImageRotation Kotlin 函数更新 CameraAvStreamManagement 特征的 imageRotation 属性:

// Change the camera's image orientation
val isRotated = false

cameraAvStreamManagement.update { setImageRotation(if (isRotated) 180.toUShort() else 0.toUShort()) }

开启或关闭夜视功能

如需为相机开启或关闭夜视功能,请使用 TriStateAutoEnum 通过内置的 setNightVision Kotlin 函数更新 CameraAvStreamManagement 特征的 nightVision 属性:

// Turn night vision on
cameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.On)
}

// Turn night vision off
CameraAvStreamManagement.update {
  setNightVision(CameraAvStreamManagementTrait.TriStateAutoEnum.Off)
}

更改状态 LED 的亮度

如需更改状态 LED 的亮度,请使用 ThreeLevelAutoEnum 通过内置的 setStatusLightBrightness Kotlin 函数更新 CameraAvStreamManagement 特征的 statusLightBrightness 属性:

// Set the LED brightness to high
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.High)
}

// Set the LED brightness to low
cameraAvStreamManagement.update {
  setStatusLightBrightness(CameraAvStreamManagementTrait.ThreeLevelAutoEnum.Low)
}

更改相机视口

摄像头取景器与缩放和增强 Nest 摄像头视频画面支持文章中所述的“缩放和裁剪”功能相同。

视口在 ViewportStruct 中定义,其中包含四个值,这些值用作视口的坐标。坐标定义如下:

(x1,y1) -- (x2,y1)
   |          |
(x1,y2) -- (x2,y2)

确定 ViewportStruct 的值取决于应用的界面和相机实现。在非常基本的层面上,如需设置相机视频的视口,请使用内置的 setViewport Kotlin 函数,通过 ViewportStruct 更新 CameraAvStreamManagement 特征的 viewport 属性:

cameraAvStreamManagement
  .update { setViewport(
    CameraAvStreamManagementTrait.ViewportStruct(
      x1 = horizontalRange.rangeStart.roundToInt().toUShort(),
      x2 = horizontalRange.rangeEnd.roundToInt().toUShort(),
      y1 = verticalRange.rangeStart.roundToInt().toUShort(),
      y2 = verticalRange.rangeEnd.roundToInt().toUShort(),
    )
) }

调整设备唤醒灵敏度

设备的唤醒灵敏度用于通过以下方式节省电池电量:缩短设备可感应活动的范围,以及在检测到活动后延长唤醒时间。

在 Home API 中,可以使用设备 transportOptionstriggerOptionsmotionSensitivity 属性来设置此值。这些选项在每个设备的 PushAvStreamTransport 特征中定义。

唤醒灵敏度只能设置为以下值:

  • 1 = 低
  • 5 = 中等
  • 10 = 高

更新过程如下:使用 findTransport 命令查找有效录制流的传输配置,然后使用 modifyPushTransport 命令修改配置,使其包含新的灵敏度值:

// Create a struct with the new wake-up sensitivity
val toUpdate =  TransportOptionsStruct(
  triggerOptions =
    TransportTriggerOptionsStruct(
      motionSensitivity =
        OptionalValue.present(wakeUpSensitivity.toUByte())
    )
  )

// Get the configurations for active connections
val connections  = pushAvStreamTransport.findTransport().transportConfigurations
  // Update all recording streams with the new transport options.
  for (connection in connections) {
    if (connection.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording) {
      trait.modifyPushTransport(
        connectionId = connection.connectionId,
        transportOptions = toUpdate,
      )
    }
  }

调整事件录制时长上限

事件时长上限是指摄像头为事件录制片段的时长。通过 Home API,您可以按设备将此参数配置为与通过 GHA 配置的长度相同的长度(以秒为单位),

  • 10 秒
  • 15 秒
  • 30 秒
  • 60 秒(1 分钟)
  • 120 秒(2 分钟)
  • 180 秒(3 分钟)

在 Home API 中,可以使用设备 transportOptionstriggerOptionsmotionTimeControl 属性来设置此值。这些选项在每个设备的 PushAvStreamTransport 特征中定义。

更新过程如下:使用 findTransport 命令查找有效录制流的传输配置,然后使用 modifyPushTransport 命令修改配置,使其包含新的活动时长值:

// Create a struct with the new max event length
// where maxDuration is the length in seconds
val toUpdate =  TransportOptionsStruct(
  triggerOptions =
    TransportTriggerOptionsStruct(
      motionTimeControl =
        OptionalValue.present(
          TransportMotionTriggerTimeControlStruct(maxDuration = it.toUInt())
        )
    )
  )

// Get the configurations for active connections
val connections  = pushAvStreamTransport.findTransport().transportConfigurations
  // Update all recording streams with the new transport options.
  for (connection in connections) {
    if (connection.transportOptions.getOrNull()?.streamUsage == StreamUsageEnum.Recording) {
      trait.modifyPushTransport(
        connectionId = connection.connectionId,
        transportOptions = toUpdate,
      )
    }
  }