iOS 向けカメラ デバイス ガイド

カメラ デバイスタイプは、2 つのトレイトを使用して実装されます。PushAvStreamTransportTrait は、プッシュベースのプロトコルを使用して音声と動画のストリーム転送を処理します。WebRtcLiveViewTrait は、ライブ ストリームとトークバックを制御する機能を提供します。

機能を使用したり、属性を更新しようとしたりする前に、デバイスの属性とコマンドのサポートを必ず確認してください。詳しくは、iOSでデバイスを制御するをご覧ください。

Google Home の API のデバイスタイプ トレイト Swift サンプルアプリ ユースケース

カメラ

GoogleCameraDeviceType

home.matter.6006.types.0158

静止画像や動画をキャプチャするデバイス。カメラには、アクセス可能なライブ配信、双方向通話、アクティビティの検出などの機能が搭載されている場合があります。

必須のトレイト
     google PushAvStreamTransportTrait
     google WebRtcLiveViewTrait

カメラ

ライブ配信を開始する

ライブ配信を開始するには、セッション記述プロトコル(SDP)文字列を WebRtcLiveViewTrait トレイトの startLiveView(offerSdp:) メソッドに送信します。このメソッドは次の 3 つの値を返します。

  • セッションの SDP。
  • セッションの長さ(秒数)。
  • セッションの延長または終了に使用されるセッション ID。
public func sendOffer(offerSdp: String) async throws
-> (answerSdp: String, mediaSessionId: String, liveViewDuration: TimeInterval)
{
  do {
    // Sending StartLiveView command
    let response = try await liveViewTrait.startLiveView(
      offerSdp: offerSdp
    )
    // Received StartLiveView response
    return (
      answerSdp: response.answerSdp,
      mediaSessionId: response.mediaSessionId,
      liveViewDuration: TimeInterval(response.liveSessionDurationSeconds)
    )
  } catch {
    // Failed to send StartLiveView command
    throw error
  }
}

ライブ配信を延長する

ライブ配信には、期限切れになるまでの期間が事前に設定されています。アクティブなストリームの期間を延長するには、extendLiveView(mediaSessionId:optionalArgsProvider:) メソッドを使用して延長リクエストを発行します。

public func extendLiveView(mediaSessionId: String) async throws {
  do {
    // Extending live view
    let extendedDuration = try await liveViewTrait.extendLiveView(mediaSessionId: mediaSessionId)
  } catch {
    // Failed to extend live view
    throw error
  }
}

TalkBack の開始と停止

TalkBack を開始するには、WebRtcLiveViewTrait トレイトの startTalkback(mediaSessionId:optionalArgsProvider:) メソッドを呼び出します。停止するには、stopTalkback(mediaSessionId:) を使用します。

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

録画機能を有効または無効にする

カメラの録画機能を有効にするには、PushAvStreamTransportTrait トレイトの setTransportStatus(transportStatus:optionalArgsProvider:) メソッドに TransportStatusEnum.Active を渡します。録画機能を無効にするには、TransportStatusEnum.Inactive を渡します。次の例では、これらの呼び出しを 1 つの呼び出しでラップし、Boolean を使用して録音機能を切り替えます。

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

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

カメラの録画機能を有効または無効にすることは、カメラの動画のオンとオフを切り替えることと同じです。カメラの動画がオンになっている場合、イベントと関連するクリップの目的で録画が行われます。

録画機能が無効になっている場合(カメラの動画がオフの場合):

  • カメラは、デバイスタイプの connectivityState に従ってオンラインとして表示されることがあります。
  • ライブ ストリームにアクセスできず、カメラでクラウド イベントも検出されません。

録画機能が有効になっているかどうかを確認する

カメラの録画機能が有効になっているかどうかを確認するには、接続がアクティブかどうかを確認します。次の例では、これを行う 2 つの関数を定義しています。

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

音声設定

さまざまなカメラの音声設定は、Home API を介して制御できます。

マイクのオンとオフを切り替える

デバイスのマイクのオンとオフを切り替えるには、組み込みの setMicrophoneMuted 関数を使用して CameraAvStreamManagementTrait トレイトの microphoneMuted 属性を更新します。

// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

録音のオンとオフを切り替える

