camera-streaming

Configuración de capacidad de sesión y transmisión, fotogramas de video, captura de fotos, configuración de resolución y velocidad de fotogramas

npx skills add https://github.com/facebook/meta-wearables-dat-android --skill camera-streaming

Camera Streaming (Android)

Use a DeviceSession and an attached Camera to receive frames and capture photos through camera.stream.

For PCM audio delivered with this stream, use the audio-streaming skill.

Key concepts

  • DeviceSession: Device connection lifecycle created through Wearables.createSession(...)
  • Camera: Camera capability attached to a session with session.addCamera(...)
  • Stream: Video stream accessed through camera.stream
  • StreamConfiguration: Video quality, frame rate, and compression configuration for the stream
  • PhotoData: Still image captured from glasses while streaming

Create a session and attach a stream

DeviceSession.start() is fire-and-forget: it returns Unit and the connection completes in the background. A capability can only be added once the session reports DeviceSessionState.STARTED — calling addCamera(...) right after start() fails with DeviceSessionError.SESSION_IDLE. Add the camera from the session-state collector.

import com.meta.wearable.dat.camera.Camera
import com.meta.wearable.dat.camera.addCamera
import com.meta.wearable.dat.camera.types.StreamConfiguration
import com.meta.wearable.dat.camera.types.VideoQuality
import com.meta.wearable.dat.core.Wearables
import com.meta.wearable.dat.core.selectors.AutoDeviceSelector
import com.meta.wearable.dat.core.session.DeviceSessionState

var camera: Camera? = null

Wearables.createSession(AutoDeviceSelector()).fold(
    onSuccess = { session ->
        lifecycleScope.launch {
            session.errors.collect { error -> showError(error.description) }
        }
        lifecycleScope.launch {
            session.state.collect { state ->
                if (state == DeviceSessionState.STARTED && camera == null) {
                    session.addCamera(
                        StreamConfiguration(
                            videoQuality = VideoQuality.MEDIUM,
                            frameRate = 24,
                        ),
                    ).fold(
                        onSuccess = { addedCamera ->
                            camera = addedCamera
                            addedCamera.stream.start().onFailure { error, _ ->
                                showError(error.description)
                            }
                        },
                        onFailure = { error, _ -> showError(error.description) },
                    )
                }
            }
        }
        // Subscribe before start() so no initial transition is missed.
        session.start()
    },
    onFailure = { error, _ -> showError(error.description) },
)

Check Wearables.checkPermissionStatus(Permission.CAMERA) before starting the stream; see the permissions-registration skill.

Resolution options

QualitySize
VideoQuality.HIGH720 x 1280
VideoQuality.MEDIUM504 x 896
VideoQuality.LOW360 x 640

Frame rate options

Valid values: 2, 7, 15, 24, 30 FPS.

Lower resolution and frame rate usually produce better visual quality per frame over Bluetooth.

Observe stream state

StreamState transitions: STOPPED -> STARTING -> STARTED -> STREAMING -> STOPPING -> STOPPED, and CLOSED once the stream is terminal. PAUSED is reported when the device pauses the stream, for example on a single cap-touch tap; the stream can resume on its own from PAUSED.

lifecycleScope.launch {
    camera.stream.state.collect { state ->
        when (state) {
            StreamState.STREAMING -> {
                // Frames are flowing
            }
            StreamState.PAUSED -> {
                // Paused by the device; wait for it to resume
            }
            StreamState.STOPPED -> {
                // Streaming ended
            }
            StreamState.CLOSED -> {
                // Stream fully closed
            }
            else -> Unit
        }
    }
}

Observe camera.stream.errorStream alongside the state. StreamError.STREAM_ERROR is informational and does not stop the stream, while StreamError.CRITICAL_STREAM_ERROR means the stream should be torn down.

lifecycleScope.launch {
    camera.stream.errorStream.collect { error ->
        showStreamError(error.description)
    }
}

