# ESP32-CAM Video Recorder: time-lapse AVI on an SD card, served over the browser

> This GPL-3.0 Arduino sketch records MJPEG frames from an ESP32-CAM into an AVI file on the SD card, with web configuration, a download link instead of FTP, and a Telegram bot. It suits a maker with a cheap camera board, and the repository carries a version per Arduino core release because the camera API kept changing.

**jameszah/ESP32-CAM-Video-Recorder** — Video Recorder for ESP32-CAM with http server for config and ftp (or http) server to download video

- Repository: https://github.com/jameszah/ESP32-CAM-Video-Recorder
- Stars: 527 · Forks: 105
- Language: C++
- License: GPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/jameszah-esp32-cam-video-recorder

## What it records, and where it puts it

ESP32-CAM Video Recorder is a program that records an MJPEG AVI video on the SD Card of an ESP32-CAM, written by James Zahary and dated July 20, 2019 in the source header.

The AVI container is the choice that matters here. The ESP32-CAM's camera produces JPEGs, one frame at a time, and a naive recorder would write a directory of numbered files and leave the user to assemble them. Writing an AVI with an MJPEG stream instead means the output is a single file that any player will open, and that a recording session is one artefact rather than thousands of loose frames. It also means the index is part of the file, which is why the readme spends time on what happens when a frame is corrupt.

The camera is the OV2640, which is what an ESP32-CAM board carries, and the board is a microcontroller with a camera and a WiFi radio, so the whole system is a single cheap device that records unattended onto a memory card with no host machine involved.

The licence is GNU General Public License v3.0, the primary language is C++, and the default branch is master. There are no GitHub releases, and the last push to the repository was on 2026-06-08.

The repository tree is organised by version rather than by component. There are vA1/, v99/, v98/ and v98-WiFiMan/ directories, which are the released variants, an old/ directory, a sample/ directory with a samples file, and a sample-output/ directory. The images at the root, the demo photographs and the de-soldering pictures, are documentation rather than code.

## One folder per Arduino core version, and why that matters

The most important thing in the readme is three lines near the top, and they are a compatibility table rather than a changelog:

```text
vA1 for arduino-esp32 2.0.2  
v99 for arduino-esp32 1.0.6   
v98 for arduino-esp32 1.0.4   
```

The reason there are three is that the camera API in the ESP32 Arduino core kept changing, and each of the changes was significant enough to require different code. The readme explains the last of them in the January 2022 entry, where the switch to arduino-esp32 2.0.2 was described as bringing some nicer camera code that clears away little glitches that used to pop up, with the comment that it is very clean now.

So the version in the folder name is not a project version, it is a mapping to the core you have installed in the Arduino IDE, and choosing the wrong folder means the sketch will not compile against your core or will behave differently from the documentation. The March 2021 entry makes the recommendation explicit, that it would be best to use arduino-esp32 1.04 until the author scans through for update problems, because 1.05 was released in late February 2021 with new frame sizes, new aspect ratios and some changes in the WiFi that needed code changes.

The September 2021 entry lists what the 1.0.6 update involved: the frame size numbers changed, which the author had used in the http url command, so those were updated, the new HD frame size of 1280x720 was added, and there were updates for the new SSL libraries to keep the Telegram interface working. It also says you need all the files in the v99 folder, which is a warning that these sketches are multi-file rather than a single sketch file, and that you can still use the previous version with the board library set to 1.0.4.

The January 2022 entry is the current one, and it is the version to start with. Version A1 switched from FTP to HTTP file transfer, pointing at the author's separate ESPxWebFlMgr file manager project, made the changes for arduino-esp32 1.06 to 2.02, added a link to Telegram to download a completed AVI with one click, deleted the low-voltage handler on the grounds that it serves no purpose, and got rid of the touch support because it was not much used.

A later entry, from January 17, 2022, is a small update to fix the file delete when the disk is full, which the arduino-esp32 2.0.2 required.

