ESP32-CAM video to SD Card

Hello.

I am in need for a system that generates five minute videos and saves them to an SD card (for example, when I turn it on, it will record five minute videos until I turn it off, in which case the video being taken will not be saved).
I have purchased the ESP32-CAM which has an incorporated OV2640 camera and an adapter (https://www.amazon.com/ESP32-CAM-MB-Aideepen-ESP32-CAM-Bluetooth-Arduino/dp/B08P2578LV/ref=sr_1_1_sspa?crid=3BSBMRLKRS6PL&keywords=esp32%2Bcam&qid=1679409702&sprefix=esp32%2Bcam%2Caps%2C174&sr=8-1-spons&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFIMlRCRkQxMUg0Q0kmZW5jcnlwdGVkSWQ9QTEwMjc0NTQzUEtaWUxXU08wVkJJJmVuY3J5cHRlZEFkSWQ9QTA1NDcwNDczNkVVTEZMMDZWUzZSJndpZGdldE5hbWU9c3BfYXRmJmFjdGlvbj1jbGlja1JlZGlyZWN0JmRvTm90TG9nQ2xpY2s9dHJ1ZQ&th=1).

I have searched for ways to save videos to the SD card but have only found a code that saves an image with flash whenever a button is pushed. This is the code for that in case it is of use:

/*
  ESP32 CAM Camera with MicroSD storage
  esp32cam-microsd.ino
  Take picture when button pressed
  Store image on MicroSD card
 
  DroneBot Workshop 2022
  https://dronebotworkshop.com
*/
// Include Required Libraries
 
// Camera libraries
#include "esp_camera.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
 
// MicroSD Libraries
#include "FS.h"
#include "SD_MMC.h"
 
// EEPROM Library
#include "EEPROM.h"
 
// Use 1 byte of EEPROM space
#define EEPROM_SIZE 1
 
// Counter for picture number
unsigned int pictureCount = 0;
 
// Pin definitions for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22
 
void configESPCamera() {
  // Configure Camera parameters
 
  // Object to store the camera configuration parameters
  camera_config_t config;
 
  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_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG; // Choices are YUV422, GRAYSCALE, RGB565, JPEG
 
  // Select lower framesize if the camera doesn't support PSRAM
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
    config.jpeg_quality = 10; //10-63 lower number means higher quality
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }
 
  // Initialize the Camera
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
 
  // Camera quality adjustments
  sensor_t * s = esp_camera_sensor_get();
 
  // BRIGHTNESS (-2 to 2)
  s->set_brightness(s, 0);
  // CONTRAST (-2 to 2)
  s->set_contrast(s, 0);
  // SATURATION (-2 to 2)
  s->set_saturation(s, 0);
  // SPECIAL EFFECTS (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
  s->set_special_effect(s, 0);
  // WHITE BALANCE (0 = Disable , 1 = Enable)
  s->set_whitebal(s, 1);
  // AWB GAIN (0 = Disable , 1 = Enable)
  s->set_awb_gain(s, 1);
  // WB MODES (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
  s->set_wb_mode(s, 0);
  // EXPOSURE CONTROLS (0 = Disable , 1 = Enable)
  s->set_exposure_ctrl(s, 1);
  // AEC2 (0 = Disable , 1 = Enable)
  s->set_aec2(s, 0);
  // AE LEVELS (-2 to 2)
  s->set_ae_level(s, 0);
  // AEC VALUES (0 to 1200)
  s->set_aec_value(s, 300);
  // GAIN CONTROLS (0 = Disable , 1 = Enable)
  s->set_gain_ctrl(s, 1);
  // AGC GAIN (0 to 30)
  s->set_agc_gain(s, 0);
  // GAIN CEILING (0 to 6)
  s->set_gainceiling(s, (gainceiling_t)0);
  // BPC (0 = Disable , 1 = Enable)
  s->set_bpc(s, 0);
  // WPC (0 = Disable , 1 = Enable)
  s->set_wpc(s, 1);
  // RAW GMA (0 = Disable , 1 = Enable)
  s->set_raw_gma(s, 1);
  // LENC (0 = Disable , 1 = Enable)
  s->set_lenc(s, 1);
  // HORIZ MIRROR (0 = Disable , 1 = Enable)
  s->set_hmirror(s, 0);
  // VERT FLIP (0 = Disable , 1 = Enable)
  s->set_vflip(s, 0);
  // DCW (0 = Disable , 1 = Enable)
  s->set_dcw(s, 1);
  // COLOR BAR PATTERN (0 = Disable , 1 = Enable)
  s->set_colorbar(s, 0);
 
}
 