デバイスの録音のオンとオフを切り替えるには、組み込みの setRecordingMicrophoneMuted 関数を使用して、CameraAvStreamManagementTrait トレイトの recordingMicrophoneMuted 属性を更新します。

// Turn audio recording on or off for the device
func setAudioRecording(on: Bool) async {
  do {
    _ = try await self.cameraAvStreamManagementTrait?.update {
      $0.setRecordingMicrophoneMuted(!on)
    }
  } catch {
    // Error
  }
}

スピーカーの音量を調整する

デバイスのスピーカー音量を調整するには、組み込みの setSpeakerVolumeLevel 関数を使用して、CameraAvStreamManagementTrait トレイトの speakerVolumeLevel 属性を更新します。

// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setSpeakerVolumeLevel(value)
    }
  } catch {
    // Error
  }
}

その他の設定

その他のさまざまなカメラ設定は、Home API を通じて制御できます。

画像の向きを変更する

カメラ画像(動画)の向きを回転させることができます。動画は 180 度のみ回転できます。

カメラの画像の向きを変更するには、組み込みの setImageRotation 関数を使用して、CameraAvStreamManagementTrait トレイトの imageRotation 属性を更新します。

// Change the camera's image orientation
// Value must be 0 or 180
func setImageRotation(to value: UInt16) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setImageRotation(value)
    }
  } catch {
    // Error
  }
}

ナイトビジョン機能をオンまたはオフにする

カメラのナイト ビジョンをオンまたはオフにするには、TriStateAutoEnum を使用して、組み込みの setNightVision 関数を使用して CameraAvStreamManagementTrait トレイトの nightVision 属性を更新します。

// Turn night vision on or off
func setNightVision(
  to value: Google.CameraAvStreamManagementTrait.TriStateAutoEnum
) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setNightVision(value)
    }
  } catch {
    // Error
  }
}

ステータス LED の明るさを変更する

ステータス LED の明るさを変更するには、ThreeLevelAutoEnum を使用して、組み込みの setStatusLightBrightness 関数を使用して CameraAvStreamManagementTrait トレイトの statusLightBrightness 属性を更新します。

// Set the LED brightness
func setStatusLightBrightness(
  to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
  do {
    _ = try await cameraAvStreamManagementTrait.update {
      $0.setStatusLightBrightness(value)
    }
  } catch {
    // Error
  }
}

カメラのビューポートを変更する

カメラのビューポートは、Google Nest カメラの動画でズーム機能や補正機能を使用するのサポート記事で説明されているズームと切り抜き機能と同じです。

ビューポートは、ビューポートの座標として使用される 4 つの値を含む ViewportStruct で定義されます。座標は次のように定義されます。

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

ViewportStruct の値を決定するには、アプリの UI とカメラの実装に依存します。基本的なレベルでは、カメラ動画のビューポートを設定するには、組み込みの setViewport 関数を使用して、CameraAvStreamManagementTrait トレイトの viewport 属性を ViewportStruct で更新します。

func setCrop(x1: UInt16, y1: UInt16, x2: UInt16, y2: UInt16) {

  let viewport = Google.CameraAvStreamManagementTrait.ViewportStruct(
    x1: x1,
    y1: y1,
    x2: x2,
    y2: y2
  )

  Task {
    do {
      try await cameraAvStreamManagementTrait.update {
        $0.setViewport(viewport)
      }
    } catch {
      // Error
    }
  }

}

TransportOptionsStruct を生成する

一部の設定では、TransportOptionsStruct のプロパティを変更する必要があります。このプロパティは、ストリーミング接続のトランスポート オプションに渡されます。Swift の場合、この構造体はプロパティを更新する前に生成する必要があります。

このヘルパー関数を使用して、次の設定変更で使用する構造体を生成します。

