Repository navigation
Troubleshooting
Quick fixes for the most common problems. See also Known limitations and the FAQ.
If the log shows:
Setup failed for custom integration 'aidot': Requirements for aidot not found:
['python-aidot-cameras[webrtc]>=...'].
this is fixed as of python-aidot-cameras 0.10.3. Update the AiDot
integration and restart Home Assistant.
Background: HA 2026.7 pins PyAV to av==17, while stock
aiortc (the WebRTC engine) capped av<17,
so the streaming dependency was unsatisfiable and HA reported it as "not found."
As of library 0.10.3, aiortc is vendored with the PyAV ceiling widened -
aiortc runs unchanged on av 17 - so the integration installs normally on HA
2026.7. No HA downgrade needed.
If you still see it: update the AiDot integration in HACS and restart Home
Assistant. If HACS shows no update, the fix rides the library floor (currently
>=1.0.0rc54 from integration 2.37.12); restarting HA re-resolves the requirement and pulls it. Confirm your
HA version under Settings -> About.
go2rtc must be running. Go to Settings -> Add-ons -> go2rtc and confirm it is started. On Home Assistant OS and Container it ships pre-installed; if you run Core or Supervised you may need to install it separately.
Mains (A000088 / M3 Pro) cameras: a bug fixed in 2.9.14 (library 0.12.14) made every DTLS camera go dark whenever a positive warm-hold window was configured - the serve was torn down and respawned forever. If a mains camera shows a blank picture, update to 2.9.14 or later first.
SDES cameras (battery L2 models and the PTZ / A001064): update to 2.10.0 first. Before that release these cameras could fail every live view, and the cause was a bug in the integration rather than your network. Opening a view re-registered the camera with go2rtc, and that call silently dropped the very stream the camera was publishing - so go2rtc had nothing to serve and the view went blank. The related "press play once, fail, press again, works" behaviour on a cold camera is fixed in the same release.
A camera whose picture is black while everything else looks right: update to 2.11.0. This one was easy to mistake for a dead camera, because nothing else was wrong - the camera connected, the stream ran at around 2 Mbps, and eleven megabytes arrived during a viewing that showed nothing at all. The decoder was being set up from a description of the video remembered from an earlier session, and one camera model changes that description between sessions, so the decoder was told to expect a stream that no longer matched and could not decode a single frame. A camera that does this is now recognised and the stale description is neither kept nor used for it again.
Worth knowing when diagnosing this yourself: bytes arriving is not evidence the picture should be appearing. "Is media arriving" and "is media decodable" are different questions, and only the second one explains a black picture.
If it still happens on 2.10.0 or later: this is NO_MEDIA - the camera's encrypted media can't get back to Home Assistant, usually because the camera can't reach HA directly and its media isn't traversing the cloud relay. That is common when the camera sits on a separate VLAN or behind AP/client isolation.
- If the camera shares the Home Assistant LAN, set Connection mode to LAN only (fastest, same-network only) (Settings -> Devices & Services -> AiDot Cameras -> Configure -> Live view and connection) to bypass the relay.
- If it can't share the LAN, this is a camera/network limitation rather than an integration bug - the relay path simply isn't carrying the media.
The repeated ffmpeg SDES stderr warnings this wrote to the log on every retry
are quieted as of 2.8.9 (they now log at debug); a genuine ffmpeg error still
warns.
Fixed in 2.9.23 (library 0.14.0). Update and restart.
Two faults produced this, and they compounded.
Once a stream session had started, the integration treated it as live for good. When the publisher died underneath it, every later view reused that dead session and handed go2rtc a stream nobody was publishing to - so the live view failed with nothing in the log to explain it, and stayed that way until Home Assistant restarted. Opening a view now asks go2rtc whether a publisher is actually attached, and restarts the session when it is not. (If go2rtc cannot be reached the session is left alone, so an unreachable go2rtc can't tear down a working stream.)
Battery cameras were hit hardest and could show no video at all: they are deliberately excluded from the startup warm-up, so nothing else ever gave them a session. Mains cameras mostly masked the problem, because the startup warm-up leaves them running.
Underneath that, the stream handed to ffmpeg advertises both video codecs and has to be narrowed to the one the camera actually sends. When a session's media started late there was nothing to narrow on, so the wrong decoder was bound and go2rtc rejected the published stream outright - no video, for anyone. The codec is now taken from the camera's own negotiated answer in that case.
Fixed in 2.9.19 (library floor >=0.13.0). Update and restart.
The LAN-session check compared a private attribute against an enum that exists in only one version of the underlying device library. On the newer version - the one Home Assistant core's own AiDot integration requires - neither is present, so the check answered "not connected" forever and every device looked permanently offline. Nothing raised an error, which is why there was nothing in the log to go on.
Fixed in 2.9.21 (library 0.13.1). Update and restart.
A battery camera used to be kept in a permanent keepalive: the integration could not tell whether anyone was actually watching, and "unknown" never released. So the camera was renewed around the clock against a live view nobody had open - draining it, and leaving it parked in a permanently-retrying state, which is why the first view would land on a session that never delivered a frame. Hitting refresh appeared to fix it only because a retry happened to be mid-flight with media.
Fixed in 2.9.22 (library 0.13.2). Update and restart.
Mains cameras were being misread as battery-powered, because the cloud reports
the same batteryMode flag on mains cameras with none of the corroborating
battery telemetry. A camera on that path is given the battery idle window instead
of the mains warm-hold, so every re-view paid a full cold start - exactly what
the warm-hold exists to avoid.
Note the floor is a hard >=0.13.2: Home Assistant only installs a requirement it
does not already satisfy, so an older library stays in place - and the fix stays
inert - until the floor moves.
Fixed in 2.9.20. Update and restart - no configuration needed.
The underlying device library logs routine traffic at WARNING - every ping, frame, command and connect - and dumps each device's raw record, including its password and AES key, when the device client is constructed. The integration now filters that by message: the noise and the credential dump are dropped at every level (including debug), while real failures are untouched.
Do not add a
logger:override foraidot.device_clientto silence this. It looks like the fix and is a trap. Home Assistant drops the record before the filter can see it, so settingaidot.device_client: errorthrows awayconnect device error- the one message that tells you a device failed to connect. You get a quiet log and a silent failure. If you added such an override, remove it.To see the protocol chatter deliberately, set
aidot.device_client: debug, which the filter honours. Credentials stay dropped even then.
Fixed in 2.20.3 (library 1.0.0rc12). Update and restart - no configuration
needed.
The warning looks like this, and Home Assistant raises it itself:
Module aidot_cameras.camera.webrtc_open is logging too frequently.
200 messages since last count
This is a different problem from the device-library chatter above, and the fix for that one does not touch it. The camera library reports a session's progress through a channel built for its command-line tool: when something is showing those messages on a screen they are logged quietly, and when nothing is, the log itself becomes the channel and they are logged at INFO. Running inside Home Assistant nothing ever shows them, so per-packet diagnostics ended up at the same level as the handful of lines that describe a session starting.
There is now a second channel for the steady-state messages, logging at debug whether or not anything is listening. Measured over 11.7 hours on an eight-camera install, INFO lines from the library fall from 39584 to 437 - roughly 3400 an hour to 37. The lines that describe a session are deliberately kept, so the log still shows a camera waking, offering, connecting and serving.
If you turned this integration's logging down to warning to escape the
noise, you can put it back to the default and get those session lines again.
The same release stopped one diagnostic writing a camera's decrypted audio to the log as hex. That dump was at INFO, so it reached ordinary log files; it is now truncated to a short prefix. If you keep old log files or have shared one for support, they may contain it.
From integration 2.37.9 (library 1.0.0rc51; 2.37.10 is the first public release that
carries it) every live session logs one INFO line a minute under
aidot_cameras.camera.health:
camera <id>: health 20s: packets=1686 (84.1/s) lost=0 (0.0%) stall=0.0s path=direct viewers=present
- The link is lossy:
lostclimbs (DTLS models; the SDES models recover loss with retransmission and reportbytesinstead). - The picture froze:
stallclimbs whileloststays at 0 - the camera stopped sending. A DTLS session with no video for 30 s is re-opened on its own. - Nobody was watching:
viewers=absentbeyond the idle window, after which the session is released.unknownmeans the go2rtc the camera publishes into could not be asked.
path=relay means the media rides the vendor's relay rather than your LAN - normal for a
camera on another subnet. The counts are the library's own view of the stream, before
go2rtc. The interval is AIDOT_HEALTH_LINE_S; 0 turns the line off.
Expected. A device the vendor cloud no longer serves goes unavailable here
automatically, but its entities stay registered until you delete the device
yourself in Settings -> Devices & Services -> AiDot Cameras, then pick the device
and Delete. Home Assistant never removes devices on its own.
Some controls were removed once the cameras were shown to acknowledge the command and then ignore it - a switch that did nothing and reported nothing. Home Assistant keeps the entity until you delete it.
| Entity | Removed in | Use instead |
|---|---|---|
switch.<camera>_auto_tracking on a camera that cannot pan or tilt |
2.17.3 | nothing - the camera ignored it |
switch.<camera>_ir_light |
2.15.0 |
select.<camera>_night_vision, which does switch the IR cut filter |
select.<camera>_resolution |
2.11.9 (entity cleared in 2.12.0) | nothing - see Resolution |
Delete the stale entity if it lingers after updating.
Fixed in integration 2.30.4 - update. This is a different fault from the buffering one below, even though both read as "slow".
The Picture / Picture Glance card opens Home Assistant's built-in HLS dialog,
which only accepts AAC audio. The integration used to register an
ffmpeg:<stream>#audio=aac source with go2rtc so that dialog had sound. Some
go2rtc builds stamp that transcode's timestamps on a 90 kHz clock while
advertising MPEG4-GENERIC/8000, so the audio arrived stretched about
elevenfold - and because players sync video to audio, the video crawled to
match. It affected every camera and every model, and nothing was logged as an
error.
To confirm it on a version before 2.30.4, capture the same stream twice over the same wall-clock window and compare how long each result claims to be:
ffmpeg -rtsp_transport tcp -i "rtsp://<host>:8554/aidot_<id>?audio=pcma" -c copy pcma.mkv # ~15 s for 15 s
ffmpeg -rtsp_transport tcp -i "rtsp://<host>:8554/aidot_<id>?audio=aac" -c copy aac.mkv # ~163 s for 15 s
From 2.30.4 that go2rtc AAC source is no longer offered, so the dialog plays at the right speed; 2.30.4 to 2.30.7 left it silent. From 2.30.8 the dialog has sound by default through the Audio in HLS and recordings option (Configure -> Audio and recordings): the camera library publishes its own AAC track, encoded in-process with timestamps that follow the camera's own audio clock, and only the HLS path asks go2rtc for it. Turn the option off and the dialog is silent, at the right speed. WebRTC cards (Dashboard cards) carry the camera's own audio untouched either way. Moving to a different card does not fix the speed on an older version, because a downstream go2rtc prefers the same AAC source and relays the bad timestamps unchanged.
Live view is served over go2rtc WebRTC (low-latency) whenever go2rtc is reachable: each camera publishes its video and audio straight into go2rtc (Direct publish into go2rtc, on by default since 2.35.0) and the integration hands Home Assistant the go2rtc RTSP URL. A standard (DTLS) camera is served on a local port and registered with go2rtc only when the integration cannot reach go2rtc directly, as with Home Assistant's bundled go2rtc. If go2rtc is unavailable it falls back to Home Assistant's HLS pipeline (higher latency) - so confirm go2rtc is running (above).
Note: the first view of an idle camera always has the handshake delay (see Cameras) before WebRTC takes over.
To force the HLS fallback (e.g. for debugging), set AIDOT_GO2RTC=0 in the Home
Assistant process environment. AIDOT_GO2RTC_API overrides the go2rtc REST base
URL (default http://127.0.0.1:1984).
PTZ rides the active stream session: open the live camera card in the Home
Assistant UI to establish it, then retry. aidot.talk does not need a live
view - it reuses the live session when one is open and otherwise opens its own
temporary session and closes it afterwards - so if it reports this error the
camera could not be reached at all (asleep, off the network, or held by the
AiDot app's live view); the error's wording predates that behaviour.
Every live view has dropped to HLS at once; the log shows go2rtc: add stream 'aidot_...' failed http=400 for every camera
go2rtc's own configuration file (go2rtc.yaml, the WebRTC add-on's or
integration's) holds a stream listed twice, which makes that go2rtc (1.9.9)
reject every registration until the duplicate is removed by hand. go2rtc saves
each registration by reading the file, patching it and writing it back, with
nothing guarding that cycle, so two registrations landing at once could leave
a stream listed twice. From 2.34.3 this integration never writes two
registrations at once, which is what tore the file (2.30.6 had only kept one
camera's own registrations apart), and from 2.34.4 a repair issue in
Settings names the condition and goes away once a registration succeeds.
To fix an existing file: stop go2rtc, delete the second copy of the duplicated
aidot_...: block in go2rtc.yaml (the key line and its - rtsp://... line
below it), start go2rtc. The warning's text from library 1.0.0rc41 on quotes
go2rtc's reason (mapping key ... already defined).
The PTZ camera's HLS view or recording is blank with "In-sync audio for recordings" on, while the live view works
The camera answered in H.265 despite the H.264 pin (it does so in roughly one
open in seven), and only an H.264 session can feed the in-sync stream. From
library 1.0.0rc42 (integration 2.33 and later) such a session is abandoned
and re-opened, up to twice; the log line is sent video payload type 97 against an offer pinned to 96 ... re-opening. If it still happens, the camera insisted
three times in a row and the session was served as it came; the next one is
normally fine.
Fixed in 2.30.6. Update and restart.
Home Assistant resolves a camera's stream source only when it creates a stream,
and otherwise reuses the one it cached - even a stopped one. A battery camera's
session was then released 120 s after its last viewer, so a camera.record (or the
Picture cards' HLS dialog) started in the next few seconds got the old stream,
which pointed at a source no longer being published: it answered 404, never
re-opened the camera, and the recording never wrote a file. The integration now
replaces a cached stream whose session has ended at the moment Home Assistant
is about to reuse it, so the camera is opened again. A stream over a live
session is reused exactly as before.
Fixed in 2.34.2. Update; clips cached by an older version are made again.
Reading the cloud's clip, the integration threw away everything it had read while working out the clip's format - the whole first part of the clip, about 3 s, often with the motion that triggered the notification. 2.34.1 hid the blank picture this left at the start; from 2.34.2 nothing is lost (a 12 s clip is its full 15 s again).
Recorded clips require an active AiDot cloud storage subscription. Check the AiDot mobile app to confirm the camera's cloud plan is active. See Cloud recordings.
- Check that
switch.motion_detectionis on for the camera. - Motion is cloud-polled (~30 s), not pushed, so a new event can take up to ~30 s to appear - this is normal.
- Update to 2.8.5 or later. Earlier versions reloaded the integration on every account-token refresh, which re-primed the motion poll and dropped any event that landed just after - so motion (and occupancy) could look stuck.
- If events consistently never arrive, reload the integration: the
Reload button on the AiDot device, the entry's
...menu, or Settings -> Devices & Services -> AiDot Cameras. - Check whose account Home Assistant is signed in with. Motion events come from the camera's cloud event list, and that list is only populated for the account that owns the home - a member the home is shared to reads an empty list and so gets no motion events, no notifications, and no cloud recordings, even though the owner's phone in the AiDot app shows all three. This is an account-role limit on AiDot's side, not a fault in the integration. If motion never fires but the app shows events, sign Home Assistant in with the home-owner account (the one the cameras were added under). See also Cloud recordings.
As of 2.8.5 the integration no longer reloads itself on every account-token refresh - that self-reload was the usual cause of "keeps reloading" and of motion/occupancy dropping out, so update to the latest first.
If it still reloads, your AiDot credentials have likely expired or changed: go to
Settings -> Devices & Services -> AiDot Cameras -> Reconfigure and re-enter them. To
reload on demand, use the Reload button on the AiDot device or the entry's
... menu.
Enable Local camera control in the integration options (Settings -> Devices & Services -> AiDot Cameras -> Configure). This only works for mains-powered cameras; battery cameras are excluded by design. Changes take effect after restarting Home Assistant. If cameras still don't attach, confirm they are on the same subnet as the Home Assistant host.
Each camera serves one live session at a time. Close the live view in the AiDot mobile app before streaming in Home Assistant. Snapshots and recorded clips are unaffected.
AiDot for Home Assistant / camera-capable fork of AiDot-Development-Team/hass-AiDot / device communication via python-aidot-cameras / MIT licensed / Open an issue
Getting started
Cameras
- Cameras overview
- Dashboard cards
- PTZ control
- Two-way audio
- Resolution (removed)
- Cloud recordings
- On-device recordings
Lights
Using it
Help