From 7455d950b13740e1e06c2fe9c45a0f8163eb17be Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Mon, 4 Feb 2019 09:57:22 -0800 Subject: [PATCH] Fix ffmpeg v4 stream issue (#20314) * Add ffmpeg version * Add ffmpeg stream content type * Change ffmpeg camera stream content type * Change ffmpeg stream content type * Lint * Add a none guard * Fix * Fix * Update onvif.py * Fix version match regrex * Fix regrex * Upgrade ha-ffmpeg to 1.11 * Lint * Get ffmpeg version in ffmpeg component setup --- homeassistant/components/amcrest/camera.py | 2 +- homeassistant/components/arlo/camera.py | 2 +- homeassistant/components/camera/canary.py | 2 +- homeassistant/components/camera/ffmpeg.py | 2 +- homeassistant/components/camera/onvif.py | 5 ++-- homeassistant/components/camera/ring.py | 2 +- homeassistant/components/camera/xiaomi.py | 2 +- homeassistant/components/camera/yi.py | 2 +- homeassistant/components/ffmpeg.py | 30 +++++++++++++++++++++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 11 files changed, 41 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/amcrest/camera.py b/homeassistant/components/amcrest/camera.py index 4ba527b4805..3b3368c2f5c 100644 --- a/homeassistant/components/amcrest/camera.py +++ b/homeassistant/components/amcrest/camera.py @@ -82,7 +82,7 @@ class AmcrestCam(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._ffmpeg.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/arlo/camera.py b/homeassistant/components/arlo/camera.py index d56616218e7..7857995b4af 100644 --- a/homeassistant/components/arlo/camera.py +++ b/homeassistant/components/arlo/camera.py @@ -104,7 +104,7 @@ class ArloCam(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._ffmpeg.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/canary.py b/homeassistant/components/camera/canary.py index 7a83e2da4d1..eb0c8f3fc6d 100644 --- a/homeassistant/components/camera/canary.py +++ b/homeassistant/components/camera/canary.py @@ -101,7 +101,7 @@ class CanaryCamera(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._ffmpeg.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/ffmpeg.py b/homeassistant/components/camera/ffmpeg.py index 6bd68b05bb5..db9e73f3e1b 100644 --- a/homeassistant/components/camera/ffmpeg.py +++ b/homeassistant/components/camera/ffmpeg.py @@ -68,7 +68,7 @@ class FFmpegCamera(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._manager.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/onvif.py b/homeassistant/components/camera/onvif.py index d1afd39ca7b..da0bae7c50b 100644 --- a/homeassistant/components/camera/onvif.py +++ b/homeassistant/components/camera/onvif.py @@ -213,7 +213,8 @@ class ONVIFHassCamera(Camera): if not self._input: return None - stream = CameraMjpeg(self.hass.data[DATA_FFMPEG].binary, + ffmpeg_manager = self.hass.data[DATA_FFMPEG] + stream = CameraMjpeg(ffmpeg_manager.binary, loop=self.hass.loop) await stream.open_camera( self._input, extra_cmd=self._ffmpeg_arguments) @@ -221,7 +222,7 @@ class ONVIFHassCamera(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + ffmpeg_manager.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/ring.py b/homeassistant/components/camera/ring.py index ad351fb59cf..da1119281b3 100644 --- a/homeassistant/components/camera/ring.py +++ b/homeassistant/components/camera/ring.py @@ -142,7 +142,7 @@ class RingCam(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._ffmpeg.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/xiaomi.py b/homeassistant/components/camera/xiaomi.py index 207dd17ed9b..93e9dd4a07c 100644 --- a/homeassistant/components/camera/xiaomi.py +++ b/homeassistant/components/camera/xiaomi.py @@ -161,6 +161,6 @@ class XiaomiCamera(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._manager.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/camera/yi.py b/homeassistant/components/camera/yi.py index 8b5b865ee57..7d731d2a433 100644 --- a/homeassistant/components/camera/yi.py +++ b/homeassistant/components/camera/yi.py @@ -147,6 +147,6 @@ class YiCamera(Camera): try: return await async_aiohttp_proxy_stream( self.hass, request, stream, - 'multipart/x-mixed-replace;boundary=ffserver') + self._manager.ffmpeg_stream_content_type) finally: await stream.close() diff --git a/homeassistant/components/ffmpeg.py b/homeassistant/components/ffmpeg.py index a2f0ca19231..3184b5a5d54 100644 --- a/homeassistant/components/ffmpeg.py +++ b/homeassistant/components/ffmpeg.py @@ -5,6 +5,7 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/ffmpeg/ """ import logging +import re import voluptuous as vol @@ -16,7 +17,7 @@ from homeassistant.helpers.dispatcher import ( import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['ha-ffmpeg==1.9'] +REQUIREMENTS = ['ha-ffmpeg==1.11'] DOMAIN = 'ffmpeg' @@ -60,6 +61,8 @@ async def async_setup(hass, config): conf.get(CONF_FFMPEG_BIN, DEFAULT_BINARY) ) + await manager.async_get_version() + # Register service async def async_service_handle(service): """Handle service ffmpeg process.""" @@ -96,12 +99,37 @@ class FFmpegManager: self.hass = hass self._cache = {} self._bin = ffmpeg_bin + self._version = None + self._major_version = None @property def binary(self): """Return ffmpeg binary from config.""" return self._bin + async def async_get_version(self): + """Return ffmpeg version.""" + from haffmpeg.tools import FFVersion + + ffversion = FFVersion(self._bin, self.hass.loop) + self._version = await ffversion.get_version() + + self._major_version = None + if self._version is not None: + result = re.search(r"(\d+)\.", self._version) + if result is not None: + self._major_version = int(result.group(1)) + + return self._version, self._major_version + + @property + def ffmpeg_stream_content_type(self): + """Return HTTP content type for ffmpeg stream.""" + if self._major_version is not None and self._major_version > 3: + return 'multipart/x-mixed-replace;boundary=ffmpeg' + + return 'multipart/x-mixed-replace;boundary=ffserver' + class FFmpegBase(Entity): """Interface object for FFmpeg.""" diff --git a/requirements_all.txt b/requirements_all.txt index 4ce0ae263aa..f8085401d98 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -487,7 +487,7 @@ greenwavereality==0.5.1 gstreamer-player==1.1.2 # homeassistant.components.ffmpeg -ha-ffmpeg==1.9 +ha-ffmpeg==1.11 # homeassistant.components.media_player.philips_js ha-philipsjs==0.0.5 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index deee1efca3f..3ec1c7d35fa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -101,7 +101,7 @@ geojson_client==0.3 georss_client==0.5 # homeassistant.components.ffmpeg -ha-ffmpeg==1.9 +ha-ffmpeg==1.11 # homeassistant.components.hangouts hangups==0.4.6