Add streaming support w/ audio to Android IP Webcam integration (#126009)

* Add streaming support w/ audio to Android IP Webcam integration

* ruff reformat

* Fix ruff

* Break long comments and strings

* Add camera test

* Fix docstring

* Remove dead code

* Call library function to get URL

* Simplify

---------

Co-authored-by: Shay Levy <levyshay1@gmail.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Parker Wahle 2025-06-24 07:54:34 -04:00 committed by GitHub
parent 23b90f5984
commit fc62a6cd89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 0 deletions

View File

@ -2,6 +2,7 @@
from __future__ import annotations
from homeassistant.components.camera import CameraEntityFeature
from homeassistant.components.mjpeg import MjpegCamera, filter_urllib3_logging
from homeassistant.const import (
CONF_HOST,
@ -31,6 +32,7 @@ class IPWebcamCamera(MjpegCamera):
"""Representation of a IP Webcam camera."""
_attr_has_entity_name = True
_attr_supported_features = CameraEntityFeature.STREAM
def __init__(self, coordinator: AndroidIPCamDataUpdateCoordinator) -> None:
"""Initialize the camera."""
@ -46,3 +48,17 @@ class IPWebcamCamera(MjpegCamera):
identifiers={(DOMAIN, coordinator.config_entry.entry_id)},
name=coordinator.config_entry.data[CONF_HOST],
)
self._coordinator = coordinator
async def stream_source(self) -> str:
"""Get the stream source for the Android IP camera."""
return self._coordinator.cam.get_rtsp_url(
video_codec="h264", # most compatible & recommended
# while "opus" is compatible with more devices,
# HA's stream integration requires AAC or MP3,
# and IP webcam doesn't provide MP3 audio.
# aac is supported on select devices >= android 4.1.
# The stream will be quiet on devices that don't support aac,
# but it won't fail.
audio_codec="aac",
)

View File

@ -0,0 +1,54 @@
"""Test the Android IP Webcam camera."""
from typing import Any
import pytest
from homeassistant.components.android_ip_webcam.const import DOMAIN
from homeassistant.components.camera import async_get_stream_source
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry
@pytest.mark.usefixtures("aioclient_mock_fixture")
@pytest.mark.parametrize(
("config", "expected_stream_source"),
[
(
{
"host": "1.1.1.1",
"port": 8080,
"username": "user",
"password": "pass",
},
"rtsp://user:pass@1.1.1.1:8080/h264_aac.sdp",
),
(
{
"host": "1.1.1.1",
"port": 8080,
},
"rtsp://1.1.1.1:8080/h264_aac.sdp",
),
],
)
async def test_camera_stream_source(
hass: HomeAssistant,
config: dict[str, Any],
expected_stream_source: str,
) -> None:
"""Test camera stream source."""
entity_id = "camera.1_1_1_1"
entry = MockConfigEntry(domain=DOMAIN, data=config)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(entity_id)
assert state is not None
stream_source = await async_get_stream_source(hass, entity_id)
assert stream_source == expected_stream_source