Skip to content

Commit

Permalink
Speed up ffmpeg setup (home-assistant#113496)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
bdraco authored Mar 15, 2024
1 parent 1c938f6 commit c69ab42
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 12 deletions.
39 changes: 27 additions & 12 deletions homeassistant/components/ffmpeg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

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
Expand All @@ -24,9 +24,16 @@
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"
Expand All @@ -49,6 +56,12 @@

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(
Expand Down Expand Up @@ -142,26 +155,28 @@ def __init__(self, hass: HomeAssistant, ffmpeg_bin: str) -> None:
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:
Expand Down
38 changes: 38 additions & 0 deletions tests/components/ffmpeg/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
SERVICE_RESTART,
SERVICE_START,
SERVICE_STOP,
get_ffmpeg_manager,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
Expand Down Expand Up @@ -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

0 comments on commit c69ab42

Please sign in to comment.