Reolink fallback to download command for playback (#145842)

This commit is contained in:
starkillerOG 2025-05-29 15:31:50 +02:00 committed by Bram Kragten
parent 4317fad798
commit 0f7379c941
2 changed files with 32 additions and 2 deletions

View File

@ -52,6 +52,7 @@ class PlaybackProxyView(HomeAssistantView):
verify_ssl=False, verify_ssl=False,
ssl_cipher=SSLCipherList.INSECURE, ssl_cipher=SSLCipherList.INSECURE,
) )
self._vod_type: str | None = None
async def get( async def get(
self, self,
@ -68,6 +69,8 @@ class PlaybackProxyView(HomeAssistantView):
filename_decoded = urlsafe_b64decode(filename.encode("utf-8")).decode("utf-8") filename_decoded = urlsafe_b64decode(filename.encode("utf-8")).decode("utf-8")
ch = int(channel) ch = int(channel)
if self._vod_type is not None:
vod_type = self._vod_type
try: try:
host = get_host(self.hass, config_entry_id) host = get_host(self.hass, config_entry_id)
except Unresolvable: except Unresolvable:
@ -127,6 +130,25 @@ class PlaybackProxyView(HomeAssistantView):
"apolication/octet-stream", "apolication/octet-stream",
]: ]:
err_str = f"Reolink playback expected video/mp4 but got {reolink_response.content_type}" err_str = f"Reolink playback expected video/mp4 but got {reolink_response.content_type}"
if (
reolink_response.content_type == "video/x-flv"
and vod_type == VodRequestType.PLAYBACK.value
):
# next time use DOWNLOAD immediately
self._vod_type = VodRequestType.DOWNLOAD.value
_LOGGER.debug(
"%s, retrying using download instead of playback cmd", err_str
)
return await self.get(
request,
config_entry_id,
channel,
stream_res,
self._vod_type,
filename,
retry,
)
_LOGGER.error(err_str) _LOGGER.error(err_str)
if reolink_response.content_type == "text/html": if reolink_response.content_type == "text/html":
text = await reolink_response.text() text = await reolink_response.text()
@ -140,7 +162,10 @@ class PlaybackProxyView(HomeAssistantView):
reolink_response.reason, reolink_response.reason,
response_headers, response_headers,
) )
response_headers["Content-Type"] = "video/mp4" if "Content-Type" not in response_headers:
response_headers["Content-Type"] = reolink_response.content_type
if response_headers["Content-Type"] == "apolication/octet-stream":
response_headers["Content-Type"] = "application/octet-stream"
response = web.StreamResponse( response = web.StreamResponse(
status=reolink_response.status, status=reolink_response.status,

View File

@ -58,17 +58,22 @@ def get_mock_session(
return mock_session return mock_session
@pytest.mark.parametrize(
("content_type"),
[("video/mp4"), ("application/octet-stream"), ("apolication/octet-stream")],
)
async def test_playback_proxy( async def test_playback_proxy(
hass: HomeAssistant, hass: HomeAssistant,
reolink_connect: MagicMock, reolink_connect: MagicMock,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
hass_client: ClientSessionGenerator, hass_client: ClientSessionGenerator,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
content_type: str,
) -> None: ) -> None:
"""Test successful playback proxy URL.""" """Test successful playback proxy URL."""
reolink_connect.get_vod_source.return_value = (TEST_MIME_TYPE_MP4, TEST_URL) reolink_connect.get_vod_source.return_value = (TEST_MIME_TYPE_MP4, TEST_URL)
mock_session = get_mock_session() mock_session = get_mock_session(content_type=content_type)
with patch( with patch(
"homeassistant.components.reolink.views.async_get_clientsession", "homeassistant.components.reolink.views.async_get_clientsession",