Home AssistantHome AssistantContributors
On this page

A camera entity serves images from a camera: a still image on request, and, if the camera can, a live video stream. It is what powers the camera feeds on dashboards, the snapshots in notifications, and the recordings made with the camera.record action.

Inherit from Camera, imported from homeassistant.components.camera. Use it for anything that shows a live or near-live picture. If your device only has a still image that changes now and then, like a map or a QR code, the image entity is simpler.

Properties

These properties are specific to camera entities. The generic properties every entity has are on the entity class.

Name Type Default Description
brand str | None None The brand of the camera.
model str | None None The model of the camera.
frame_interval float 0.5 Seconds between frames of the MJPEG stream that Home Assistant builds from still images.
is_on bool True Whether the camera is on. When it is off, image requests fail with a "service unavailable" response.
is_recording bool False Whether the camera is recording. Sets the state.
is_streaming bool False Whether the camera is streaming. Sets the state.
motion_detection_enabled bool False Whether motion detection is on.
use_stream_for_stills bool False Take still images from the stream instead of calling async_camera_image. Only a property: there is no _attr_ for it.
content_type str "image/jpeg" The MIME type of the images you return. A plain instance attribute set in __init__, not a property.
stream_options dict {} Options passed to the stream integration when it opens your stream source. A plain instance attribute.

Cameras do not poll by default (should_poll is False). When you override __init__, call super().__init__(): it sets up the access tokens, the stream, and the WebRTC bookkeeping.

Supported features

Combine the flags of CameraEntityFeature with the bitwise or (|) operator.

Flag Description
ON_OFF The camera can be turned on and off. Implement turn_on and turn_off.
STREAM The camera has a live stream. Implement stream_source for HLS, or the native WebRTC methods.

Still images

Every camera returns still images through async_camera_image (or camera_image). The frontend calls it for thumbnails and dashboards, and the camera.snapshot action saves its result to disk.

The frontend can ask for a width and a height. Scaling is best effort:

  • If your camera can scale, pass the size on and return the smallest image that is at least that large.
  • Keep the aspect ratio. When it does not match, the returned image can be wider or taller than asked.
  • If you cannot scale and return a JPEG, Home Assistant scales it for you.

If the camera has a stream and no separate snapshot endpoint, set use_stream_for_stills to True, and Home Assistant grabs stills from the stream. Another common way is to pass the stream source to async_get_image of the FFmpeg integration (homeassistant.components.ffmpeg), which grabs a frame from it.

Streams

A camera with CameraEntityFeature.STREAM offers a live stream in one of two ways. The frontend picks a player based on what the camera offers.

HLS through the stream integration

Implement stream_source and return a URL that FFmpeg can open, usually an RTSP URL. Home Assistant's stream integration turns it into HLS for the frontend, and uses it for camera.record and camera.play_stream too.

When another integration has registered a WebRTC provider that can handle your stream source, like the go2rtc integration, the frontend also gets WebRTC for your camera. You do not have to do anything for that.

Native WebRTC

If your camera or cloud speaks WebRTC itself, implement these methods instead:

  • async_handle_async_webrtc_offer(offer_sdp, session_id, send_message): start a session for the SDP offer of the frontend. Send the answer, candidates, and errors back with the send_message callback, as WebRTCAnswer, WebRTCCandidate, and WebRTCError.
  • async_on_webrtc_candidate(session_id, candidate): handle an ICE candidate that the frontend sends after the offer. Required when you implement the offer method.
  • close_webrtc_session(session_id): optional. Clean up when the frontend closes the stream.

Once you override async_handle_async_webrtc_offer, the frontend uses WebRTC only and never falls back to HLS. Native WebRTC streams do not go through the stream integration, so recording is not available. To pass extra settings to the WebRTC client, like a data channel, override _async_get_webrtc_client_configuration and return a WebRTCClientConfiguration.

WebRTC providers

An integration can also offer WebRTC for cameras of other integrations, based on their stream source. Implement CameraWebRTCProvider and register it with async_register_webrtc_provider(hass, provider). The provider tells Home Assistant which stream sources it supports with async_is_supported, and handles the offers and candidates for those cameras. This is how go2rtc works, and you will rarely need it.

Methods

Each method has a sync and an async variant. Implement one of them.

Method Sync variant Description
async_camera_image(width=None, height=None) camera_image Return the bytes of a still image, or None.
stream_source() none Async only. Return the stream URL, or None. Needs STREAM.
async_turn_on() turn_on Turn the camera on. Needs ON_OFF.
async_turn_off() turn_off Turn the camera off. Needs ON_OFF.
async_enable_motion_detection() enable_motion_detection Turn motion detection on.
async_disable_motion_detection() disable_motion_detection Turn motion detection off.
handle_async_mjpeg_stream(request) none Optional. Proxy an MJPEG stream from the camera directly. By default, Home Assistant builds one from still images every frame_interval seconds.

The native WebRTC methods are listed in Native WebRTC.

States

The state is final, and comes from is_recording and is_streaming, in that order. The values are in the CameraState enum.

State When
recording is_recording is True.
streaming is_streaming is True, and the camera is not recording.
idle Neither.

The camera adds access_token, and, when set, model_name, brand, and motion_detection as attributes. The access token and the entity picture are excluded from the recorder, because the tokens rotate every five minutes.

Example

A network camera with an RTSP stream and a snapshot URL.

Python
from homeassistant.components.camera import Camera, CameraEntityFeature


class MyCamera(Camera):
    """A network camera."""

    _attr_has_entity_name = True
    _attr_name = None
    _attr_supported_features = CameraEntityFeature.STREAM

    def __init__(self, device: MyDevice) -> None:
        """Initialize the camera."""
        super().__init__()
        self._device = device
        self._attr_unique_id = device.serial
        self._attr_brand = "Example"
        self._attr_model = device.model

    async def async_camera_image(
        self, width: int | None = None, height: int | None = None
    ) -> bytes | None:
        """Return a snapshot."""
        return await self._device.snapshot(width=width, height=height)

    async def stream_source(self) -> str | None:
        """Return the RTSP URL of the main stream."""
        return self._device.rtsp_url
Was this page helpful?

Last updated on .