mirror of
https://github.com/rzeldent/esp32cam-rtsp.git
synced 2025-11-14 20:18:01 +00:00
23
README.md
23
README.md
@@ -170,6 +170,29 @@ This link can be opened with for example [VLC](https://www.videolan.org/vlc/).
|
||||
|
||||
:warning: **Please be aware that there is no password present on the stream!**
|
||||
|
||||
## API
|
||||
|
||||
There is a minimum API present to perform some tasks using HTTP requests.
|
||||
The URLs are below:
|
||||
|
||||
### GET: /restart
|
||||
|
||||
Calling this URL will restart the device.
|
||||
|
||||
### GET: /config
|
||||
|
||||
Calling this URL will start the form for configuring the device in the browser.
|
||||
|
||||
### GET: /snapshot
|
||||
|
||||
Calling this URL will return a JPEG snapshot of the camera in the browser.
|
||||
|
||||
### GET: /flash?v={value}
|
||||
|
||||
Calling this URL will set the intensity of the flash LED.
|
||||
The values must for {value} must be between 0 and 255.
|
||||
If no v parameter is present, it will be set to the value of the configuration.
|
||||
|
||||
## Issues / Nice to know
|
||||
|
||||
- The red LED on the back of the device indicates the device is not connected.
|
||||
|
||||
@@ -149,7 +149,11 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">JPEG quality:</div>
|
||||
<div class="col-8">{{JpegQuality}} (0-100)</div>
|
||||
<div class="col-8">{{JpegQuality}} (1-100)</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">Flash LED intensity:</div>
|
||||
<div class="col-8">{{FlashLedIntensity}} (0-100)</div>
|
||||
</div>
|
||||
{{#CameraInitialized}}
|
||||
<div class="mt-4 alert alert-success" role="alert">
|
||||
@@ -159,7 +163,7 @@
|
||||
{{^CameraInitialized}}
|
||||
<div class="mt-4 alert alert-danger" role="alert">
|
||||
<p>Failed to initialize the camera!</p>
|
||||
<p>Result: {{CameraInitResultText}} ({{CameraInitResult}})</p>
|
||||
<p>Result: {{CameraInitResultText}}</p>
|
||||
<p>Please check hardware or correct the camera settings and restart.</p>
|
||||
<button type="button" class="btn btn-danger"
|
||||
onclick="location.href='restart'">Restart</button>
|
||||
@@ -172,20 +176,41 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="card bg-light mb-3">
|
||||
<h5 class="card-header">Camera stream</h5>
|
||||
<h5 class="card-header">Special URLs / API</h5>
|
||||
<div class="card-body">
|
||||
</p>The camera stream can be found at the following location:
|
||||
<a href="rtsp://{{HostName}}:{{RtspPort}}/mjpeg/1">rtsp://{{HostName}}:{{RtspPort}}/mjpeg/1</a>
|
||||
</p>
|
||||
<!-- <img class="rounded mx-auto d-block" src="snapshot" alt="Camera image" width="25%">-->
|
||||
<div class="row">
|
||||
<span>
|
||||
The camera RTSP stream can be found at:
|
||||
<a
|
||||
href="rtsp://{{IpV4}}:{{RtspPort}}/mjpeg/1">rtsp://{{HostName}}:{{RtspPort}}/mjpeg/1</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span>
|
||||
A snapshot of the camera can be found at:
|
||||
<a href="http://{{IpV4}}/snapshot">http://{{HostName}}/snapshot</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span>
|
||||
The intensity of the flash led (0-255) can be controlled using:
|
||||
<a href="http://{{IpV4}}/flash?v=0">http://{{HostName}}/flash?v=value</a>.
|
||||
If no value is present, the configuration value is used.
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span>
|
||||
Restarting the camera can be done using:
|
||||
<a href="http://{{IpV4}}/restart">http://{{HostName}}/restart</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 col-6 mx-auto">
|
||||
<button type="button" class="btn btn-lg btn-warning" onclick="location.href='config'">Settings</button>
|
||||
</div>
|
||||
<div class="d-grid gap-2 col-6 mx-auto">
|
||||
<button type="button" class="btn btn-lg btn-warning" onclick="location.href='config'">Settings</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="bootstrap.min.css">
|
||||
<meta http-equiv="refresh" content="30;url=/index.html">
|
||||
<meta http-equiv="refresh" content="1;url=/index.html">
|
||||
<title>{{AppTitle}} v{{AppVersion}}</title>
|
||||
</head>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
|
||||
#define WIFI_SSID "ESP32CAM-RTSP"
|
||||
#define WIFI_PASSWORD nullptr
|
||||
#define CONFIG_VERSION "1.1"
|
||||
#define CONFIG_VERSION "1.2"
|
||||
|
||||
#define OTA_PASSWORD "ESP32CAM-RTSP"
|
||||
|
||||
@@ -15,3 +15,4 @@
|
||||
#define DEFAULT_FRAME_BUFFERS "2"
|
||||
#define DEFAULT_FRAME_SIZE "SVGA (800x600)"
|
||||
#define DEFAULT_JPEG_QUALITY "12"
|
||||
#define DEFAULT_LIGHT_INTENSITY "1"
|
||||
40
src/main.cpp
40
src/main.cpp
@@ -20,6 +20,7 @@ char frame_duration_val[6];
|
||||
char frame_size_val[sizeof(frame_size_entry_t)];
|
||||
char frame_buffers_val[3];
|
||||
char jpeg_quality_val[4];
|
||||
char flash_led_intensity_val[4];
|
||||
|
||||
auto config_group_stream_settings = iotwebconf::ParameterGroup("settings", "Streaming settings");
|
||||
auto config_camera_config = iotwebconf::SelectParameter("Camera config", "config", camera_config_val, sizeof(camera_config_val), (const char *)camera_configs, (const char *)camera_configs, sizeof(camera_configs) / sizeof(camera_configs[0]), sizeof(camera_configs[0]), DEFAULT_CAMERA_CONFIG);
|
||||
@@ -27,6 +28,7 @@ auto config_frame_rate = iotwebconf::NumberParameter("Frame duration (ms)", "fd"
|
||||
auto config_frame_size = iotwebconf::SelectParameter("Frame size", "fs", frame_size_val, sizeof(frame_size_val), (const char *)frame_sizes, (const char *)frame_sizes, sizeof(frame_sizes) / sizeof(frame_sizes[0]), sizeof(frame_sizes[0]), DEFAULT_FRAME_SIZE);
|
||||
auto config_frame_buffers = iotwebconf::NumberParameter("Frame buffers", "fb", frame_buffers_val, sizeof(frame_buffers_val), DEFAULT_FRAME_BUFFERS, nullptr, "min=\"1\" max=\"16\"");
|
||||
auto config_jpg_quality = iotwebconf::NumberParameter("JPEG quality", "q", jpeg_quality_val, sizeof(jpeg_quality_val), DEFAULT_JPEG_QUALITY, nullptr, "min=\"1\" max=\"100\"");
|
||||
auto config_flash_led_intensity = iotwebconf::NumberParameter("Flash LED intensity", "li", flash_led_intensity_val, sizeof(flash_led_intensity_val), DEFAULT_LIGHT_INTENSITY, nullptr, "min=\"0\" max=\"100\"");
|
||||
|
||||
// Camera
|
||||
OV2640 cam;
|
||||
@@ -106,8 +108,8 @@ void handle_root()
|
||||
{"FrameBuffers", frame_buffers_val},
|
||||
{"JpegQuality", jpeg_quality_val},
|
||||
{"CameraInitialized", String(camera_init_result == ESP_OK)},
|
||||
{"CameraInitResult", "0x" + String(camera_init_result, 16)},
|
||||
{"CameraInitResultText", esp_err_to_name(camera_init_result)},
|
||||
{"FlashLedIntensity", flash_led_intensity_val},
|
||||
// RTSP
|
||||
{"RtspPort", String(RTSP_PORT)}};
|
||||
|
||||
@@ -119,14 +121,6 @@ void handle_root()
|
||||
void handle_restart()
|
||||
{
|
||||
log_v("Handle restart");
|
||||
// If configuration is not changed and camera working, do not allow a restart
|
||||
if (!config_changed && camera_init_result == ESP_OK)
|
||||
{
|
||||
// Redirect to root page
|
||||
web_server.sendHeader("Location", "/", true);
|
||||
web_server.send(302, "text/plain", "Restart not possible.");
|
||||
return;
|
||||
}
|
||||
|
||||
const moustache_variable_t substitutions[] = {
|
||||
{"AppTitle", APP_TITLE},
|
||||
@@ -164,9 +158,24 @@ void handle_snapshot()
|
||||
delete[] fb;
|
||||
}
|
||||
|
||||
void handle_flash()
|
||||
{
|
||||
log_v("handle_flash");
|
||||
// If no value present, use value from config
|
||||
auto value = web_server.hasArg("v") ? web_server.arg("v") : flash_led_intensity_val;
|
||||
// If conversion fails, v = 0
|
||||
auto v = (uint8_t)min(value.toInt(), 255l);
|
||||
analogWrite(LED_FLASH, v);
|
||||
web_server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
web_server.send(200);
|
||||
}
|
||||
|
||||
void on_config_saved()
|
||||
{
|
||||
log_v("on_config_saved");
|
||||
// Set flash led intensity
|
||||
analogWrite(LED_FLASH, atoi(flash_led_intensity_val));
|
||||
|
||||
config_changed = true;
|
||||
}
|
||||
|
||||
@@ -211,8 +220,10 @@ void start_rtsp_server()
|
||||
void on_connected()
|
||||
{
|
||||
log_v("on_connected");
|
||||
// Turn LED off (has inverted logic GPIO33)
|
||||
// Turn LED off (has inverted logic GPIO33) => red LED off => connected
|
||||
digitalWrite(LED_BUILTIN, true);
|
||||
// Set flash led intensity
|
||||
analogWrite(LED_FLASH, atoi(flash_led_intensity_val));
|
||||
// Start (OTA) Over The Air programming when connected
|
||||
ArduinoOTA.begin();
|
||||
// Start the RTSP Server
|
||||
@@ -225,9 +236,13 @@ void setup()
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
// Turn LED on (has inverted logic GPIO33)
|
||||
// Turn LED on (has inverted logic GPIO33) => red LED on => not connected
|
||||
digitalWrite(LED_BUILTIN, false);
|
||||
|
||||
pinMode(LED_FLASH, OUTPUT);
|
||||
// Turn flash led off
|
||||
analogWrite(LED_FLASH, 0);
|
||||
|
||||
#ifdef CORE_DEBUG_LEVEL
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
@@ -242,6 +257,7 @@ void setup()
|
||||
config_group_stream_settings.addItem(&config_frame_size);
|
||||
config_group_stream_settings.addItem(&config_frame_buffers);
|
||||
config_group_stream_settings.addItem(&config_jpg_quality);
|
||||
config_group_stream_settings.addItem(&config_flash_led_intensity);
|
||||
iotWebConf.addParameterGroup(&config_group_stream_settings);
|
||||
iotWebConf.getApTimeoutParameter()->visible = true;
|
||||
iotWebConf.setConfigSavedCallback(on_config_saved);
|
||||
@@ -255,6 +271,8 @@ void setup()
|
||||
web_server.on("/restart", HTTP_GET, handle_restart);
|
||||
// Camera snapshot
|
||||
web_server.on("/snapshot", handle_snapshot);
|
||||
// Camera flash light
|
||||
web_server.on("/flash", HTTP_GET, handle_flash);
|
||||
|
||||
// bootstrap
|
||||
web_server.on("/bootstrap.min.css", HTTP_GET, []()
|
||||
|
||||
Reference in New Issue
Block a user