Reduce idle timeout of HLS stream to conserve camera battery life (#147728)

* Reduce IDLE timeout of HLS stream to conserve camera battery life

* adjust tests
This commit is contained in:
starkillerOG 2025-06-28 22:20:47 +02:00 committed by Paulus Schoutsen
parent 81e712ea49
commit 33e1c6de68
4 changed files with 17 additions and 10 deletions

View File

@ -55,6 +55,7 @@ from .const import (
MAX_SEGMENTS,
OUTPUT_FORMATS,
OUTPUT_IDLE_TIMEOUT,
OUTPUT_STARTUP_TIMEOUT,
RECORDER_PROVIDER,
RTSP_TRANSPORTS,
SEGMENT_DURATION_ADJUSTER,
@ -363,11 +364,14 @@ class Stream:
# without concern about self._outputs being modified from another thread.
return MappingProxyType(self._outputs.copy())
def add_provider(
self, fmt: str, timeout: int = OUTPUT_IDLE_TIMEOUT
) -> StreamOutput:
def add_provider(self, fmt: str, timeout: int | None = None) -> StreamOutput:
"""Add provider output stream."""
if not (provider := self._outputs.get(fmt)):
startup_timeout = OUTPUT_STARTUP_TIMEOUT
if timeout is None:
timeout = OUTPUT_IDLE_TIMEOUT
else:
startup_timeout = timeout
async def idle_callback() -> None:
if (
@ -379,7 +383,7 @@ class Stream:
provider = PROVIDERS[fmt](
self.hass,
IdleTimer(self.hass, timeout, idle_callback),
IdleTimer(self.hass, timeout, idle_callback, startup_timeout),
self._stream_settings,
self.dynamic_stream_settings,
)

View File

@ -22,7 +22,8 @@ AUDIO_CODECS = {"aac", "mp3"}
FORMAT_CONTENT_TYPE = {HLS_PROVIDER: "application/vnd.apple.mpegurl"}
OUTPUT_IDLE_TIMEOUT = 300 # Idle timeout due to inactivity
OUTPUT_STARTUP_TIMEOUT = 60 # timeout due to no startup
OUTPUT_IDLE_TIMEOUT = 30 # Idle timeout due to inactivity
NUM_PLAYLIST_SEGMENTS = 3 # Number of segments to use in HLS playlist
MAX_SEGMENTS = 5 # Max number of segments to keep around

View File

@ -234,10 +234,12 @@ class IdleTimer:
hass: HomeAssistant,
timeout: int,
idle_callback: Callable[[], Coroutine[Any, Any, None]],
startup_timeout: int | None = None,
) -> None:
"""Initialize IdleTimer."""
self._hass = hass
self._timeout = timeout
self._startup_timeout = startup_timeout or timeout
self._callback = idle_callback
self._unsub: CALLBACK_TYPE | None = None
self.idle = False
@ -246,7 +248,7 @@ class IdleTimer:
"""Start the idle timer if not already started."""
self.idle = False
if self._unsub is None:
self._unsub = async_call_later(self._hass, self._timeout, self.fire)
self._unsub = async_call_later(self._hass, self._startup_timeout, self.fire)
def awake(self) -> None:
"""Keep the idle time alive by resetting the timeout."""

View File

@ -230,8 +230,8 @@ async def test_stream_timeout(
playlist_response = await http_client.get(parsed_url.path)
assert playlist_response.status == HTTPStatus.OK
# Wait a minute
future = dt_util.utcnow() + timedelta(minutes=1)
# Wait 40 seconds
future = dt_util.utcnow() + timedelta(seconds=40)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()
@ -241,8 +241,8 @@ async def test_stream_timeout(
stream_worker_sync.resume()
# Wait 5 minutes
future = dt_util.utcnow() + timedelta(minutes=5)
# Wait 2 minutes
future = dt_util.utcnow() + timedelta(minutes=2)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()