A professional ESP32-CAM streaming solution with full MQTT integration, OTA updates, and heartbeat monitoring using British English spelling throughout.
- 🎥 Live MJPEG video streaming over HTTP
- 📱 Web-based viewer with responsive design
- 💾 Persistent configuration using ConfigurationManager
- 📡 Full MQTT integration with heartbeat messages
- 🔄 OTA firmware updates via MQTT
- ⚙️ Remote configuration via MQTT
- 🔧 Serial configuration interface
- 🔄 Automatic WiFi and MQTT reconnection
- 🇬🇧 British English spelling throughout codebase
- ESP32-CAM module (AI-Thinker or compatible)
- USB-to-Serial adapter (FTDI or CH340)
- USB cable
- MQTT broker (e.g., Mosquitto, HiveMQ)
The project is configured for the AI-Thinker ESP32-CAM board:
- Camera pins are automatically configured in
WebCamServer.cpp - LED indicator: GPIO 33
- Boot button: GPIO 0 (for configuration mode)
- PSRAM support enabled for higher quality streaming
This project uses the following libraries from your existing codebase:
esp32-configuration-manager- Persistent configuration with NVSesp32-mqtt-handler- MQTT with TLS, OTA updates, and power managementesp32-wifi-manager- WiFi connection managementArduinoJson- JSON serialisation for MQTT messages
-
Open the project in PlatformIO:
cd esp32-web-cam pio run -
Connect your ESP32-CAM via USB-to-Serial adapter:
- ESP32-CAM GND → Adapter GND
- ESP32-CAM 5V → Adapter 5V
- ESP32-CAM U0R → Adapter TX
- ESP32-CAM U0T → Adapter RX
- Connect GPIO 0 to GND for programming mode
-
Upload the firmware:
pio run --target upload
-
Disconnect GPIO 0 from GND and reset the board
-
Monitor the serial output:
pio device monitor
On first boot, the device will prompt for complete configuration via Serial Monitor (115200 baud):
- Device UUID - Unique identifier for this camera
- WiFi SSID - Your WiFi network name
- WiFi Password - Your WiFi password
- MQTT Server - MQTT broker hostname/IP
- MQTT Port - Usually 1883 (unencrypted) or 8883 (TLS)
- MQTT Username - MQTT authentication username
- MQTT Password - MQTT authentication password
- MQTT Client Name - Friendly name for this camera
- Power Settings - WiFi/MQTT timeouts (defaults are fine)
- Type
CONFIRMto save the configuration
The device will restart and connect to WiFi and MQTT.
Once configured and connected:
- The Serial Monitor will display the stream URL (e.g.,
http://192.168.1.100/) - Open the URL in a web browser
- The live video stream will be displayed
The camera publishes to the following MQTT topics:
Topic: heartbeat
{
"id": "camera-01",
"name": "Front Door Camera",
"type": "webcam",
"version": "1.0.0+1",
"boot_count": 5,
"uptime": 3600,
"free_heap": 180000,
"psram_found": true,
"rssi": -45,
"ip_address": "192.168.1.100",
"camera_active": true,
"stream_url": "http://192.168.1.100/",
"deep_sleep_enabled": false,
"always_on": true
}Topic: configure/[device-uuid]
The device subscribes to this topic for:
- OTA firmware updates
- Configuration changes
- Power management settings
To perform an OTA update via MQTT:
{
"action": "update",
"url": "http://your-server.com/firmware.bin"
}Publish this to the configure/[device-uuid] topic.
You can update settings remotely via MQTT. Publish to configure/[device-uuid]:
{
"action": "update_setting",
"setting": "sleep_interval",
"value": 30
}Available settings match those in ConfigurationManager.
To reconfigure the device:
- Hold the GPIO 0 button (boot button)
- Press the reset button
- Release the reset button
- Release the GPIO 0 button
- Follow the configuration prompts in Serial Monitor
The device hosts a simple web interface:
- Index Page (
/) - HTML viewer with embedded video player - Stream Endpoint (
/stream) - Raw MJPEG stream
Default configuration:
- Frame size: VGA (640x480) for smooth streaming
- JPEG quality: 10 (0-63, lower is better)
- Frame rate: ~15-30 FPS (depending on network and lighting)
Settings can be modified in WebCamServer.cpp in the initialiseCam() method.
esp32-web-cam/
├── include/
│ ├── HeartbeatMqttPublisher.h # MQTT heartbeat publishing
│ ├── WebCamServer.h # Camera and HTTP server
│ └── version.h # Version information
├── src/
│ ├── HeartbeatMqttPublisher.cpp
│ ├── WebCamServer.cpp
│ └── main.cpp # Main application logic
├── platformio.ini # PlatformIO configuration
└── README.md
This project follows British English spelling conventions:
initialiseinstead ofinitializecolourinstead ofcolorcentreinstead ofcenter
Variable names, comments, and all text use British English spelling for consistency with the existing codebase.
The camera sends heartbeat messages every 60 seconds containing:
- Device identification (UUID, name, type)
- Version information
- Boot count
- Uptime
- System metrics (free heap, PSRAM status)
- WiFi status (RSSI, IP address)
- Camera status and stream URL
- Power configuration
You can monitor these in your MQTT broker or Home Assistant.
- Check that the camera module is properly connected
- Ensure camera ribbon cable is inserted correctly (blue side up on AI-Thinker)
- Try power cycling the device
- Verify credentials in configuration
- Check WiFi signal strength
- Ensure using 2.4GHz WiFi (ESP32 doesn't support 5GHz)
- Hold GPIO 0 button during boot to reconfigure
- Verify MQTT broker is running and accessible
- Check MQTT credentials
- Verify MQTT port (1883 for unencrypted, 8883 for TLS)
- Check firewall settings
- Check network bandwidth
- Reduce JPEG quality or frame size in settings
- Ensure good lighting conditions
- Some ESP32-CAM boards don't have PSRAM
- The code will automatically adjust settings for non-PSRAM boards
- Streaming quality may be reduced but will still work
Edit WebCamServer.cpp, line where set_framesize is called:
s->set_framesize(s, FRAMESIZE_SVGA); // Options: QVGA, VGA, SVGA, XGA, UXGAEdit WebCamServer.cpp:
s->set_quality(s, 12); // 0-63, lower = higher quality, larger file sizeEdit main.cpp:
const unsigned long heartbeatInterval = 60000; // milliseconds (60 seconds)Modify the HTML in WebCamServer.cpp indexHandler() method to customise the web interface.
Add to your configuration.yaml:
mqtt:
sensor:
- name: "Front Door Camera Status"
state_topic: "heartbeat"
value_template: "{{ value_json.name }}"
json_attributes_topic: "heartbeat"
json_attributes_template: "{{ value_json | tojson }}"
- name: "Front Door Camera RSSI"
state_topic: "heartbeat"
value_template: "{{ value_json.rssi }}"
unit_of_measurement: "dBm"
device_class: "signal_strength"
- name: "Front Door Camera Uptime"
state_topic: "heartbeat"
value_template: "{{ value_json.uptime }}"
unit_of_measurement: "s"
camera:
- platform: generic
name: Front Door Camera
still_image_url: http://192.168.1.100/stream
stream_source: http://192.168.1.100/streamUse MQTT nodes to subscribe to the heartbeat topic and display camera status.
- WiFi credentials stored in NVS (not encrypted)
- HTTP streaming (not HTTPS)
- MQTT can use TLS if configured
- No authentication on web interface
For production use, consider:
- HTTPS support for web streaming
- Basic authentication on web interface
- VPN or network isolation
- Encrypted MQTT (TLS)
The ESP32-CAM runs continuously for live streaming:
- Active streaming: ~160-300mA @ 5V
- Idle with WiFi: ~80-100mA @ 5V
- Not suitable for battery operation (always-on design)
This project is designed for educational and personal use.
Built with:
- ESP32 Arduino Core
- ESP-IDF Camera Driver
- PlatformIO
- Your existing ESP32 libraries (ConfigurationManager, MQTTHandler, WiFiManager)
British English spelling maintained throughout for consistency with existing codebase.
- Initial release
- Full MQTT integration
- Heartbeat monitoring
- OTA updates support
- Web streaming interface