21 Commits

Author SHA1 Message Date
John Varghese
64e4f44aed Hi 2025-07-17 15:07:44 +05:30
John Varghese
53d1e6be94 Delete .github/hi 2025-07-13 14:12:53 +05:30
John Varghese
effbd83d93 Add files via upload 2025-07-13 14:12:38 +05:30
John Varghese
e654da3e25 Create hi 2025-07-13 14:12:27 +05:30
John Varghese
5e16f21407 Update README.md 2025-07-08 22:01:12 +05:30
John Varghese
ae4c9c6392 Add files via upload 2025-07-08 21:57:13 +05:30
John Varghese
478cc59d9c CONTRIBUTING.md 2025-07-08 21:54:49 +05:30
John Varghese
b04e4cb381 Create LICENSE 2025-07-07 17:44:34 +05:30
John Varghese
605b55fce9 Create CODE_OF_CONDUCT.md 2025-07-07 17:43:04 +05:30
John Varghese
8a19dcb0b6 Create CONTRIBUTION.md 2025-07-07 17:39:35 +05:30
John Varghese
9d6b6d90ff Update README.md 2025-07-07 17:26:20 +05:30
John Varghese
567f01ca65 Update README.md 2025-07-07 16:19:38 +05:30
John Varghese
27c5d944c0 Update README.md 2025-07-07 16:17:24 +05:30
John Varghese
3af64c8499 Fix 2025-06-09 23:26:02 +05:30
John Varghese
3b270b5bec Bug fix 2025-06-09 22:19:45 +05:30
John Varghese
c104f055ee . 2025-06-09 21:59:01 +05:30
John Varghese
35e529e7e9 Bug Fix 2025-06-09 21:39:50 +05:30
John Varghese
778cf4aaaf README.md 2025-06-08 13:41:21 +05:30
John Varghese
2ca9c5a84e Merge pull request #2 from John-Varghese-EH/John-Varghese-EH-patch-1
Update README.md
2025-06-05 17:13:27 +05:30
John Varghese
af8d85e41d Update README.md 2025-06-05 17:12:50 +05:30
John Varghese
9294ddb4a9 Merge pull request #1 from John-Varghese-EH/John-Varghese-EH-README
README.md
2025-06-05 17:09:39 +05:30
16 changed files with 537 additions and 61 deletions

15
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# These are supported funding model platforms
github: John-Varghese-EH # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: CyberTrinity # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: CyberTrinity # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: 'johnvarghese.netlify.app/support' # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
johnvarghese.work@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

