core/homeassistant/components/ffmpeg/camera.py

89 lines
2.7 KiB
Python
Raw Normal View History

"""Support for Cameras with FFmpeg as decoder."""
import asyncio
import logging
import voluptuous as vol
from haffmpeg.camera import CameraMjpeg
from haffmpeg.tools import ImageFrame, IMAGE_JPEG
2019-07-31 19:25:30 +00:00
from homeassistant.components.camera import PLATFORM_SCHEMA, Camera, SUPPORT_STREAM
from homeassistant.const import CONF_NAME
from homeassistant.helpers.aiohttp_client import async_aiohttp_proxy_stream
import homeassistant.helpers.config_validation as cv
from . import CONF_EXTRA_ARGUMENTS, CONF_INPUT, DATA_FFMPEG
2016-08-27 20:43:33 +00:00
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
DEFAULT_NAME = "FFmpeg"
DEFAULT_ARGUMENTS = "-pred 1"
2016-08-27 20:43:33 +00:00
2019-07-31 19:25:30 +00:00
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_INPUT): cv.string,
vol.Optional(CONF_EXTRA_ARGUMENTS, default=DEFAULT_ARGUMENTS): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
}
)
2019-07-31 19:25:30 +00:00
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up a FFmpeg camera."""
async_add_entities([FFmpegCamera(hass, config)])
class FFmpegCamera(Camera):
"""An implementation of an FFmpeg camera."""
def __init__(self, hass, config):
"""Initialize a FFmpeg camera."""
super().__init__()
self._manager = hass.data[DATA_FFMPEG]
self._name = config.get(CONF_NAME)
self._input = config.get(CONF_INPUT)
self._extra_arguments = config.get(CONF_EXTRA_ARGUMENTS)
@property
def supported_features(self):
"""Return supported features."""
return SUPPORT_STREAM
async def stream_source(self):
"""Return the stream source."""
2019-07-31 19:25:30 +00:00
return self._input.split(" ")[-1]
async def async_camera_image(self):
"""Return a still image response from the camera."""
2019-07-31 19:25:30 +00:00
ffmpeg = ImageFrame(self._manager.binary, loop=self.hass.loop)
2019-07-31 19:25:30 +00:00
image = await asyncio.shield(
ffmpeg.get_image(
self._input, output_format=IMAGE_JPEG, extra_cmd=self._extra_arguments
)
)
return image
async def handle_async_mjpeg_stream(self, request):
"""Generate an HTTP MJPEG stream from the camera."""
stream = CameraMjpeg(self._manager.binary, loop=self.hass.loop)
2019-07-31 19:25:30 +00:00
await stream.open_camera(self._input, extra_cmd=self._extra_arguments)
try:
2019-03-27 06:55:05 +00:00
stream_reader = await stream.get_reader()
return await async_aiohttp_proxy_stream(
2019-07-31 19:25:30 +00:00
self.hass,
request,
stream_reader,
self._manager.ffmpeg_stream_content_type,
)
finally:
await stream.close()
@property
def name(self):
"""Return the name of this camera."""
return self._name