Repository navigation
Configuration options
After the integration is set up, open Settings -> Devices & Services -> AiDot Cameras -> Configure to adjust its behaviour. That opens a menu with four pages (from 2.34.4; it was three before, with the audio settings on the streaming page): Live view and connection, Audio and recordings, Motion notifications - targets and wording, and Motion notifications - per camera. All options have sensible defaults and most users never need to change them.
When a default changes in a release (2.35.0 turned three options on by default), a choice you have already saved in the options is kept.
| Option | Default | What it does |
|---|---|---|
| Camera stream port base | 18600 | Base local port for serving camera streams to Home Assistant / go2rtc (each camera uses base..base+399). With direct publish on (the default) only a standard (DTLS) camera that cannot publish straight into go2rtc still uses it. Change only if it conflicts with another service. |
| Connection mode | Automatic - LAN preferred, relay fallback (recommended) | How cameras connect. Automatic - LAN preferred, relay fallback offers every path and prefers the LAN, keeping the cloud relay as a fallback - cameras on the same LAN connect directly, and only a camera with no direct route rides the relay. LAN only skips the relay for a faster (~1 s vs ~3-4 s) start, but a camera that cannot reach Home Assistant directly will not connect (battery cameras keep the relay regardless - it is their only path back from a cloud wake). Each camera reports the path in use under Diagnostics as media_path. |
| Pin camera video to H.264 | On | Stops a camera switching itself to H.265 mid-session. Some cameras ignore the requested codec and answer with H.265 at a much larger frame size; players that use Media Source Extensions - the Home Assistant iOS app among them - may then show only about one frame per keyframe. On by default since 2.35.0. Turn it off only for a camera that can encode nothing but H.265, which would otherwise have nothing to send. |
| SDES fast connect | On | Matches the official app: skips the livePlayResp wait and goes straight to the video handshake, so SDES (battery) cameras start ~4.5 s sooner. The PTZ camera is excluded automatically (its handshake needs the slower path). If a live view ever drops to a snapshot on a specific camera, turn this off. |
| Mains camera warm-hold (seconds) | 0 (always warm) | How long a mains-powered camera's live session is kept warm after the last viewer leaves, so re-opening it is instant instead of paying the full cold-start handshake. The default 0 keeps it warm forever - views are instant around the clock. Set a positive window (for example 300 = 5 min) to let unwatched cameras go dormant; a dormant camera reconnects on view in roughly 3 s on a mains camera (see Cameras for current per-model timings). A camera that stops sending video when unwatched cannot be held warm at all - it is detected as stalled and reconnected repeatedly - so give those a positive window rather than the default. Each warm camera keeps decrypting, which costs host CPU. Battery cameras ignore this: from 2.36.0 they are never held warm or pre-warmed on motion, and stream only while someone is watching (see Cameras). |
| Warm camera sessions at startup | On | Opens a session on every mains camera in the background at startup (staggered so the handshakes don't collide), so the first view after a restart is instant instead of paying the cold start (about 3 s on a mains camera; battery models are slower and are excluded anyway). Battery cameras are excluded. |
| Local camera control | Off | Routes camera settings writes (LED, motion detection, night vision, sensitivity, volume, PTZ tracking) over the LAN instead of the cloud, for eligible mains-powered cameras, with automatic cloud fallback. Does not affect video. Battery cameras are skipped automatically. Takes effect after a restart. |
Its own page from 2.34.4; before that these settings sat on the streaming page.
| Option | Default | What it does |
|---|---|---|
| SDES camera audio | On | Includes audio in SDES camera streams (battery models and the mains PTZ), matching the official app. On by default: the stream feeds the audio encoder a continuous silence base so audio from battery cameras plays smoothly. Turn off only if you don't want camera audio. |
| Camera audio gain (dB) | 0 | Volume trim for SDES camera audio, applied after the level normalizer the library runs on every camera. 0 (the default from 2.37.10) serves a battery or PTZ camera at the same loudness as an M3 Pro. Raise it if a camera is too quiet, lower it if it clips. Before 2.37.10 the default was -8 on the raw microphone signal, which served these cameras as silence; an install that saved that default keeps it, so set 0 to match. A quiet room still reads quiet: the normalizer does not lift a microphone's noise floor. |
| Audio in HLS and recordings | On | Also publishes an AAC copy of each camera's audio, encoded in-process, so Home Assistant's own HLS dialog (the Picture cards) and camera.record recordings have sound; WebRTC views already carry the camera's audio. Applies to cameras that publish directly: every SDES camera, and standard cameras with direct publish on. Costs about 2-3% of one CPU core per streaming camera. On by default since 2.30.8; turn it off to save that, or if a camera's HLS audio misbehaves. |
| In-sync audio for recordings | On | Home Assistant's HLS dialog and recordings read the camera's stream straight from this integration, with sound and picture on one clock, instead of through go2rtc - where a recording that starts while the camera is already streaming can have its sound up to about 0.75 s behind the picture. Live WebRTC views are unchanged. Needs Direct publish into go2rtc and Audio in HLS and recordings on (all three are on by default since 2.35.0). SDES cameras (the battery and PTZ models) take part too: this also pins their video to H.264, as Pin camera video to H.264 does, because a session that answers in H.265 cannot feed this stream. |
| Direct publish into go2rtc | On | Publishes each camera's video and audio straight into go2rtc without an ffmpeg process in between. SDES cameras (battery and PTZ models) always publish; standard (DTLS) cameras publish too when the integration can reach go2rtc's API, and with Home Assistant's bundled go2rtc they keep the local serve port. Fewer moving parts; live WebRTC views carry the camera's own audio, untranscoded, and the HLS dialog and recordings get it through Audio in HLS and recordings. A session that answers in H.265 keeps the ffmpeg path, and a standard camera publishes only when the integration can reach go2rtc directly - with Home Assistant's bundled go2rtc it keeps the local serve. On by default since 2.35.0; turn it off to go back to an ffmpeg process per camera. |
Available from 2.19.0. Nothing is sent until you switch a camera on under Motion notifications - per camera. Changing any of these settings takes effect on the next event without reloading the integration, so live streams are not interrupted.
This is an independent notification path from the AiDot app's. Home Assistant produces these notifications by polling each camera's cloud event list on a timer; the AiDot app receives its own through a separate push channel. The two do not touch each other - turning the app's notifications off does not stop these, turning these off does not change the app's, and both can run at once. That is unlike almost every other control the integration exposes: motion detection, the siren, the detection types, the floodlight and so on all mirror a setting stored on the device, so a change made on either surface shows on the other. Notifications are the exception.
One thing they still share: a notification only fires if the camera actually records an event, and whether it records is governed by the camera's own detection settings (motion detection, detection types, the alarm triggers) - and those settings are mirrored controls. So the notification channel is independent of the app; the events that feed it are the same events the app would see.
If notifications never fire at all, the most common cause is an account one: the cloud event list is only populated for the home owner, so a member the home is shared to gets none - see Troubleshooting.
| Option | Default | What it does |
|---|---|---|
| Default notification targets | (none) | The notify.* services to send to - for example a phone running the companion app (mobile_app_<name>). The list shows the services on your instance; you can also type a name that is not listed. Used by every camera that does not set its own targets. |
| Cooldown per camera (seconds) | 60 | After a notification for a camera, further motion from that camera is not sent for this long. A person detection still gets through a cooldown that plain motion started. 0 disables the cooldown. |
| Notification title | {camera}: {event_title} |
Placeholders: {camera}, {event} (motion/person), {event_title} (Motion/Person), {time} (the event's local time), {device_id}. |
| Notification message | {event_title} detected at {time} |
Same placeholders as the title. |
| Open the clip inside the Home Assistant app (experimental) | Off | When a notification is tapped, play the event's clip on a page inside the Home Assistant app. Off: the tap opens the clip's own link, which the iPhone app opens in Safari. From 2.34.0. |
Pick a camera, then:
| Option | Default | What it does |
|---|---|---|
| Send a notification for | Off | Off: never. All motion and person events. Person only: only when the camera reports a person. |
| Targets for this camera | (use defaults) | Overrides the default targets for this camera only. Leave empty to use the defaults. |
Each notification carries the event's still image; tapping it opens the clip's own link (the iPhone app opens it in Safari), or a page inside the companion app with Open the clip inside the Home Assistant app on. Repeated notifications for the same camera replace each other instead of piling up.
The clip link inside a notification is valid for a week, including across Home Assistant restarts (since 2.19.10). After that it is refused; open the clip from the Media browser instead.
- All cameras on the same LAN as Home Assistant -> the default Connection mode: Automatic already connects them directly; switch to LAN only if you want the slightly faster start and have no remote cameras.
- A camera on another network / VLAN / behind strict NAT -> keep Connection mode: Automatic (the default) so it can fall back to the cloud relay.
- You want a push when a camera sees someone -> set your phone under Motion notifications - targets and wording, then switch the camera to Person only under Motion notifications - per camera.
-
You want mains cameras instant at all times -> keep the default
warm-hold of
0(always warm). - One camera keeps reconnecting while idle -> it is a model that stops sending when unwatched, and cannot be held warm. Give it a positive warm-hold (120 s is a reasonable start) so it goes dormant cleanly instead of stall-reconnecting.
-
You prefer unwatched cameras to rest -> set a positive warm-hold (for
example
300) and they go dormant after that window, reconnecting on view. - You run many cameras on a lean host -> each warm camera keeps decrypting, so consider a positive warm-hold to shed idle CPU load.
- You want camera setting changes to stay on the LAN -> enable Local camera control (mains cameras only) and restart Home Assistant.
The concurrent-stream cap sizes itself to your camera count automatically (override with the
AIDOT_MAX_CONCURRENT_STREAMSenvironment variable), so warm cameras no longer crowd out live views.
From 2.11.0 the integration works out which video decoder your machine can actually use, in the background when it starts, and uses it where it genuinely helps. Where a machine has video decoding hardware that works, it is used; where it does not, software decoding is used exactly as before. There is nothing to configure.
The choice has to be measured rather than looked up. The list of decoders ffmpeg reports describes what the program was built with, not what the machine can do: a Raspberry Pi 4 lists decoders for graphics hardware it does not have, and one for its own video hardware that fails to start. So each candidate is made to decode a sample first, and only one that works is used.
Hardware decoding is also not always faster. On an Apple M1, VideoToolbox decodes H.264 about three times slower than software does. Candidates are therefore ranked by measured speed on your own machine and the faster one wins, whichever that turns out to be - so on many machines the honest answer is software, and that is not a failure.
This never delays startup. It costs a Raspberry Pi 4 about six seconds, once; a machine with no video decoding hardware is answered in about three milliseconds without starting anything. The answer is remembered per machine and re-measured only if ffmpeg itself changes.
To override it:
| Variable | Effect |
|---|---|
AIDOT_VIDEO_DECODER |
Force a decoder by name (h264_v4l2m2m), or an acceleration method with a hwaccel: prefix (hwaccel:videotoolbox) |
AIDOT_DISABLE_HWACCEL=1 |
Keep to software decoding |
See also: Cameras overview for how cold-start, warm-hold and the stream cap interact.
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