Maker.io main logo

DIY IP Camera with the Seeed XIAO ESP32 Sense, ESPHome, & Home Assistant

153

2026-03-10 | By Nate_Larson

License: Attribution Camera ESP32

Introduction

The Seeed Studio XIAO ESP32-S3 Sense is a compact, affordable development board with a built-in camera connector, onboard PSRAM, and Wi-Fi. When paired with ESPHome, it can become a low-cost IP camera integrated directly into Home Assistant — no cloud, no third-party app.

This guide walks through the complete process: flashing the ESP32 board with ESPHome, configuring the camera stream, routing that stream through go2RTC, and displaying it on a Home Assistant dashboard using the WebRTC Camera integration.


What You'll Need

Hardware

  • Seeed Studio XIAO ESP32-S3 Sense (with the OV2640/OV3660 camera module attached)

  • USB-C cable

  • A computer with a Chromium-based browser (Chrome, Edge) for the initial flash

Software / Services (all on your Home Assistant server)

  • Home Assistant OS (this guide uses HAOS on a Raspberry Pi 5)

  • ESPHome Builder app (formerly known as the ESPHome add-on)

  • HACS installed

  • WebRTC Camera integration by AlexxIT (search "WebRTC Camera" in HACS)

  • go2RTC app (installed via the Home Assistant App store)


Step 1 — Install the ESPHome Builder App

If you haven't already, install the ESPHome Builder app from the Home Assistant App store:

  1. In Home Assistant, go to Settings → Apps → Install app.

  2. Search for ESPHome and install the ESPHome Device Builder app.

  3. Start it and enable Show in sidebar.

    image


Step 2 — Create a New ESPHome Device

  1. Open the ESPHome Builder app from the sidebar.

  2. Click + New Device, select Empty Configuration, give it a name (e.g., Xiao Sense Cam).

    image


Step 3 — Configure the YAML

Click Edit on your new device. Replace the entire contents with the configuration below.