func getTransportOptions(
  transportOptions: Google.PushAvStreamTransportTrait.TransportOptionsStruct,
  wakeUpSensitivity: UInt8?,
  maxEventLength: UInt32?
) async throws
  -> Google.PushAvStreamTransportTrait.TransportOptionsStruct
{

  var newMotionTimeControl:
    Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct? = nil
  if let maxEventLength {
    guard let motionTimeControl = transportOptions.triggerOptions.motionTimeControl else {
      throw HomeError.failedPrecondition(
        // Error - cannot update max event length without motion time control
    }
    newMotionTimeControl =
      Google.PushAvStreamTransportTrait.TransportMotionTriggerTimeControlStruct(
        initialDuration: motionTimeControl.initialDuration,
        augmentationDuration: motionTimeControl.augmentationDuration,
        maxDuration: maxEventLength,
        blindDuration: motionTimeControl.blindDuration
      )
  }

  return Google.PushAvStreamTransportTrait.TransportOptionsStruct(
    streamUsage: .recording,
    videoStreamID: nil,
    audioStreamID: nil,
    tlsEndpointID: transportOptions.tlsEndpointID,
    url: transportOptions.url,
    triggerOptions: Google.PushAvStreamTransportTrait.TransportTriggerOptionsStruct(
      triggerType: .motion,
      motionZones: nil,
      motionSensitivity: wakeUpSensitivity,
      motionTimeControl: newMotionTimeControl,
      maxPreRollLen: nil
    ),
    ingestMethod: .cmafIngest,
    containerOptions: Google.PushAvStreamTransportTrait.ContainerOptionsStruct(
      containerType: .cmaf,
      cmafContainerOptions: nil
    ),
    expiryTime: nil
  )
}

private func getRecordingConnection() async throws
  -> Google.PushAvStreamTransportTrait.TransportConfigurationStruct?
{
  guard let pushAvStreamTransportTrait else {
    // Error - PushAvStreamTransport trait not available
    return nil
  }

  let connections = try await pushAvStreamTransportTrait.findTransport().transportConfigurations

  for connection in connections {
    guard let transportOptions = connection.transportOptions,
      transportOptions.streamUsage == .recording
    else {
      continue
    }

    return connection
  }

  return nil
}

デバイスの復帰感度を調整する

デバイスの起動感度は、デバイスがアクティビティを感知できる範囲を狭め、アクティビティを検出してから起動するまでの時間を長くすることで、バッテリーを節約するために使用されます。

Home API では、デバイスの transportOptionstriggerOptionsmotionSensitivity プロパティを使用して設定できます。これらのオプションは、各デバイスの PushAvStreamTransportTrait トレイト内で定義されます。

ウェイクアップ感度は、次の値にのみ設定できます。

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

更新プロセスでは、findTransport コマンドを使用してアクティブな録音ストリームのトランスポート構成を見つけ、modifyPushTransport コマンドを使用して新しい機密性値で構成を変更します。

modifyPushTransport コマンドでは完全な TransportOptionsStruct を渡す必要があるため、まず現在の構成から既存の値をコピーする必要があります。これを行うには、ヘルパー関数の TransportOptionsStruct を生成するをご覧ください。

func setWakeUpSensitivity(to value: UInt8) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionSensitivity != nil else {
      // Error - Motion sensitivity not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: value,
        maxEventLength: nil
      )
    )

  } catch {
    // Error
  }
}

最長アクティビティ時間を調整する

最長アクティビティ時間は、カメラがアクティビティのクリップを録画する時間の長さです。Home API を使用すると、デバイスごとに Google Home app (GHA) と同じ長さで、秒単位で設定できます。

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

Home API では、デバイスの transportOptionstriggerOptionsmotionTimeControl プロパティを使用して設定できます。これらのオプションは、各デバイスの PushAvStreamTransportTrait トレイト内で定義されます。

更新プロセスでは、findTransport コマンドを使用してアクティブな録画ストリームのトランスポート構成を見つけ、modifyPushTransport コマンドを使用して新しいイベントの長さの値で構成を変更します。

modifyPushTransport コマンドでは完全な TransportOptionsStruct を渡す必要があるため、まず現在の構成から既存の値をコピーする必要があります。これを行うには、ヘルパー関数の TransportOptionsStruct を生成するをご覧ください。

func setMaxEventLength(to value: UInt32) async {
  do {
    let connection = try await getRecordingConnection()
    guard let connection,
      let transportOptions = connection.transportOptions
    else {
      // Error - Transport options not available
      return
    }

    guard transportOptions.triggerOptions.motionTimeControl != nil else {
      // Error - Motion time control not available to be updated for this device
      return
    }

    try await pushAvStreamTransportTrait.modifyPushTransport(
      connectionID: connection.connectionID,
      transportOptions: self.getTransportOptions(
        transportOptions: transportOptions,
        wakeUpSensitivity: nil,
        maxEventLength: value
      )
    )

  } catch {
    // Error
  }
}