Sending video(.avi) and audio (.wav) files from ESP32 via http post multipart/form-data to server

nmot20
Posts: 2
Joined: Tue Mar 12, 2024 5:53 pm

Sending video(.avi) and audio (.wav) files from ESP32 via http post multipart/form-data to server

Postby nmot20 » Tue Mar 12, 2024 6:05 pm

Hi, I really love the features of ESP32. However, I can't find a method of sending .avi and .wav files generated on the board and stored on the sd card via http post multipart/form-data.

Board: XIAO ESP32S3 (Sense)

UseCase: I would like to use a Arduino script to record both video and audio with the board, store them temporarily on the sd card and then send them via http post multipart/form-data to a server that processes the data further. The two files together are smaller than 1 megabyte.

Problem: Recording a video as an .avi file, recording audio as a .wav file and saving both files on the sd card works fine without any problems. The structure of the post request is also valid and works as well. In addition, the request contains a json generated in the script (sending the json as part of the request already works). However, I do not know how to attach the .avi and .wav file to the request. Simply adding the files as a string does not work.

Question: How can I send .avi and .wav as part of the http post multipart/form-data request? Is there a way to attach the files read directly from the SD card to the request?

Code example: Below you can find a minimal code example (Arduino) that establishes a wifi connection, retrieves the two files from the SD card, generates a json and sets up the request. What is missing is the way the files are sent with the request.

I am happy to hear about any suggestions for solutions.
  1. #include <WiFi.h>
  2. #include <HTTPClient.h>
  3. #include <ArduinoJson.h>
  4.  
  5. const char* ssid = "...";
  6. const char* password = "...";
  7.  
  8. const char* serverAddress = "...";
  9.  
  10. const char* aviFilePath = "/video0.avi";
  11. const char* wavFilePath = "/arduino_rec.wav";
  12.  
  13. //SD
  14. #include "FS.h"
  15. #include "SD.h"
  16. #include "SPI.h"
  17. const int SD_PIN_CS = 21;
  18. bool sd_sign = false;
  19. File videoFile;
  20. File audioFile;
  21.  
  22. void setup() {
  23.   Serial.begin(115200);
  24.  
  25.   // Connect to Wi-Fi
  26.   WiFi.begin(ssid, password);
  27.   while (WiFi.status() != WL_CONNECTED) {
  28.     delay(1000);
  29.     Serial.println("Connecting to WiFi...");
  30.   }
  31.   Serial.println("Connected to WiFi");
  32.  
  33.   //Setup SD Card
  34.   // Initialize the SD card
  35.   if (!SD.begin(SD_PIN_CS)) {
  36.     Serial.println("SD card initialization failed!");
  37.     return;
  38.   }
  39.  
  40.   uint8_t cardType = SD.cardType();
  41.  
  42.   // Determine if the type of SD card is available
  43.   if(cardType == CARD_NONE){
  44.     Serial.println("No SD card attached");
  45.     return;
  46.   }
  47.  
  48.   Serial.print("SD Card Type: ");
  49.   if(cardType == CARD_MMC){
  50.     Serial.println("MMC");
  51.   } else if(cardType == CARD_SD){
  52.     Serial.println("SDSC");
  53.   } else if(cardType == CARD_SDHC){
  54.     Serial.println("SDHC");
  55.   } else {
  56.     Serial.println("UNKNOWN");
  57.   }
  58.  
  59.   sd_sign = true;
  60. }
  61.  
  62. void loop() {
  63.   if (SD.exists("/video0.avi") == 1 && SD.exists("/arduino_rec.wav") == 1) {
  64.  
  65.     videoFile = SD.open("/video0.avi", FILE_READ);
  66.     audioFile = SD.open("/arduino_rec.wav", FILE_READ);
  67.  
  68.     if ((WiFi.status() == WL_CONNECTED)) { // Check Wi-Fi connection status
  69.  
  70.       StaticJsonDocument<96> movement;
  71.       movement["start_date"] = "2024-03-08 16:03:10.210804";
  72.       movement["end_date"] = "2024-03-08 16:04:10.210804";
  73.       movement["audio"] = "audioKey";
  74.       movement["video"] = "videoKey";
  75.      
  76.       String output;
  77.  
  78.       serializeJson(movement, output);
  79.  
  80.       HTTPClient http;
  81.       http.begin(serverAddress);
  82.  
  83.       // Set headers for multipart/form-data
  84.       String boundary = "----WebKitFormBoundary" + String(random(0xFFFFFF), HEX);
  85.       http.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
  86.  
  87.       String requestBody = "------" + boundary + "\r\n";
  88.       requestBody += "Content-Disposition: form-data; name=\"json\"\r\n\r\n";
  89.       requestBody += output;
  90.       requestBody += "\r\n";
  91.       requestBody += "--" + boundary + "\r\n";
  92.       requestBody += "Content-Disposition: form-data; name=\"videoKey\"; filename=\"video0.avi\"\r\n";
  93.       requestBody += "Content-Type: video/avi\r\n\r\n";
  94.       requestBody += videoFile.readString();
  95.       requestBody += "\r\n";
  96.       requestBody += "--" + boundary + "\r\n";
  97.       requestBody += "Content-Disposition: form-data; name=\"audioKey\"; filename=\"arduino_rec.wav\"\r\n";
  98.       requestBody += "Content-Type: audio/wav\r\n\r\n";
  99.       requestBody += audioFile.readString();
  100.       requestBody += "\r\n";
  101.       requestBody += "--" + boundary + "--\r\n";
  102.  
  103.       // Calculate the content length
  104.       int contentLength = requestBody.length();
  105.  
  106.       // Set the Content-Length header
  107.       http.addHeader("Content-Length", String(contentLength));
  108.  
  109.       // Send the POST request
  110.      int httpResponseCode = http.sendRequest("POST", requestBody);
  111.  
  112.       if (httpResponseCode == HTTP_CODE_OK) {
  113.         Serial.println("Data sent successfully!");
  114.       } else {
  115.         Serial.print("Error sending data. HTTP code: ");
  116.         Serial.println(httpResponseCode);
  117.       }
  118.  
  119.       videoFile.close();
  120.       audioFile.close();
  121.  
  122.       http.end();
  123.       }
  124.     }
  125.     delay(10000);

nmot20
Posts: 2
Joined: Tue Mar 12, 2024 5:53 pm

Re: Sending video(.avi) and audio (.wav) files from ESP32 via http post multipart/form-data to server

Postby nmot20 » Fri Mar 22, 2024 3:17 pm

Solution was found in an Arduino forum post (https://forum.arduino.cc/t/sending-vide ... er/1234706).

lbernstone
Posts: 826
Joined: Mon Jul 22, 2019 3:20 pm

Re: Sending video(.avi) and audio (.wav) files from ESP32 via http post multipart/form-data to server

Postby lbernstone » Sat Mar 23, 2024 5:13 am

Just a couple comments to help you optimize:
1) reading/writing to sd is slow. You can optimize this by making your transfers match the sector size of the device. For sd cards, that is 512 bytes. If you set your buffer to that size, it will read a whole sector at a time, which should be a bit faster.
2) I assume you have psram on your board. If you store your files as large Strings, they should automatically be allocated from the psram. psram is MUCH faster than an sd card, and can take advantage of dma transfers to make it even faster sending your chunks.
3) If you post your code with names redacted, it may help the next person trying to do this. github gists get indexed and work well for this.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 45 guests