Hi guys, I'm trying to stream video using the IP address but what I get when I access the browser (Google Chrome) is a white screen.
I have been using the board for capturing pictures (using the same code below but different function for streaming: void startCameraServer_stream()) and it works just fine.
Setting:
USB CDC On Boot ---> Enabled
Flash Size ---> 8MB(64Mb)
Partition Scheme ---> 8M with spiffs (3MB APP/1.5MB SPIFFS)
PSRAM ---> OPI PSRAM
Could you help me to figure out what I'm missing? (Below the code)
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
#include "esp_camera.h"
#include "esp_system.h"
#include <WiFi.h>
const char *ssid = "*****"; //wifi name
const char *password = "*****";//wifi password
AsyncWebServer server(80);
#define CAMERA_MODEL_ESP32S3_EYE //it is designed for facial recognition and AI applications.
#if defined(CAMERA_MODEL_ESP32S3_EYE)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 4
#define SIOC_GPIO_NUM 5
#define Y2_GPIO_NUM 11
#define Y3_GPIO_NUM 9
#define Y4_GPIO_NUM 8
#define Y5_GPIO_NUM 10
#define Y6_GPIO_NUM 12
#define Y7_GPIO_NUM 18
#define Y8_GPIO_NUM 17
#define Y9_GPIO_NUM 16
#define VSYNC_GPIO_NUM 6
#define HREF_GPIO_NUM 7
#define PCLK_GPIO_NUM 13
#else
#error "Camera model not selected"
#endif
void startCameraServer_stream(); // Video only
void camera_settings();
int camera_cfg();
void wifi();
void setup() {
Serial.begin(115200);
if(camera_cfg()) { //Setting PINs configuration for camera
wifi();
camera_settings();
Serial.println("Camera sensor settings applied");
startCameraServer_stream();
}
else Serial.print("Fail!");
}
void loop() {
delay(1000);
}
int camera_cfg(){
camera_config_t config;
// Camera pins configuration for ESP32-S3
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
/*FRAMESIZE_UXGA (1600 x 1200)
FRAMESIZE_QVGA (320 x 240)
FRAMESIZE_CIF (352 x 288)
FRAMESIZE_VGA (640 x 480)
FRAMESIZE_SVGA (800 x 600)
FRAMESIZE_XGA (1024 x 768)
FRAMESIZE_SXGA (1280 x 1024)*/
config.frame_size = FRAMESIZE_VGA; //UXGA less quality -> frame too big, VGA and SBGA smaller frame better quality
config.pixel_format = PIXFORMAT_JPEG; // Medium quality video
//config.pixel_format = PIXFORMAT_RGB565; // High quality video. Not working for capture
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; //good for picture, for video CAMERA_GRAB_LATEST
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 10; //The lower it is, the higher the quality
config.fb_count = 2; //1-> best value so far. 2 and 3 not great
// Initialize the camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.print("Camera init failed with error 0x");
Serial.println(err, HEX);
return 0;
}
Serial.println("Camera initialized");
return 1;
}
void camera_settings(){
sensor_t *s = esp_camera_sensor_get();
if (!s) {
Serial.println("Failed to get camera sensor");
return;
}
//Additional sensor settings for better quality
s->set_brightness(s, 0); // -2 to 2
s->set_contrast(s, 0); // -2 to 2
s->set_saturation(s, 0); // -2 to 2
s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_whitebal(s, 1); // 0 = disable , 1 = enable
s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_aec2(s, 0); // 0 = disable , 1 = enable
s->set_ae_level(s, 0); // -2 to 2
s->set_aec_value(s, 300); // 0 to 1200
s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_agc_gain(s, 0); // 0 to 30
s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6
s->set_bpc(s, 0); // 0 = disable , 1 = enable
s->set_wpc(s, 1); // 0 = disable , 1 = enable
s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
s->set_lenc(s, 1); // 0 = disable , 1 = enable
s->set_hmirror(s, 1); // 0 = disable , 1 = enable
s->set_vflip(s, 1); // 0 = disable , 1 = enable
s->set_dcw(s, 1); // 0 = disable , 1 = enable
s->set_colorbar(s, 0); // 0 = disable , 1 = enable
}
void wifi(){
WiFi.mode(WIFI_STA); //to make sure that it connects to a router
WiFi.begin(ssid, password);
delay(100);
WiFi.setSleep(false); // to disable the Wi-Fi sleep mode. By default, the ESP32 might enter a sleep mode to conserve power when it’s not actively transmitting or receiving data.
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
Serial.print("Wifi-status: ");
Serial.println(WiFi.status()); //Check wifi status
}
Serial.println("Connected to Wi-Fi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
}
void startCameraServer_stream() { //for streaming video
// Set up the server to stream MJPEG video
server.on("/stream", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html",
"<html><body><img src='/mjpeg_stream'></body></html>");
});
server.on("/mjpeg_stream", HTTP_GET, [](AsyncWebServerRequest *request){
AsyncWebServerResponse *response = request->beginChunkedResponse("multipart/x-mixed-replace; boundary=frame",
[](uint8_t *buffer, size_t maxLen, size_t index) -> size_t {
camera_fb_t *fb = esp_camera_fb_get(); // Capture a frame from the camera
if (!fb) {
Serial.println("Camera capture failed");
return 0;
}
size_t len = fb->len;
if (len > maxLen) {
len = maxLen;
}
memcpy(buffer, fb->buf, len); // Copy frame data to buffer
esp_camera_fb_return(fb); // Return the frame buffer
return len;
});
response->addHeader("Access-Control-Allow-Origin", "*");
request->send(response);
});
server.begin();
Serial.println("Camera server started"); //Use http://IP-address/stream for video
}