Receive frames

lifecycleScope.launch {
    camera.stream.videoStream.collect { frame ->
        updatePreview(frame)
    }
}

By default the SDK decodes on the phone and VideoFrame.buffer holds YUV pixel data. Set StreamConfiguration(compressVideo = true) to receive compressed HEVC buffers instead; then check frame.isCompressed and frame.isCodecConfig and feed the frames to your own decoder. Keep frame handling off the main thread for anything heavier than a buffer copy.

In-stream photo capture

This path captures while video streaming remains active. For standalone high-quality capture with resolution, quality, transfer progress, and its own lifecycle, use the camera-capture skill.

capturePhoto() only succeeds while the stream is active, and returns a PhotoData sealed type — branch on the variant instead of reading a single data property.

import com.meta.wearable.dat.camera.types.PhotoData

lifecycleScope.launch {
    camera.stream.capturePhoto()
        .onSuccess { photoData ->
            when (photoData) {
                is PhotoData.Bitmap -> savePhoto(photoData.bitmap)
                is PhotoData.HEIC -> saveHeic(photoData.data) // ByteBuffer of HEIC bytes
            }
        }
        .onFailure { error, _ ->
            showCaptureError(error.description)
        }
}

Only one capture can be in flight at a time; a second concurrent call fails with CaptureError.CaptureInProgress.

Clean up

Stop the camera when you no longer need camera data, then stop the parent session if the device interaction is finished. Stopping the camera cascades to its stream, and stopping the session cascades to every attached capability.

camera.stop()
session.stop()

Camera.stop() and Stream.stop() invalidate the instance — they cannot be restarted. Call session.removeCamera() to detach the capability so a later session.addCamera(...) on the same session can succeed.

Links

Más skills de facebook

gc-safe-coding
facebook
Para la explicación completa y el fundamento, consulta doc/GCSafeCoding.md.
app-review-prep
facebook
Prepara una app de Meta para App Review: comprueba el estado actual, los requisitos pendientes, los privilegios concedidos y el historial de envíos. Úsalo antes de enviar una app…
api-health
facebook
Monitorea la salud de la API para una app de Meta: verifica límites de tasa, volumen de llamadas y deprecaciones de API. Úsalo para diagnosticar limitaciones, planificar capacidad o prepararse para versiones de API…
debug-webhooks
facebook
Soluciona problemas de webhooks para una aplicación de Meta — inspecciona las suscripciones activas, identifica configuraciones incorrectas y envía cargas de prueba para verificar la entrega. Usa cuando…
api-integration
facebook
Guía a un desarrollador para configurar una integración de la API de Meta desde cero: descubre las APIs adecuadas, obtiene guías de configuración, requisitos de autenticación,…
webhook-setup
facebook
Configura webhooks para una app de Meta de principio a fin: descubre los temas disponibles, suscríbete a campos y verifica con una carga de prueba. Úsalo al configurar webhooks para…
test-ui
facebook
Prueba el sistema de UI (PanelUI, ScreenSpace) contra el ejemplo de poke usando la CLI de iwsdk.
flags
facebook
We need to translate the given text from English to Spanish. The text describes a skill for inspecting and comparing feature flag states across React release channels. We must preserve product names, protocol names, URLs, numbers, and technical terms. The name "flags" is not in the text, so we don't include it. We translate only the text inside <text>. No extra commentary, labels, etc. The text: "Inspect and compare feature flag states across React release channels. View all flags across channels (www, www-modern, canary, next, experimental, rn variants) or compare specific channels with --diff Output formats include default table view, CSV export, and cleanup status grouping Flag states indicated by symbols: enabled (✅), disabled (❌), variant testing (🧪), profiling-only (📊) Common pitfall: __VARIANT__ flags are tested in both states on www; use --diff to spot meaningful..." We need to translate to Spanish. Keep technical terms like "React", "www", "www-modern", "canary",