void initMicroSDCard() {
  // Start the MicroSD card
 
  Serial.println("Mounting MicroSD Card");
  if (!SD_MMC.begin()) {
    Serial.println("MicroSD Card Mount Failed");
    return;
  }
  uint8_t cardType = SD_MMC.cardType();
  if (cardType == CARD_NONE) {
    Serial.println("No MicroSD Card found");
    return;
  }
 
}
 
void takeNewPhoto(String path) {
  // Take Picture with Camera
 
  // Setup frame buffer
  camera_fb_t  * fb = esp_camera_fb_get();
 
  if (!fb) {
    Serial.println("Camera capture failed");
    return;
  }
 
  // Save picture to microSD card
  fs::FS &fs = SD_MMC;
  File file = fs.open(path.c_str(), FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file in write mode");
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
  }
  // Close the file
  file.close();
 
  // Return the frame buffer back to the driver for reuse
  esp_camera_fb_return(fb);
}
 
void setup() {
 
  // Disable brownout detector
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
 
  // Start Serial Monitor
  Serial.begin(115200);
 
  // Initialize the camera
  Serial.print("Initializing the camera module...");
  configESPCamera();
  Serial.println("Camera OK!");
 
  // Initialize the MicroSD
  Serial.print("Initializing the MicroSD card module... ");
  initMicroSDCard();
 
  // initialize EEPROM with predefined size
  EEPROM.begin(EEPROM_SIZE);
  pictureCount = EEPROM.read(0) + 1;
 
  // Path where new picture will be saved in SD Card
  String path = "/image" + String(pictureCount) + ".jpg";
  Serial.printf("Picture file name: %s\n", path.c_str());
 
  // Take and Save Photo
  takeNewPhoto(path);
 
  // Update EEPROM picture number counter
  EEPROM.write(0, pictureCount);
  EEPROM.commit();
 
  // Bind Wakeup to GPIO13 going LOW
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
 
  Serial.println("Entering sleep mode");
  delay(1000);
 
  // Enter deep sleep mode
  esp_deep_sleep_start();
 
}
 
void loop() {
 
}

Saving a series of still images is the only option with the ESP32-CAM.

For video, get a GoPro camera or similar.

1 Like

Hi, thanks for your information. This series of images could be done at a very high rate (fps), and thus produce a video in images. In this case, I would need to modify the code I found so that images are saved without the need of a button. Is there any way to change this code for the one I need?

So you have code to save an image to SD. Choose the resolution you want and add a bit of code that times how long it takes to save one image to SD.

Is then the save time, for one image, short enough to give you the 'very high rate (fps)' you want ?

1 Like

Yes, exactly. What I don't know how to do is to remove the code where the button is needed to be pressed to take a photo; and change it so that it starts taking photos immediately and indefinitely until I turn it off.

Does it matter, all you need is working code that saves an image to SD, there must be heaps of examples ?

Find in the code where it saves the file SD, this is pseudo code and not tested;

uint32_t startms = millis();

// start save image to sd

//image save to sd finished

Serial.print("Save time ");
Serial.print(millis() - startms);
Serial.println("mS");
1 Like

Good ESP32-CAM tutorials at randomnerdtutorials.com

What I don't know how to do is to remove the code where the button is needed

Just cut out anything to do with the button. If you want to continue with this hobby, it would be a great idea to learn the programming language.

1 Like

this is not related to your question, but it'd good to know: in that link above, you can remove everything from the question mark to the end. if you do that it will show up as an embedded link with a picture and a description

everything from the question mark to the end is related to the ebay session where you got the link, not to the product.

Why do you need a button to operate?Are you going to sit by it to press a button 24/7?why not think of automatic operation?For still image taking there are many options.This module is designed to remote operations such as surveillance, security.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.