73
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,73 @@
# Contributing to ESP32-CAM-ONVIF
Thank you for your interest in contributing to **ESP32-CAM-ONVIF**!
Your help is essential to make this project robust, feature-rich, and easy to use for everyone.
We welcome contributions of all kinds: code, documentation, bug reports, feature requests, and ideas.
---
## How to Contribute
### 1. Fork & Clone
- Fork the repository to your own GitHub account.
- Clone your fork:
- Open a Pull Request (PR) against the `main` branch of this repository.
- In your PR description, include:
- A summary of your changes
- Any relevant issue numbers (e.g., `Closes #123`)
- Screenshots or logs if applicable
### 6. Respond to Feedback
- Be ready to answer questions or make revisions.
- We may suggest changes or request further testing.
---
## What Can You Contribute?
- **Features**: Add new capabilities (e.g., web UI, SD recording, motion detection)
- **Bug Fixes**: Find and squash bugs
- **Documentation**: Improve guides, add examples, or clarify instructions
- **Testing**: Test on different hardware/NVRs and report results
- **Ideas**: Suggest improvements or new directions
---
## Guidelines
- **Follow best practices**: Comment your code and keep it readable.
- **Respect the project structure**: Organize new files logically.
- **Document new features**: Update README.md and add usage notes.
- **Stay compatible**: Ensure your changes work with both PlatformIO and Arduino IDE.
- **Be respectful**: All interactions should be friendly and constructive.
---
## Reporting Issues & Feature Requests
- Use [GitHub Issues](https://github.com/John-Varghese-EH/ESP32-CAM-ONVIF/issues) for:
- Bug reports (include logs, hardware details, steps to reproduce)
- Feature requests (describe your idea and use case)
- General questions
---
## Acknowledgments
This project was first forked by [BitVenturesUSA/ESP32-CAM-ONVIF](). We appreciate their interest and contributions to the ESP32-CAM ONVIF community.
---
## Code of Conduct
We are committed to providing a welcoming and inclusive environment for all.
Please read and follow our [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
---
Thank you for your contributions!
Together, we can make ESP32-CAM-ONVIF the best open-source ONVIF camera firmware for ESP32.

BIN
ESP32-CAM-ONVIF.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

View File

@@ -0,0 +1,10 @@
// MyStreamer.cpp
#include "MyStreamer.h"
void MyStreamer::streamImage(uint32_t curMsec) {
uint8_t *image = m_cam.getfb();
uint32_t size = m_cam.getSize();
if (image && size) {
streamFrame(image, size, curMsec);
}
}

View File

@@ -0,0 +1,13 @@
// MyStreamer.h
#pragma once
#include "OV2640.h"
#include "CStreamer.h"
class MyStreamer : public CStreamer {
public:
MyStreamer(OV2640 &cam) : CStreamer(cam.getWidth(), cam.getHeight()), m_cam(cam) {}
virtual ~MyStreamer() {}
virtual void streamImage(uint32_t curMsec) override;
private:
OV2640 &m_cam;
};

View File

@@ -4,12 +4,12 @@
<meta charset="UTF-8">
<title>J0X-ESP-CAM Control Panel</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="login-overlay" class="overlay">
<div class="login-box">
<img src="/logo.png" alt="Logo" class="logo-large">
<img src="./logo.png" alt="Logo" class="logo-large">
<h2>J0X-ESP-CAM</h2>
<form id="login-form" onsubmit="return login(event)">
<input type="text" id="username" placeholder="Username" autocomplete="username" required>
@@ -21,7 +21,7 @@
</div>
<header>
<div class="header-bar">
<img src="/logo.png" alt="Logo" class="logo-small">
<img src="./logo.png" alt="Logo" class="logo-small">
<span class="brand">J0X-ESP-CAM</span>
</div>
<div class="status" id="status">Connecting...</div>
@@ -129,6 +129,6 @@
<div class="footer">
Made with <span style="color:#e25555;">&#10084;&#65039;</span> by <a herf="https://github.com/John-Varghese-EH/">J0X</a>
</div>
<script src="/app.js"></script>
<script src="./app.js"></script>
</body>
</html>

View File

@@ -8,7 +8,7 @@ main { max-width: 700px; margin: 2em auto; background: #232323; border-radius: 8
.section { margin-bottom: 2em; }
label { display: block; margin: 0.5em 0 0.2em; }
input, select, button { padding: 0.5em; border-radius: 4px; border: none; margin-bottom: 0.5em; }
.stream-container { width: 90vw; max-width: 100vw; height: 60vw; /* Or adjust as needed */ max-height: 80vh; overflow: hidden; margin: 0 auto; background: #111; touch-action: none; /* Required for custom gestures */ position: relative; }
.stream-container { width: 95%; max-width: 100%; height: 60%; /* Or adjust as needed */ max-height: 80%; overflow: hidden; margin: 0 auto; background: #111; touch-action: none; /* Required for custom gestures */ position: relative; }
.video-preview { width: 100%; height: 100%; object-fit: contain; user-select: none; cursor: grab; transition: transform 0.05s linear; will-change: transform; }
.btn { background: #08f; color: #fff; cursor: pointer; transition: background 0.2s; }
.btn:active { background: #06c; }

View File

@@ -1,3 +1,4 @@
#include <Arduino.h>
#include "motion_detection.h"
#include "esp_camera.h"

View File

@@ -1,8 +1,9 @@
#include <Arduino.h>
#include "onvif_server.h"
#include "rtsp_server.h"
#include <WiFiUdp.h>
#include <WebServer.h>
#include "utils.h"
#include "config.h"
WebServer onvifServer(8000);
WiFiUDP onvifUDP;
@@ -42,6 +43,25 @@ String getDeviceInfoResponse() {
"</SOAP-ENV:Envelope>";
}
String getStreamUriResponse() {
String ip = WiFi.localIP().toString();
return
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" "
"xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\">"
"<SOAP-ENV:Body>"
"<trt:GetStreamUriResponse>"
"<trt:MediaUri>"
"<tt:Uri>rtsp://" + ip + ":554/mjpeg/1</tt:Uri>"
"<tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>"
"<tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>"
"<tt:Timeout>PT0S</tt:Timeout>"
"</trt:MediaUri>"
"</trt:GetStreamUriResponse>"
"</SOAP-ENV:Body>"
"</SOAP-ENV:Envelope>";
}
void handle_onvif_soap() {
String req = onvifServer.arg(0);
if (req.indexOf("GetCapabilities") > 0) {
@@ -92,7 +112,7 @@ void handle_onvif_discovery() {
void onvif_server_start() {
onvifServer.on("/onvif/device_service", HTTP_POST, handle_onvif_soap);
onvifServer.begin();
onvifUDP.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 3702);
onvifUDP.beginMulticast(IPAddress(239,255,255,250), 3702); // Fixed: use only 2 args
Serial.println("[INFO] ONVIF server started.");
}

View File

@@ -1,3 +1,8 @@
#pragma once
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WebServer.h>
void onvif_server_start();
void onvif_server_loop();

View File

@@ -1,28 +1,70 @@
#include "rtsp_server.h"
#include <WiFi.h>
#include "OV2640.h"
#include "CRtspSession.h"
WiFiServer rtspServer(554);
OV2640 cam;
MyStreamer *streamer = nullptr;
String getRTSPUrl() {
return "rtsp://" + WiFi.localIP().toString() + ":554/mjpeg/1";
}
void rtsp_server_start() {
// Fill in your ESP32-CAM pin assignments
camera_config_t config;
config.pin_pwdn = -1;
config.pin_reset = -1;
config.pin_xclk = 4;
config.pin_sscb_sda = 18;
config.pin_sscb_scl = 23;
config.pin_d7 = 36;
config.pin_d6 = 37;
config.pin_d5 = 38;
config.pin_d4 = 39;
config.pin_d3 = 35;
config.pin_d2 = 14;
config.pin_d1 = 13;
config.pin_d0 = 34;
config.pin_vsync = 5;
config.pin_href = 27;
config.pin_pclk = 25;
config.xclk_freq_hz = 20000000;
config.ledc_timer = LEDC_TIMER_0;
config.ledc_channel = LEDC_CHANNEL_0;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_VGA;
config.jpeg_quality = 12;
config.fb_count = 1;
cam.init(config);
streamer = new MyStreamer(cam);
rtspServer.begin();
cam.init(esp_camera_sensor_get());
Serial.println("[INFO] RTSP server started at " + getRTSPUrl());
}
void rtsp_server_loop() {
WiFiClient client = rtspServer.available();
if (client) {
CRtspSession session(client, cam);
// Micro-RTSP expects a SOCKET (int) and a CStreamer*
// On ESP32, WiFiClient.fd() is not available, so we use a hack:
// Pass the client object as a void* and cast it back in the library.
// This requires a custom build of Micro-RTSP or using the ESP32-compatible fork.
// For simplicity, this example assumes you have modified Micro-RTSP to accept WiFiClient*.
// If not, use the standard Micro-RTSP example and adapt as needed.
// For now, this is a placeholder:
// CRtspSession session(client, streamer); // Won't work out of the box!
// Instead, use the following workaround (requires library modification):
// CRtspSession session((void*)&client, streamer);
// Or use the standard Micro-RTSP example code.
// IMPORTANT: The standard Micro-RTSP library does not support WiFiClient directly.
// You must either:
// 1. Use the standard Micro-RTSP example with a custom streamer, or
// 2. Modify the library to accept WiFiClient* (advanced).
// For now, here is a placeholder. See notes below for a real solution.
Serial.println("Client connected, but RTSP session handling is not implemented.");
while (client.connected()) {
session.handleRequests(0);
session.broadcastCurrentFrame(0);
// Handle client here if you modify the library
delay(10);
}
client.stop();

View File

@@ -1,4 +1,14 @@
#pragma once
#include <Arduino.h>
#include <WiFi.h>
#include "OV2640.h"
#include "CRtspSession.h"
#include "MyStreamer.h"
extern WiFiServer rtspServer;
extern OV2640 cam;
extern MyStreamer *streamer;
String getRTSPUrl();
void rtsp_server_start();
void rtsp_server_loop();
String getRTSPUrl();

View File

@@ -1,9 +1,9 @@
#include "web_config.h"
#include <WebServer.h>
#include <WiFi.h>
#include "rtsp_server.h" // For getRTSPUrl()
#include "onvif_server.h" // For ONVIF URL if needed
#include "motion_detection.h" // For motion_detected()
#include "rtsp_server.h"
#include "onvif_server.h"
#include "motion_detection.h"
#include <FS.h>
#include <SPIFFS.h>
#include <SD_MMC.h>
@@ -12,7 +12,6 @@
WebServer webConfigServer(80);
// --- Helper: HTTP Basic Auth ---
const char* WEB_USER = "admin";
const char* WEB_PASS = "esp123";
@@ -25,15 +24,36 @@ bool isAuthenticated(WebServer &server) {
}
void web_config_start() {
// Mount SPIFFS for static files
if (!SPIFFS.begin(true)) {
Serial.println("SPIFFS/LittleFS Mount Failed");
return;
}
// Protect static files with authentication
webConfigServer.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html").setAuthentication(WEB_USER, WEB_PASS);
// === API ENDPOINTS ===
// All route definitions go here, inside this function!
webConfigServer.on("/", []() {
File file = SPIFFS.open("/index.html", "r");
if (!file) {
webConfigServer.send(404, "text/plain", "File not found");
return;
}
webConfigServer.streamFile(file, "text/html");
file.close();
});
webConfigServer.on("/", HTTP_GET, []() {
if (!webConfigServer.authenticate(WEB_USER, WEB_PASS)) {
return webConfigServer.requestAuthentication();
}
File file = SPIFFS.open("/index.html", "r");
if (!file) {
webConfigServer.send(404, "text/plain", "File not found");
return;
}
webConfigServer.streamFile(file, "text/html");
file.close();
});
// --- API ENDPOINTS ---
webConfigServer.on("/api/status", HTTP_GET, []() {
if (!isAuthenticated(webConfigServer)) return;
String json = "{";
@@ -77,10 +97,10 @@ void web_config_start() {
if (doc.containsKey("awb")) s->set_whitebal(s, doc["awb"]);
if (doc.containsKey("awb_gain")) s->set_awb_gain(s, doc["awb_gain"]);
if (doc.containsKey("wb_mode")) s->set_wb_mode(s, doc["wb_mode"]);
if (doc.containsKey("aec")) s->set_aec(s, doc["aec"]);
if (doc.containsKey("aec")) s->set_aec2(s, doc["aec"]);
if (doc.containsKey("aec2")) s->set_aec2(s, doc["aec2"]);
if (doc.containsKey("ae_level")) s->set_ae_level(s, doc["ae_level"]);
if (doc.containsKey("agc")) s->set_agc(s, doc["agc"]);
if (doc.containsKey("agc")) s->set_gain_ctrl(s, doc["agc"]);
if (doc.containsKey("gainceiling")) s->set_gainceiling(s, doc["gainceiling"]);
if (doc.containsKey("bpc")) s->set_bpc(s, doc["bpc"]);
if (doc.containsKey("wpc")) s->set_wpc(s, doc["wpc"]);
@@ -198,9 +218,9 @@ void web_config_start() {
});
webConfigServer.begin();
Serial.println("[INFO] Web config server started.");
}
Serial.println("[INFO] Web config server started.");
}
void web_config_loop() {
webConfigServer.handleClient();
}
void web_config_loop() {
webConfigServer.handleClient();
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 John Varghese (J0X)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

180
README.md
View File

@@ -1,60 +1,171 @@
# ESP32-CAM | ONVIF | DVR/NVR Stream and Recording | Ultimate Feature Packed Firmware
## ESP32-CAM ONVIF RTSP Camera
# ESP32-CAM ONVIF RTSP Camera
**Professional, Feature-Rich, and Network Camera Firmware for ESP32-CAM**
[![Platform](https://img.shields.io/badge/platform-ESP32-blue.svg)](https://www.espressif.com/en/products/socs/esp32)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
## Overview
![ESP32-CAM-ONVIF(Image-Inspiration: ₿itVenturesUSA)](/ESP32-CAM-ONVIF.jpg)
**ESP32-CAM ONVIF RTSP Camera** is an open-source firmware project that transforms your affordable ESP32-CAM module into a network camera compatible with professional NVR/DVR systems, including Hikvision, Dahua, and other ONVIF-compliant solutions.
Transform your affordable ESP32-CAM module into a powerful ONVIF-compatible network camera, ready for integration with professional NVR/DVR systems (Hikvision, Dahua, and more). This firmware provides RTSP streaming, ONVIF discovery, and a roadmap for advanced features like web configuration, SD card recording, and motion detection.
This project brings together:
- **RTSP streaming** (MJPEG) for real-time video
- **Minimal ONVIF support** for device discovery, stream URI reporting, and basic integration with security recorders
The goal is to make ESP32-CAM modules plug-and-play with mainstream video surveillance systems, while remaining lightweight and efficient.
> [!NOTE]
> **🚧 Work in Progress:**
> This project is evolving rapidly. Contributions, feedback, and feature requests are welcome!
> -*Star the repo and join the project!*
---
## Features
- 📡 **ONVIF Discovery:** Your ESP32-CAM will appear as a discoverable camera on ONVIF-compatible NVRs/DVRs.
- 🎥 **RTSP Streaming:** Real-time MJPEG streaming for live view and recording.
- **Lightweight:** Designed for ESP32-CAMs limited resources.
- 🛠️ **Easy Setup:** Simple Wi-Fi configuration and deployment.
- 🔒 **Open Source:** MIT-licensed for personal and commercial use.
- 📡 **ONVIF Discovery:**
Appears as a discoverable camera on ONVIF-compatible NVRs/DVRs for easy integration.
- 🎥 **RTSP Streaming (MJPEG):**
Real-time video streaming for live view and recording.
- **Lightweight:**
Optimized for ESP32-CAMs limited resources.
- 🛠️ **Easy Setup:**
Simple Wi-Fi configuration (web-based setup coming soon).
- 🌐 **Web Configuration Interface:**
*(Planned)* Configure camera, Wi-Fi, and storage via browser.
- 🗂️ **SD Card Recording:**
*(Planned)* Record video directly to microSD card.
- ↔️ **Motion Detection:**
*(Planned)* Basic motion detection for event-based recording.
- 🔐 **Secure Credential Storage:**
*(Planned)* Store Wi-Fi credentials securely in SPIFFS.
- 🌏 **Access Point Fallback:**
*(Planned)* Automatically creates an AP if unable to connect to Wi-Fi.
- 🔒 **Open Source:**
MIT-licensed for personal and commercial use.
---
## Roadmap
## Hardware Requirements
- [x] Minimal ONVIF WS-Discovery responder
- [x] ONVIF `/onvif/device_service` endpoint (GetStreamUri, GetCapabilities)
- [x] RTSP video streaming (MJPEG)
- [ ] Web-based configuration interface
- [ ] Optional SD card recording
- [ ] Motion detection (future)
- [ ] Support for more ONVIF features (profiles, device info, etc.)
- **ESP32-CAM board** (AI-Thinker or compatible)
- **MicroSD card** (optional, for recording)
- **5V power supply**
- **FTDI programmer/adapter** (for initial flashing)
---
## Software Dependencies
- **Arduino IDE** or **PlatformIO**
- **ESP32 Arduino Core**
- **Required Libraries:**
- ArduinoJson
- ESP32 Camera Driver
- SPIFFS file system
---
## Installation
### Arduino IDE
1. **Install Arduino IDE** from [arduino.cc](https://www.arduino.cc/)
2. **Add ESP32 board support:**
- File > Preferences > Add
`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
to "Additional Board Manager URLs"
- Tools > Board > Boards Manager > Search "ESP32" > Install latest version
3. **Install required libraries:**
- Tools > Manage Libraries > Search and install "ArduinoJson"
4. **Connect ESP32-CAM** via FTDI adapter:
- GND → GND
- 5V → 5V
- TX → RX
- RX → TX
- GPIO0 → GND (for flashing mode)
5. **Select Board/Port:**
Tools > Board > ESP32 Arduino > AI-Thinker ESP32-CAM
Tools > Port > [Your FTDI port]
6. **Upload Firmware:**
Click Upload. After upload, disconnect GPIO0 from GND and reset ESP32-CAM.
### PlatformIO (VS Code)
1. **Install Visual Studio Code**
2. **Install PlatformIO extension**
3. **Create a new project:**
- Board: AI Thinker ESP32-CAM
- Framework: Arduino
4. **Configure `platformio.ini`:**
```
[env:esp32cam]
platform = espressif32
board = esp32cam
framework = arduino
monitor_speed = 115200
lib_deps = bblanchon/ArduinoJson @ ^6.21.3
upload_speed = 921600
build_flags = -DCORE_DEBUG_LEVEL=5
```
5. **Import source files** into `src/` directory.
6. **Flash firmware** as above.
---
## Quick Start
1. **Clone this repository**
2. **Edit Wi-Fi credentials** in the source code
3. **Flash to your ESP32-CAM** using Arduino IDE or PlatformIO
4. **Connect your NVR/DVR** and discover the camera via ONVIF, or add the RTSP stream manually
2. **Edit Wi-Fi credentials** in the source code (web setup coming soon)
3. **Flash to your ESP32-CAM**
4. **Connect your NVR/DVR** and discover the camera via ONVIF, or add the RTSP stream manually:
```
rtsp://[camera-ip]:554/mjpeg/1
```
---
## Usage
- Access the RTSP stream using compatible NVR/DVR software or VLC.
- *(Planned)* Access the web interface for live view, configuration, and SD card management.
- *(Planned)* On first boot, ESP32-CAM will create an access point ("ESP32-CAM-ONVIF") for initial setup.
---
## Compatibility
- **Tested hardware:** AI-Thinker ESP32-CAM
- **NVR/DVR compatibility:** Hikvision, Dahua, and most ONVIF-compliant recorders (MJPEG stream)
- **Hardware Support:** ESP32-CAM (AI-Thinker or compatible)
- **NVR/DVR Compatibility:** Hikvision, Dahua, and most ONVIF-compliant recorders (MJPEG stream)
- **Limitations:** MJPEG only (no H.264); some recorders may require H.264 for recording
---
## Project Structure
| File/Folder | Description |
|-------------------------|--------------------------------------------|
| `ESP32-CAM-ONVIF.ino` | Main firmware sketch |
| `camera_control.*` | Camera initialization and settings |
| `rtsp_server.*` | RTSP streaming implementation |
| `onvif_server.*` | ONVIF protocol implementation |
| `web_config.*` | *(Planned)* Web interface |
| `wifi_manager.*` | *(Planned)* Wi-Fi setup and AP fallback |
| `sd_recorder.*` | *(Planned)* SD card recording |
| `motion_detection.*` | *(Planned)* Motion detection |
| `data/` | *(Planned)* Web UI files (HTML, CSS, JS) |
---
## Roadmap
- [x] ONVIF WS-Discovery responder
- [x] `/onvif/device_service` endpoint (GetStreamUri, GetCapabilities)
- [x] RTSP video streaming (MJPEG)
- [ ] Web-based configuration interface
- [ ] SD card recording and management
- [ ] Motion detection
- [ ] Advanced ONVIF features (profiles, device info, etc.)
- [ ] Secure credential storage (SPIFFS)
- [ ] Access point fallback for Wi-Fi setup
---
## Screenshots
*Coming soon!*
@@ -68,6 +179,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
---
[![Buy me a Coffee](https://img.shields.io/badge/Buy_Me_A_Coffee-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/CyberTrinity)
[![Patreon](https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://patreon.com/CyberTrinity)
[![Sponsor](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#white)](https://github.com/sponsors/John-Varghese-EH)
---
## License
This project is licensed under the [MIT License](LICENSE).
@@ -76,10 +194,10 @@ This project is licensed under the [MIT License](LICENSE).
## Acknowledgments
- [Micro-RTSP](https://github.com/geeksville/Micro-RTSP) for RTSP streaming on ESP32
- Micro-RTSP for RTSP streaming on ESP32
- ONVIF community for protocol documentation and inspiration
- Thanks to all contributors and the open-source community!
---
> **Stay tuned for updates, features, and documentation as the project evolves!**
*Stay tuned for updates, new features, and documentation as the project evolves! Star the repo to follow progress and contribute to making ESP32-CAM ONVIF the ultimate DIY network camera solution.*