diff --git a/homeassistant/components/skybell/camera.py b/homeassistant/components/skybell/camera.py index f531e67f2d0..499f1f3bfca 100644 --- a/homeassistant/components/skybell/camera.py +++ b/homeassistant/components/skybell/camera.py @@ -1,6 +1,8 @@ """Camera support for the Skybell HD Doorbell.""" from __future__ import annotations +from aiohttp import web +from haffmpeg.camera import CameraMjpeg import voluptuous as vol from homeassistant.components.camera import ( @@ -8,9 +10,11 @@ from homeassistant.components.camera import ( Camera, CameraEntityDescription, ) +from homeassistant.components.ffmpeg import get_ffmpeg_manager from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_MONITORED_CONDITIONS from homeassistant.core import HomeAssistant +from homeassistant.helpers.aiohttp_client import async_aiohttp_proxy_stream import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -46,11 +50,14 @@ async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Skybell switch.""" - async_add_entities( - SkybellCamera(coordinator, description) - for description in CAMERA_TYPES - for coordinator in hass.data[DOMAIN][entry.entry_id] - ) + entities = [] + for description in CAMERA_TYPES: + for coordinator in hass.data[DOMAIN][entry.entry_id]: + if description.key == "avatar": + entities.append(SkybellCamera(coordinator, description)) + else: + entities.append(SkybellActivityCamera(coordinator, description)) + async_add_entities(entities) class SkybellCamera(SkybellEntity, Camera): @@ -70,3 +77,25 @@ class SkybellCamera(SkybellEntity, Camera): ) -> bytes | None: """Get the latest camera image.""" return self._device.images[self.entity_description.key] + + +class SkybellActivityCamera(SkybellCamera): + """A camera implementation for latest Skybell activity.""" + + async def handle_async_mjpeg_stream( + self, request: web.Request + ) -> web.StreamResponse: + """Generate an HTTP MJPEG stream from the latest recorded activity.""" + stream = CameraMjpeg(get_ffmpeg_manager(self.hass).binary) + url = await self.coordinator.device.async_get_activity_video_url() + await stream.open_camera(url, extra_cmd="-r 210") + + try: + return await async_aiohttp_proxy_stream( + self.hass, + request, + await stream.get_reader(), + get_ffmpeg_manager(self.hass).ffmpeg_stream_content_type, + ) + finally: + await stream.close() diff --git a/homeassistant/components/skybell/manifest.json b/homeassistant/components/skybell/manifest.json index 6884fe07df2..c0e66aa5462 100644 --- a/homeassistant/components/skybell/manifest.json +++ b/homeassistant/components/skybell/manifest.json @@ -4,6 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/skybell", "requirements": ["aioskybell==22.6.1"], + "dependencies": ["ffmpeg"], "codeowners": ["@tkdrob"], "iot_class": "cloud_polling", "loggers": ["aioskybell"]