Before pasting, read these important notes:

  • Generate your own API key: You can generate your key here (https://esphome.io/components/api/#configuration-variables), or run openssl rand -base64 32 in a terminal. Do not reuse someone else's key — it grants API access to your device.

  • Choose your own OTA password: Any string works; treat it like a password.

  • Choose your own fallback hotspot password: This is the Wi-Fi password for the board's emergency access point if it can't reach your network.

  • Set your own static IP, gateway, and subnet to match your network. Using a static IP ensures your go2RTC stream URL never changes.

  • secrets.yaml: Your Wi-Fi SSID and password should live in your ESPHome secrets.yaml file (ESPHome Builder app header→ "Secrets"), referenced as !secret wifi_ssid and !secret wifi_password.

Copy Code
esphome:
  name: xiao_sense_cam
  friendly_name: XIAO Sense Cam

esp32:
  board: seeed_xiao_esp32s3
  variant: esp32s3
  framework:
    type: esp-idf

psram:
  mode: octal
  speed: 80MHz

logger:
  level: DEBUG

api:
  encryption:
    key: "YOUR_GENERATED_API_KEY_HERE"
  reboot_timeout:
    minutes: 5

ota:
  - platform: esphome
    password: "YOUR_OTA_PASSWORD_HERE"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  # Reduce output power to improve connection stability.
  # The default of 20dB is known to cause connectivity issues on this board.
  # 8.5dB resolves most connection and dropout problems.
  power_save_mode: none
  output_power: 8.5dB
  ap:
    ssid: "XIAO Sense Cam Fallback Hotspot"
    password: "YOUR_FALLBACK_HOTSPOT_PASSWORD_HERE"

  manual_ip:
    static_ip: 192.168.X.X       # Set to your chosen static IP
    gateway: 192.168.X.1         # Your router's IP
    subnet: 255.255.255.0

captive_portal:

# Camera SCCB bus (I2C)
i2c:
  id: bus_a
  sda: GPIO40
  scl: GPIO39
  scan: true

esp32_camera:
  name: XRP_POV
  external_clock:
    pin: GPIO10
    frequency: 20MHz
  i2c_id: bus_a
  data_pins: [GPIO15, GPIO17, GPIO18, GPIO16, GPIO14, GPIO12, GPIO11, GPIO48]
  vsync_pin: GPIO38
  href_pin: GPIO47
  pixel_clock_pin: GPIO13

  # --- Performance & Stability ---
  # 320x240 at 5fps is a conservative but reliable starting point.
  # Increasing resolution or framerate demands more bandwidth and processing.
  # If you push these values too high, you may see:
  #   - Dropped frames or a frozen stream
  #   - Unreliable Wi-Fi connectivity
  #   - The board running hot
  # Increase incrementally and monitor with the temperature sensor below.
  # Other resolution options and configuration details can be found here:
  # https://esphome.io/components/api/#configuration-variables
  resolution: 320x240
  jpeg_quality: 30
  frame_buffer_count: 2
  max_framerate: 5 fps
  vertical_flip: false
  horizontal_mirror: false

# Expose an MJPEG stream on port 8080
esp32_camera_web_server:
  - port: 8080
    mode: stream

# --- Diagnostics & Monitoring ---
text_sensor:
  - platform: wifi_info
    ip_address:
      name: "IP Address"
    ssid:
      name: "Connected SSID"

button:
  - platform: restart
    name: "Restart XIAO Sense Cam"

sensor:
  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s

  - platform: uptime
    name: "Uptime"
    update_interval: 60s

  # Monitor board temperature — useful if experimenting with higher resolutions/framerates
  - platform: internal_temperature
    name: "Sense Cam Temp"

binary_sensor:
  - platform: status
    name: "Status"

When you're done editing, click Save.


Step 4 — Flash the Firmware (First Time)

The first flash must be done over USB. After this, all future updates can be pushed wirelessly via OTA.

  1. Plug the XIAO ESP32-S3 Sense into your computer via USB-C.

  2. In the ESPHome app, click the three-dot menu on your device and select Install.

  3. Choose Plug into this computer and follow the browser's prompts to select the board's serial port.

  4. ESPHome's web-based flasher will compile and flash the firmware automatically.

Troubleshooting tip: If the flasher fails to connect, the board may need to be manually placed into bootloader mode. Hold the BOOT button on the board, press and release the RESET button, then release BOOT. This is not typically required when using ESPHome's web flasher, but it is worth trying if you encounter serial connection errors.

Once flashing completes, the board will reboot, connect to your Wi-Fi, and appear as online in the ESPHome dashboard. All future firmware changes can be deployed wirelessly using Install → Wirelessly.

image

At this point, you should have a camera feed that works locally within Home Assistant; however, this video feed would not render for users who were remotely connected to the server. The following steps were implemented to overcome this limitation.


Step 5 — Install the WebRTC Camera Integration via HACS

ESPHome exposes the camera as an MJPEG stream but does not create a native HA camera entity that supports smooth, low-latency playback. The WebRTC Camera integration bridges this gap cleanly.

  1. Open HACS in Home Assistant.

  2. Search for WebRTC Camera and install it.

  3. Restart Home Assistant when prompted.

  4. Go to Settings → Devices & Services → Add Integration, search for WebRTC Camera, and add it.

image


Step 6 — Configure go2RTC to Ingest the Camera Stream

go2RTC is a media server that pulls the MJPEG stream from the board and makes it available as an efficient, low-latency WebRTC stream for Home Assistant.

go2RTC is not available in the default app store repository, so you first need to add AlexxIT's add-on repository:

  1. In Home Assistant, go to Settings → Add-ons → Add-on Store.

  2. Click the three-dot menu (top right) and select Repositories.

  3. Add the following URL and click Add: https://github.com/AlexxIT/hassio-addons

  4. Close the dialog. The store will refresh, and go2RTC will now appear in the list.

  5. Find go2RTC, install it, and start it.

  6. With go2RTC running, open its web UI by clicking Open Web UI on the add-on page (or navigate to http://your-ha-ip:1984/ in your browser).

  7. In the web UI, click Add to add a new stream.

  8. Give your stream a name (e.g., xrp_pov) and enter your board's MJPEG stream URL as the source, replacing 192.168.X.X with your board's static IP: http://192.168.X.X:8080

  9. Save the stream. It will now appear in the go2RTC stream list, and you can click on it to verify the feed is live before continuing.

The stream name xrp_pov is what you'll reference in the dashboard card. You can name it anything, but it must be consistent across this config and the card YAML.

image


Step 7 — Create a Generic Camera Entity in Home Assistant

With go2RTC running, create a Home Assistant camera entity that points to the local go2RTC stream.

  1. Go to Settings → Devices & Services → Add Integration.

  2. Search for and add the Generic Camera integration.

  3. For the Still Image URL, enter: http://127.0.0.1:1984/api/frame.jpeg?src=xrp_pov

  4. For the Stream Source URL, enter: rtsp://127.0.0.1:8554/xrp_pov

  5. Complete the setup wizard. Home Assistant will now have a camera entity for your XIAO.

127.0.0.1 works here because go2RTC is running as an add-on on the same host as Home Assistant. Port 1984 is go2RTC's HTTP API (used for the still image snapshot), and port 8554 is its RTSP server (used for the stream source).

image


Step 8 — Add the Camera to Your Dashboard

  1. Open the dashboard you want to add the camera to and enter edit mode.

  2. Add a new card and choose Manual (to paste YAML directly).

  3. Paste the following:

Copy Code
type: custom:webrtc-camera
url: xrp_pov
title: POV
muted: true
  1. Save the card. The live stream should appear within a few seconds.

The url value must match the stream name you defined in go2RTC. muted: true suppresses any audio (this board has a microphone, but it is not configured in this ESPHome setup).

image


image

A Note on Performance and Heat

The configuration above uses 320×240 at 5 fps deliberately. The XIAO ESP32-S3 Sense is a capable but small board, and higher resolutions or framerates place a significant load on both the processor and the Wi-Fi radio simultaneously. Pushing these settings too far can cause the following:

  • Dropped frames or a frozen/unreliable stream

  • Wi-Fi disconnections (the connectivity is already sensitive on this board, hence the reduced output_power)

  • The board is running noticeably warm

The board ships with small heatsinks; use them! The temperature sensor configured in the YAML will appear as an entity in Home Assistant, making it easy to monitor thermals while experimenting with settings. If you want higher quality video, increase resolution and jpeg_quality incrementally, check the temperature sensor and stream stability, and back off if you see problems. If the board gets uncomfortably hot under sustained use, consider adding a small active cooling solution (a 5V mini fan powered from the board's 5V pin, for example).


Troubleshooting

The board won't connect to Wi-Fi / keeps dropping. This is a well-documented issue with the XIAO ESP32-S3 Sense at the default ESPHome output power. Ensure output_power: 8.5dB is in your config. Also, ensure power_save_mode: none is set, and that the board's antenna is unobstructed.

The stream is frozen or very choppy. Lower resolution (try 240x176) and/or reduce max_framerate to 3 fps. Also, check your Wi-Fi signal strength using the WiFi Signal sensor entity.

ESPHome web flasher can't find the device / serial port. Try a different USB-C cable (some cables are charge-only). If the port is found but flashing fails, try manually entering bootloader mode: hold BOOT, tap RESET, release BOOT.

The go2RTC stream URL shows an error in the Generic Camera setup. Make sure the go2RTC add-on is running and that the stream name in the add-on config exactly matches the url value in the dashboard card and the Generic Camera URLs.

The camera entity shows "unavailable" in Home Assistant. Check that the board's IP address hasn't changed (confirm by looking at the "IP Address" sensor entity). If it has, either update your go2RTC config or revisit the static IP settings in the ESPHome YAML to lock it down permanently. For best results, the board should have a static IP address set in your WiFi router’s configuration.


Next Steps

  • Add the microphone: ESPHome supports the XIAO's digital microphone via the i2s_audio and microphone components, though streaming both audio and video simultaneously is demanding.

  • Increase resolution: Once your setup is stable, experiment with 640x480 and a slightly higher jpeg_quality. Monitor temperatures closely.

  • Automate restarts: The restart button entity can be called from an automation to recover a hung stream without physical access to the board.

  • Mounting: The XIAO's small form factor makes it easy to mount in tight spaces. The USB-C port is your power and (initial) programming connection, so plan cable routing accordingly.

Mfr Part # 113991115
XIAO ESP32S3 SENSE
Seeed Technology Co., Ltd
¥2,290
View More Details
Mfr Part # 102010635
XIAO ESP32S3 SENSE PRE-SOLDERED
Seeed Technology Co., Ltd
¥2,453
View More Details
Mfr Part # 114993115
OV5640 CAMERA XIAO ESP32S3 SENSE
Seeed Technology Co., Ltd
¥1,962
View More Details
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.