## Configuration, the SD card housekeeping and the compile switches

The configuration story is worth understanding because it is split across two mechanisms, and the readme is explicit about which is which.

You can hardcode your SSID and password into settings.h, or put in a one character long SSID and the sketch will use WiFiManager to set your SSID and password. If you want the Telegram bot to work, you still have to hardcode them into settings.h.

So WiFiManager covers the network credentials and nothing else, and the Telegram bot credentials are hardcoded whatever happens. The reason for the one character SSID is that WiFiManager is driven through a captive portal at 192.168.4.1 during setup, and the sketch is probably in station mode with a placeholder SSID at that moment.

The WiFiManager route has a documented gotcha. The only difference from the previous version is that you have to reboot the ESP32 after you have set the SSID and password for it to work correctly, and there is a link to the WiFiManager issue about it. You also need the latest WiFiManager code, currently 2.0.3-alpha, installed from the Arduino IDE's Manage Libraries.

The readme is also candid about a limitation of the WiFiManager approach. The WiFiManager could be enhanced to set parameters that cannot be set over HTTP, such as the Telegram name and password, but that has not been done yet.

Storage is handled automatically, and the September 2020 entry describes it. Version 98 added a feature to automatically delete your oldest day of videos when the SD card reaches 90 percent full. That is a retention policy, not a disk-full panic, and it means the recorder is unattended-safe in a way that a card filling up would otherwise not be.

The other configuration mechanism is the compile directives. There are compile directives in the settings.h file to cut out entire sections of code, such as the FTP or the Telegram support, if you need the resources to add your own stuff. On a board with limited memory, removing the Telegram client and the HTTPS stack is the difference between a program that fits and one that does not, and doing it with a preprocessor switch rather than by deleting files keeps the change reviewable.

## Downloading the video, and the Telegram notification

The HTTP file transfer replaced the FTP server, and that is the change that makes the project much easier to use.

The readme puts it plainly: you can download the videos to your computer or phone with just a click on the file from your browser, with no need for an FTP program anymore. The web interface already existed for configuration, so the change was to add a file listing and a download path to the same server, using the author's own ESPxWebFlMgr project for the file management side.

The Telegram bot is the notification half. If the Telegram bot is turned on, it sends the Telegram app the first frame of a new recording, and gives a link to the previous recording for you to download to your phone or computer with one click. That is a small design decision with a large effect on an unattended device: you get told when something happened, and you get a link, and the link is an HTTP URL that the same server serves.

The alternative designs are all present in the repository as spin-offs, and the readme points at them, which is a good way to see the same problem solved for different requirements. The ESP32-CAM-Video-Recorder-junior project is the newer, quicker version with fewer features, described as simple fast recording and streaming with HTTP just for information, no controls and no FTP. The ESP32-CAM-Video-Telegram project records a video and sends it to your Telegram account with no SD card at all, on request or on a PIR event, using the Telegram interface, and it is described as a new program to check out.

The September 2020 entry describes what the junior version drops: wifi, http, time, ftp, telegram, pir and touch, leaving something that just records very fast, at pretty much the full speed of the camera, with a decent SD card and reasonable quality parameters. The latest version of junior adds back the streaming video and a series of photos over WiFi, and records at 6 fps in UXGA and 24 fps in SVGA, while otherwise remaining uncomplicated.

The topic list also includes PIR, which is the passive infrared sensor trigger, and that is what the Telegram variant uses to start a recording when somebody walks past.

## Bad frames, quality settings and the live view

The most interesting piece of engineering in the readme is the handling of corrupt frames, and it is worth reading because the failure it prevents is subtle.

The August 2020 entry, for version 94, describes a feature to filter out bad JPEGs. The explanation is that this happens when you have high quality JPEG settings and then take a movie in bright light, and some of the JPEGs exceed the memory allocated, and you get a partial JPEG. That partial frame will screw up the index and break an entire AVI, so there is now code to find those bad JPEGs and get a new frame that is good, with a link to the Espressif issue about the camera driver.

