From 5e6217f20ce90f952a647ea9bd446f00026f6168 Mon Sep 17 00:00:00 2001 From: uvjustin <46082645+uvjustin@users.noreply.github.com> Date: Wed, 27 Jul 2022 14:13:38 +0800 Subject: [PATCH] Use executor to finish stream recording (#75776) --- homeassistant/components/stream/recorder.py | 44 +++++++++++++-------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/stream/recorder.py b/homeassistant/components/stream/recorder.py index 42b98946c15a..3bda8acfa7b6 100644 --- a/homeassistant/components/stream/recorder.py +++ b/homeassistant/components/stream/recorder.py @@ -4,6 +4,7 @@ from __future__ import annotations from io import BytesIO import logging import os +from typing import TYPE_CHECKING import av @@ -16,6 +17,9 @@ from .const import ( ) from .core import PROVIDERS, IdleTimer, Segment, StreamOutput, StreamSettings +if TYPE_CHECKING: + import deque + _LOGGER = logging.getLogger(__name__) @@ -139,6 +143,25 @@ class RecorderOutput(StreamOutput): source.close() + def finish_writing( + segments: deque[Segment], output: av.OutputContainer, video_path: str + ) -> None: + """Finish writing output.""" + # Should only have 0 or 1 segments, but loop through just in case + while segments: + write_segment(segments.popleft()) + if output is None: + _LOGGER.error("Recording failed to capture anything") + return + output.close() + try: + os.rename(video_path + ".tmp", video_path) + except FileNotFoundError: + _LOGGER.error( + "Error writing to '%s'. There are likely multiple recordings writing to the same file", + video_path, + ) + # Write lookback segments while len(self._segments) > 1: # The last segment is in progress await self._hass.async_add_executor_job( @@ -153,20 +176,7 @@ class RecorderOutput(StreamOutput): await self._hass.async_add_executor_job( write_segment, self._segments.popleft() ) - # Write remaining segments - # Should only have 0 or 1 segments, but loop through just in case - while self._segments: - await self._hass.async_add_executor_job( - write_segment, self._segments.popleft() - ) - if output is None: - _LOGGER.error("Recording failed to capture anything") - else: - output.close() - try: - os.rename(self.video_path + ".tmp", self.video_path) - except FileNotFoundError: - _LOGGER.error( - "Error writing to '%s'. There are likely multiple recordings writing to the same file", - self.video_path, - ) + # Write remaining segments and close output + await self._hass.async_add_executor_job( + finish_writing, self._segments, output, self.video_path + )