Speed up ffmpeg setup (#113496)

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* Speed up ffmpeg setup

Only check for old versions of ffmpeg if is_official_image
is False

* adjust

* adjust

* twea

* Update homeassistant/components/ffmpeg/__init__.py

* forgot about the mock in conftest for comps
pull/113540/head
J. Nick Koston 2024-03-15 03:05:42 -10:00 committed by GitHub
parent 1c938f6422
commit c69ab425c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 12 deletions

View File

@ -4,7 +4,7 @@ from __future__ import annotations
import asyncio
import re
from typing import Generic, TypeVar
from typing import TYPE_CHECKING, Generic, TypeVar
from haffmpeg.core import HAFFmpeg
from haffmpeg.tools import IMAGE_JPEG, FFVersion, ImageFrame
@ -24,9 +24,16 @@ from homeassistant.helpers.dispatcher import (
async_dispatcher_send,
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.system_info import is_official_image
from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import bind_hass
if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property
_HAFFmpegT = TypeVar("_HAFFmpegT", bound=HAFFmpeg)
DOMAIN = "ffmpeg"
@ -49,6 +56,12 @@ CONF_OUTPUT = "output"
DEFAULT_BINARY = "ffmpeg"
# Currently we only care if the version is < 3
# because we use a different content-type
# It is only important to update this version if the
# content-type changes again in the future
OFFICIAL_IMAGE_VERSION = "6.0"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
@ -142,26 +155,28 @@ class FFmpegManager:
self._version: str | None = None
self._major_version: int | None = None
@property
@cached_property
def binary(self) -> str:
"""Return ffmpeg binary from config."""
return self._bin
async def async_get_version(self) -> tuple[str | None, int | None]:
"""Return ffmpeg version."""
ffversion = FFVersion(self._bin)
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))
if self._version is None:
if is_official_image():
self._version = OFFICIAL_IMAGE_VERSION
self._major_version = int(self._version.split(".")[0])
elif (
(version := await FFVersion(self._bin).get_version())
and (result := re.search(r"(\d+)\.", version))
and (major_version := int(result.group(1)))
):
self._version = version
self._major_version = major_version
return self._version, self._major_version
@property
@cached_property
def ffmpeg_stream_content_type(self) -> str:
"""Return HTTP content type for ffmpeg stream."""
if self._major_version is not None and self._major_version > 3:

View File

@ -8,6 +8,7 @@ from homeassistant.components.ffmpeg import (
SERVICE_RESTART,
SERVICE_START,
SERVICE_STOP,
get_ffmpeg_manager,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
@ -251,3 +252,40 @@ async def test_async_get_image_with_extra_cmd_width_height(hass: HomeAssistant)
assert get_image_mock.call_args_list == [
call("rtsp://fake", output_format="mjpeg", extra_cmd="-vf any -s 640x480")
]
async def test_modern_ffmpeg(
hass: HomeAssistant,
) -> None:
"""Test modern ffmpeg uses the new ffmpeg content type."""
with assert_setup_component(1):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
manager = get_ffmpeg_manager(hass)
assert "ffmpeg" in manager.ffmpeg_stream_content_type
async def test_legacy_ffmpeg(
hass: HomeAssistant,
) -> None:
"""Test legacy ffmpeg uses the old ffserver content type."""
with assert_setup_component(1), patch(
"homeassistant.components.ffmpeg.FFVersion.get_version", return_value="3.0"
), patch("homeassistant.components.ffmpeg.is_official_image", return_value=False):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
manager = get_ffmpeg_manager(hass)
assert "ffserver" in manager.ffmpeg_stream_content_type
async def test_ffmpeg_using_official_image(
hass: HomeAssistant,
) -> None:
"""Test ffmpeg using official image is the new ffmpeg content type."""
with assert_setup_component(1), patch(
"homeassistant.components.ffmpeg.is_official_image", return_value=True
):
await async_setup_component(hass, ffmpeg.DOMAIN, {ffmpeg.DOMAIN: {}})
manager = get_ffmpeg_manager(hass)
assert "ffmpeg" in manager.ffmpeg_stream_content_type