Improve performance of image streams (#112810)

This commit is contained in:
J. Nick Koston 2024-03-09 10:26:48 -10:00 committed by GitHub
parent 2a6de1c335
commit d0d1af8991
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 19 deletions

View file

@ -336,13 +336,12 @@ async def async_get_still_stream(
# given the low frequency of image updates, it is acceptable.
frame.extend(frame)
await response.write(frame)
# Drain to ensure that the latest frame is available to the client
await response.drain()
return True
event = asyncio.Event()
async def image_state_update(_event: Event[EventStateChangedData]) -> None:
@callback
def _async_image_state_update(_event: Event[EventStateChangedData]) -> None:
"""Write image to stream."""
event.set()
@ -350,7 +349,7 @@ async def async_get_still_stream(
remove = async_track_state_change_event(
hass,
image_entity.entity_id,
image_state_update,
_async_image_state_update,
)
try:
while True:

View file

@ -306,22 +306,35 @@ async def test_image_stream(
client = await hass_client()
with patch.object(mock_image, "async_image", return_value=b""):
resp = await client.get("/api/image_proxy_stream/image.test")
assert not resp.closed
assert resp.status == HTTPStatus.OK
close_future = hass.loop.create_future()
original_get_still_stream = image.async_get_still_stream
mock_image.image_last_updated = datetime.datetime.now()
mock_image.async_write_ha_state()
# Two blocks to ensure the frame is written
await hass.async_block_till_done()
await hass.async_block_till_done()
async def _wrap_async_get_still_stream(*args, **kwargs):
result = await original_get_still_stream(*args, **kwargs)
hass.loop.call_soon(close_future.set_result, None)
return result
with patch.object(mock_image, "async_image", return_value=None):
mock_image.image_last_updated = datetime.datetime.now()
mock_image.async_write_ha_state()
# Two blocks to ensure the frame is written
await hass.async_block_till_done()
await hass.async_block_till_done()
with patch(
"homeassistant.components.image.async_get_still_stream",
_wrap_async_get_still_stream,
):
with patch.object(mock_image, "async_image", return_value=b""):
resp = await client.get("/api/image_proxy_stream/image.test")
assert not resp.closed
assert resp.status == HTTPStatus.OK
mock_image.image_last_updated = datetime.datetime.now()
mock_image.async_write_ha_state()
# Two blocks to ensure the frame is written
await hass.async_block_till_done()
await hass.async_block_till_done()
with patch.object(mock_image, "async_image", return_value=None):
mock_image.image_last_updated = datetime.datetime.now()
mock_image.async_write_ha_state()
# Two blocks to ensure the frame is written
await hass.async_block_till_done()
await hass.async_block_till_done()
await close_future
assert resp.closed