Тип устройства «Камера» реализован с использованием двух трейтов: PushAvStreamTransportTrait , который обрабатывает передачу аудио- и видеопотоков с использованием протоколов на основе push-уведомлений, и WebRtcLiveViewTrait , который предоставляет возможность управления прямыми трансляциями и обратной связью.
Перед использованием каких-либо функций или попыткой обновления атрибутов всегда проверяйте поддержку атрибутов и команд для устройства. См. раздел «Управление устройствами» .iOS для получения дополнительной информации.
| Главная API Тип устройства | Черты | Пример приложения на Swift | Вариант использования |
|---|---|---|---|
Камера Устройство, позволяющее делать снимки или записывать видео. Камеры могут иметь функции прямой трансляции, двусторонней связи или обнаружения событий. | Необходимые характеристики Google PushAvStreamTransportTrait google WebRtcLiveViewTrait | Камера |
Начать прямую трансляцию
Для запуска прямой трансляции отправьте строку протокола описания сессии (SDP) методу startLiveView(offerSdp:) трейта WebRtcLiveViewTrait , который возвращает три значения:
- План развития науки и техники для данной сессии.
- Продолжительность сессии в секундах.
- Идентификатор сессии, который может использоваться для продления или завершения сессии.
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
}
}
Запуск и остановка обратной связи
Чтобы запустить обратную связь, вызовите метод startTalkback(mediaSessionId:optionalArgsProvider:) трейта WebRtcLiveViewTrait . Чтобы остановить, используйте 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)")
}
}
Включение и отключение функции записи
Чтобы включить запись с камеры, передайте TransportStatusEnum.Active методу setTransportStatus(transportStatus:optionalArgsProvider:) трейта PushAvStreamTransportTrait . Чтобы отключить запись, передайте TransportStatusEnum.Inactive . В следующем примере мы объединяем эти вызовы в один вызов, использующий 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типа устройства . - Прямая трансляция недоступна, камера также не обнаруживает никаких событий, связанных с облачными сервисами.
Проверьте, включена ли функция записи.
Чтобы определить, включена ли функция записи на камере, проверьте наличие активных подключений. В следующем примере определены две функции для выполнения этой задачи:
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
}
Настройки звука
Различные настройки звука камеры можно контролировать с помощью API Home.
Включение или выключение микрофона
Чтобы включить или выключить микрофон устройства, обновите атрибут microphoneMuted трейта CameraAvStreamManagementTrait , используя встроенную функцию setMicrophoneMuted :
// Turn the device's microphone on or off
func setMicrophone(on: Bool) async {
do {
_ = try await self.cameraAvStreamManagementTrait?.update {
$0.setMicrophoneMuted(!on)
}
} catch {
// Error
}
}
Включение или выключение записи звука
Чтобы включить или выключить запись звука на устройстве, обновите атрибут recordingMicrophoneMuted трейта CameraAvStreamManagementTrait , используя встроенную функцию setRecordingMicrophoneMuted :
// 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
}
}
Отрегулируйте громкость динамиков
Для регулировки громкости динамика устройства обновите атрибут speakerVolumeLevel трейта CameraAvStreamManagementTrait , используя встроенную функцию setSpeakerVolumeLevel :
// Adjust the camera speaker volume
func setSpeakerVolume(to value: UInt8) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setSpeakerVolumeLevel(value)
}
} catch {
// Error
}
}
Другие настройки
Различные другие настройки камеры можно контролировать через API Home.
Изменить ориентацию изображения
Ориентацию изображения с камеры (видео) можно поворачивать. Видео можно повернуть только на 180 градусов.
Чтобы изменить ориентацию изображения с камеры, обновите атрибут imageRotation трейта CameraAvStreamManagementTrait , используя встроенную функцию setImageRotation :
// 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 для обновления атрибута nightVision трейта CameraAvStreamManagementTrait с помощью встроенной функции setNightVision :
// Turn night vision on or off
func setNightVision(
to value: Google.CameraAvStreamManagementTrait.TriStateAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setNightVision(value)
}
} catch {
// Error
}
}
Изменить яркость индикатора состояния
Чтобы изменить яркость светодиода состояния, используйте ThreeLevelAutoEnum для обновления атрибута statusLightBrightness трейта CameraAvStreamManagementTrait с помощью встроенной функции setStatusLightBrightness :
// Set the LED brightness
func setStatusLightBrightness(
to value: Google.CameraAvStreamManagementTrait.ThreeLevelAutoEnum
) async {
do {
_ = try await cameraAvStreamManagementTrait.update {
$0.setStatusLightBrightness(value)
}
} catch {
// Error
}
}
Изменить область просмотра камеры
Окно просмотра камеры идентично функции масштабирования и кадрирования, описанной в статье «Масштабирование и улучшение качества видео с камер Nest» .
Область просмотра определяется в структуре ViewportStruct , которая содержит четыре значения, используемые в качестве координат области просмотра. Координаты определяются следующим образом:
(x1,y1) -- (x2,y1) | | (x1,y2) -- (x2,y2)
Определение значений для ViewportStruct зависит от пользовательского интерфейса приложения и реализации камеры. На самом базовом уровне, чтобы установить область просмотра видео с камеры, обновите атрибут viewport трейта CameraAvStreamManagementTrait , указав ViewportStruct , используя встроенную функцию setViewport .
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
}
Отрегулируйте чувствительность пробуждения устройства.
Чувствительность устройства к пробуждению используется для экономии заряда батареи за счет уменьшения диапазона, в котором устройство может обнаруживать активность, и увеличения времени пробуждения после обнаружения этой активности.
В API Home это можно установить с помощью свойства motionSensitivity объекта triggerOptions в transportOptions устройства. Эти параметры определены в трейте 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
}
}
Отрегулируйте максимальную продолжительность события.
Максимальная продолжительность события — это время, в течение которого камера будет записывать видеоролик для данного события. С помощью API Home это можно настроить для каждого устройства отдельно, установив ту же продолжительность, что и в Google Home app (GHA) , с интервалом в секундах:
- 10 секунд
- 15 секунд
- 30 секунд
- 60 секунд (1 минута)
- 120 секунд (2 минуты)
- 180 секунд (3 минуты)
В API Home это можно установить с помощью свойства motionTimeControl объекта triggerOptions в transportOptions устройства. Эти параметры определены в трейте 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
}
}