1 """RTSPtoWebRTC integration with an external RTSPToWebRTC Server.
3 WebRTC uses a direct communication from the client (e.g. a web browser) to a
4 camera device. Home Assistant acts as the signal path for initial set up,
5 passing through the client offer and returning a camera answer, then the client
6 and camera communicate directly.
8 However, not all cameras natively support WebRTC. This integration is a shim
9 for camera devices that support RTSP streams only, relying on an external
10 server RTSPToWebRTC that is a proxy. Home Assistant does not participate in
11 the offer/answer SDP protocol, other than as a signal path pass through.
13 Other integrations may use this integration with these steps:
14 - Check if this integration is loaded
15 - Call is_supported_stream_source for compatibility
16 - Call async_offer_for_stream_source to get back an answer for a client offer
19 from __future__
import annotations
24 from rtsp_to_webrtc.client
import get_adaptive_client
25 from rtsp_to_webrtc.exceptions
import ClientError, ResponseError
26 from rtsp_to_webrtc.interface
import WebRTCClientInterface
27 from webrtc_models
import RTCIceServer
36 _LOGGER = logging.getLogger(__name__)
38 DOMAIN =
"rtsp_to_webrtc"
39 DATA_SERVER_URL =
"server_url"
42 CONF_STUN_SERVER =
"stun_server"
44 _DEPRECATED =
"deprecated"
48 """Set up RTSPtoWebRTC from a config entry."""
49 hass.data.setdefault(DOMAIN, {})
50 ir.async_create_issue(
54 breaks_in_ha_version=
"2025.6.0",
56 severity=ir.IssueSeverity.WARNING,
57 translation_key=_DEPRECATED,
58 translation_placeholders={
59 "go2rtc":
"[go2rtc](https://www.home-assistant.io/integrations/go2rtc/)",
63 client: WebRTCClientInterface
65 async
with asyncio.timeout(TIMEOUT):
66 client = await get_adaptive_client(
69 except ResponseError
as err:
70 raise ConfigEntryNotReady
from err
71 except (TimeoutError, ClientError)
as err:
72 raise ConfigEntryNotReady
from err
74 hass.data[DOMAIN][CONF_STUN_SERVER] = entry.options.get(CONF_STUN_SERVER)
75 if server := entry.options.get(CONF_STUN_SERVER):
78 def get_servers() -> list[RTCIceServer]:
79 return [RTCIceServer(urls=[server])]
81 entry.async_on_unload(camera.async_register_ice_servers(hass, get_servers))
83 async
def async_offer_for_stream_source(
88 """Handle the signal path for a WebRTC stream.
90 This signal path is used to route the offer created by the client to the
91 proxy server that translates a stream to WebRTC. The communication for
92 the stream itself happens directly between the client and proxy.
95 async
with asyncio.timeout(TIMEOUT):
96 return await client.offer_stream_id(stream_id, offer_sdp, stream_source)
97 except TimeoutError
as err:
99 except ClientError
as err:
102 entry.async_on_unload(
103 camera.async_register_rtsp_to_web_rtc_provider(
104 hass, DOMAIN, async_offer_for_stream_source
107 entry.async_on_unload(entry.add_update_listener(async_reload_entry))
113 """Unload a config entry."""
114 if DOMAIN
in hass.data:
115 del hass.data[DOMAIN]
116 ir.async_delete_issue(hass, DOMAIN, _DEPRECATED)
121 """Reload config entry when options change."""
122 if hass.data[DOMAIN][CONF_STUN_SERVER] != entry.options.get(CONF_STUN_SERVER):
123 await hass.config_entries.async_reload(entry.entry_id)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
None async_reload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)