This is a good example of a failure that is invisible in a unit test and fatal in the field. A truncated JPEG is still a file, the file is still written, and the recorder has no way to know the image is incomplete, so the AVI index ends up pointing at a frame that does not decode and the whole recording is unplayable. Detecting it at write time and substituting a good frame is the only recovery.

The quality discussion that follows is a nice illustration of a counter-intuitive knob. It is safe to increase the JPEG quality to 7, maybe 6, from the standard setting of 10, or 12 in bright sun, because a lower number is higher quality. Higher quality means more bytes, bigger files and slower writes, and the readme notes it is debatable whether you want very high quality JPEGs if they are flashing along at 24 frames per second.

The live view is the other feature from that release. There is a single frame on the main status screen so you can see what the camera sees, and the streaming has been very much requested to get a better look through the viewfinder and maybe to save the stream. You set a parameter in settings.h of milliseconds between updates, and then use the stream link on the main page.

The remaining caveat in the readme is the one every user should act on. More commentary coming, and refinements, and test it before you use it.

## Conclusion

ESP32-CAM Video Recorder is worth using if you have a spare ESP32-CAM and want unattended time-lapse capture on a cheap card, because the recording loop writes directly to the SD card as an AVI without a host in the loop, because the browser download replaced the FTP server that earlier versions needed, and because the Telegram integration gives you a notification and a one-click link without opening a port to the device. It is the wrong tool if you want a proper camera pipeline. Before you flash it, check three things: that you pick the version folder that matches your Arduino core, because the repository ships one for arduino-esp32 2.0.2, one for 1.0.6 and one for 1.0.4, and the camera API changed between them, so the wrong folder will not compile or will record badly; that you read the settings.h file rather than assuming the defaults, since the WiFi credentials, the Telegram bot name and password and the compile directives that switch off whole features all live there, and the WiFiManager path only covers the WiFi setup; and that you check the storage behaviour, because the recorder deletes the oldest day of videos once the card reaches 90 percent full and the readme is explicit that you should test it before you use it.

## FAQ

### How do I build the ESP32-CAM Video Recorder for my Arduino core version?

The repository ships one folder per Arduino core release, with vA1 for arduino-esp32 2.0.2, v99 for 1.0.6 and v98 for 1.0.4, because the camera API changed between those releases. You need all the files in the chosen folder, not just the sketch, and the readme notes that arduino-esp32 2.0.2 brought cleaner camera code that fixes glitches that used to appear.

### How do I configure the WiFi and the Telegram bot?

You can hardcode your SSID and password into settings.h, or put in a one character long SSID and the sketch will use WiFiManager to set them through its normal procedure at 192.168.4.1, though you then have to reboot the ESP32 for it to take effect. The Telegram bot credentials always have to be hardcoded into settings.h, because the WiFiManager setup cannot set parameters that are not configured over HTTP.

### How does the recorder handle a full SD card and corrupt frames?

Version 98 added a feature that automatically deletes the oldest day of videos once the SD card reaches 90 percent full, and a later update fixed the file deletion when the disk is full that arduino-esp32 2.0.2 required. Separately, there is code that filters out bad JPEGs, because a partial frame caused by insufficient memory in bright light would break the AVI index and the whole recording, so the recorder detects it and fetches a good frame instead.

## Sources

- [Issues](https://github.com/jameszah/ESP32-CAM-Video-Recorder/issues)
- [jameszah/ESP32-CAM-Video-Recorder on GitHub](https://github.com/jameszah/ESP32-CAM-Video-Recorder)
- [License: GPL-3.0](https://github.com/jameszah/ESP32-CAM-Video-Recorder/blob/master/LICENSE)
- [README](https://github.com/jameszah/ESP32-CAM-Video-Recorder/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jameszah-esp32-cam-video-recorder
