Logo

dev-resources.site

for different kinds of informations.

Displaying a video on a ESP32 powered SSD1306 OLED screen

Published at
4/17/2024
Categories
iot
esp32
arduino
ffmpeg
Author
afcm
Categories
4 categories in total
iot
open
esp32
open
arduino
open
ffmpeg
open
Author
4 person written this
afcm
open
Displaying a video on a ESP32 powered SSD1306 OLED screen

In this exemple, I will be using a SSD1306 OLED display driven by the ESP32-WROOM-32.

Getting the video

First, you need a video to display.

In my case, I wanted to display a video available on YouTube, so I used the Parabolic GUI for the yt-dlp project, which allows downloading videos from YouTube and other video streaming services.

IMPORTANT:

Please keep in mind you may not have the right to include a video in your project.

If you want you can also use directly the yt-dlp CLI tool after following the official documentation to install it. This should get you a video file inside the folder you have run the command from:

yt-dlp https://www.youtube.com/watch?v=dQw4w9WgXcQ
Enter fullscreen mode Exit fullscreen mode

Of course, you can use a video from any other source you want.

Getting usable video data

For the next step, we need to get the video as a sequence of images at a 128x64 resolution.

To do this, I will be using the FFmpeg media processing toolkit. You can install it on your system following the official documentation.

You can now run the following:

ffmpeg -i ./My_Video_File.mp4 -s 128x64 -vf fps=15 -ss 0 -t 60 ./My_Video_File_Output/out%4d.png
Enter fullscreen mode Exit fullscreen mode

We can explain the command line like this:

  • -s 128x64 Specify the wanted resolution
  • -vf fps=15 Specify the targeted FPS. Usually, videos are at 25FPS or more, but for such a small screen and limited memory, 15FPS will be enough in most cases.
  • -ss 0 Used to limit the amount of video extracted. Specify the start timestamp, can use several different formats, notably number of seconds or HH:MM:SS
  • -t 60 Used to limit the amount of video extracted. Specify the duration of the video taken after the start timestamp, can use several different formats, notably number of seconds or HH:MM:SS
  • ./My_Video_File_Output/out%4d.png Define where the PNG sequence will be. In that case, they will be named outXXXX.png where XXXX is the frame ID. It is very important you do not overflow the specified number of digits (here 4), or the frames will not be ordered in the next step.

Getting the generated C code

To generate C code, I will be using the image2cpp website, which runs entirely in your browser without a server. You can also close the project source code and run it locally.

In the first step, you can select all images in your sequence.

CAUTION:

Depending on how many images you have, crashes may happen.
In my testing, Firefox crashed when I uploaded 6000 images. Chrome didn't crash, but on my Fedora 39 installation, the xdg-desktop-portal process used by Chrome to select the files wasn't stopping after the files had been uploaded, while taking a huge amount of RAM, requiring me to kill the process.

The image importing process is quite slow and uses a lot of RAM since it's done all at once, which is a downside of the project being web-based. Resizing the video to 128x64 must be done by FFmpeg, even if the website can resize images because it will take too much RAM if you use the website.

After the importation finishes, you will go to the image settings step.

You need to set the background color to white, but the most important setting is the dithering.

IMO Floyd-Steinberg was the best-looking method in my testing.

You can then generate Arduino code that will look like this:

...
// 'outXXXX', 128x64px
const unsigned char epd_bitmap_outXXXX [] PROGMEM = {
  ...
  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x15, 0x55, 0x55, 0x55,
  ...
};

// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 1234)
const int epd_bitmap_allArray_LEN = 123;
const unsigned char* epd_bitmap_allArray[123] = {
  ...
  epd_bitmap_outXXXX,
  ...
};
Enter fullscreen mode Exit fullscreen mode

The epd_bitmap_allArray array will be used to display the video, here it's important to not overflow the digits in the file names, or the images will not be ordered correctly.

Displaying the video

To display the video in a loop using the following libraries:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 0x3C
Adafruit_SSD1306 display(128, 64, &Wire, -1);

// Used to know which frame to display
int t = 0;

void setup() {
  // initialize with the I2C addr 0x3D (for the 128x64)
  display.begin(SSD1306_SWITCHCAPVCC, OLED_RESET);  
  display.clearDisplay(); // Make sure the display is cleared
}

void loop() {
  // Clear the display
  display.clearDisplay();

  // Draw the t frame from the array
  display.drawBitmap(0, 0, epd_bitmap_allArray[t], 128, 64, WHITE);
  display.display();

  // Wait for 1000ms/15FPS
  // If you changed the number of FPS in FFmpeg output, you need to update this for the video to play in real-time
  delay(1000/15);

  // Which frame is next, back to 0 at the end of the array 
  t += 1;
  if (t == epd_bitmap_allArray_LEN) {
    t = 0;
  }
}
Enter fullscreen mode Exit fullscreen mode

IMG_20240201_180928

ESP32 Cabling

Wokwi diagram:

ffmpeg Article's
30 articles in total
Favicon
Desvendando Subprocessos: Criando um Bot de Música com Go
Favicon
Video data IO through ffmpeg subprocess
Favicon
Wisper, ffmpeg을 활용한 비디오 자막 자동 생성
Favicon
Integrating MinIO notifications with your Node.js service, FFmpeg, and Mozilla convert API.
Favicon
Cliet-side WebM/MP4 export from React.js Canavs Animation using ffmpeg.wasm for an Upwork client
Favicon
Reduce bitrate using FFMPEG
Favicon
Add a Watermark to a Video Using VideoAlchemy
Favicon
No Bullshit Guide to Youtube shorts automation in NodeJS, OpenAI, Ollama, ElevanLabs & ffmpeg
Favicon
Building a Video Streaming Platform with Node.js, FFmpeg, and Next.js
Favicon
Record Windows Screen using ffmpeg and convert to time lapse video
Favicon
Introducing Comet: A Free, Cross-Platform Video Converter Powered by FFmpeg
Favicon
Compress, Convert and Trim Videos with Command Line
Favicon
เผื่อใครอยากทำ mp4 to gif แบบคมๆ
Favicon
How to generate thumbnails from video ?
Favicon
Convert .caf to mp3 by Directory
Favicon
FFMPEG
Favicon
Run ffmpeg within a Docker Container: A Step-by-Step Guide
Favicon
New to DEV.to - About me
Favicon
Streaming Video to AWS MediaConnect Using FFmpeg and SRT Protocol: A Complete Guide
Favicon
Displaying a video on a ESP32 powered SSD1306 OLED screen
Favicon
FFMPEG Libraries - RTSP Client Keep Alive
Favicon
From Pixels to Playbacks: Dominate Multimedia with FFmpeg in Python
Favicon
Access webcam by ffmpeg in Windows
Favicon
OSCAR 2022 sea surface velocity streamplot animation
Favicon
Mastering Video Previews: A Guide to Compressed Videos and Thumbnails
Favicon
Dall.E Image Gen, And Size Comparison Of Image Formats
Favicon
AIS vessel density maps with pyspark and h3 and animations with ffmpeg
Favicon
Using Electron to create videos (Canvas + FFmpeg)
Favicon
BMF 📹 + Hugging Face🤗, The New Video Processing BFFs
Favicon
Leveraging GPU Acceleration in BMF for High-Performance Video Processing

Featured ones: