Skip to content

Commit

Permalink
Add integration example: Record MP4 + HTTP Post Request to Whisper Se…
Browse files Browse the repository at this point in the history
…rver. (#222)

Press record button for 2s to trigger recording of MP4.
Upon recording stop, HTTP Post Request MP4 file to Whisper Server.
Whisper Server returns the transcribed audio in Serial Monitor.
  • Loading branch information
Kyderio authored Mar 6, 2024
1 parent 2303d49 commit 99be127
Showing 1 changed file with 189 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
Example guide:
TBD
*/

#include "StreamIO.h"
#include "AudioStream.h"
#include "AudioEncoder.h"
#include "MP4Recording.h"
#include "WiFi.h"
#include "AmebaFatFS.h"
#include "Base64.h"

#define FILENAME "TestRecordingAudioOnly.mp4"

char ssid[] = "Network_SSID"; // your network SSID (name)
char pass[] = "Password"; // your network password
int status = WL_IDLE_STATUS;

char server[] = "192.168.3.4"; // your server IP running HTTP server on PC

AmebaFatFS fs;
WiFiClient wifiClient;

char buf[512];
char *p;
String filepath;
File file;

// Default audio preset configurations:
// 0 : 8kHz Mono Analog Mic
// 1 : 16kHz Mono Analog Mic
// 2 : 8kHz Mono Digital PDM Mic
// 3 : 16kHz Mono Digital PDM Mic

AudioSetting configA(0);
Audio audio;
AAC aac;
MP4Recording mp4;
StreamIO audioStreamer1(1, 1); // 1 Input Audio -> 1 Output AAC
StreamIO audioStreamer2(1, 1); // 1 Input AAC -> 1 Output MP4
const int buttonPin = 2; // the number of the pushbutton pin

int buttonState; // variable for reading the pushbutton status
unsigned long buttonPressTime = 0; // variable to store the time when button was pressed
bool buttonPressedFor2Seconds = false; // flag to indicate if button is pressed for at least 2 seconds
int recordingstate = -1;
int previousRecordingState = -1;


void setup()
{
Serial.begin(115200);

// Connection to internet
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(2000);
}

// list files under root directory
fs.begin();

// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_G, OUTPUT);

// Configure audio peripheral for audio data output
audio.configAudio(configA);
audio.begin();
// Configure AAC audio encoder
aac.configAudio(configA);
aac.begin();

// Configure MP4 recording settings
mp4.configAudio(configA, CODEC_AAC);
mp4.setRecordingDuration(5);
mp4.setRecordingFileCount(1);
mp4.setRecordingFileName("TestRecordingAudioOnly");
mp4.setRecordingDataType(STORAGE_AUDIO); // Set MP4 to record audio only

// Configure StreamIO object to stream data from audio channel to AAC encoder
audioStreamer1.registerInput(audio);
audioStreamer1.registerOutput(aac);
if (audioStreamer1.begin() != 0) {
Serial.println("StreamIO link start failed");
}

// Configure StreamIO object to stream data from AAC encoder to MP4
audioStreamer2.registerInput(aac);
audioStreamer2.registerOutput(mp4);
if (audioStreamer2.begin() != 0) {
Serial.println("StreamIO link start failed");
}
}

void loop()
{
// Button state
int newButtonState = digitalRead(buttonPin);
if (newButtonState != buttonState) {
buttonPressTime = millis();
}
// update button state
buttonState = newButtonState;

// update recording state
recordingstate = (int)(mp4.getRecordingState());

// check if the button has been held for at least 2 seconds
if (buttonState == HIGH && millis() - buttonPressTime >= 2000) {
// button has been pressed for at least 2 seconds
buttonPressedFor2Seconds = true;
} else {
// button was released before 2 seconds
buttonPressedFor2Seconds = false;
}
// if button has been pressed for at least 2 seconds
if (buttonPressedFor2Seconds) {
if (recordingstate == 1) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
mp4.begin();
Serial.println("Recording");
}
}
if (recordingstate == 1 && previousRecordingState == 0) {
// Change from 0 to 1
digitalWrite(LED_BUILTIN, HIGH);
} else if (recordingstate == 0 && previousRecordingState == 1) {
// Change from 1 to 0
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
encodeMP4andsendHttpPostRequest();
}

// Check if there are incoming bytes available from the server
while (wifiClient.available()) {
char c = wifiClient.read();
Serial.write(c);
}
previousRecordingState = recordingstate;
delay(10);
}

void encodeMP4andsendHttpPostRequest()
{
memset(buf, 0, sizeof(buf));
fs.readDir(fs.getRootPath(), buf, sizeof(buf));
filepath = String(fs.getRootPath()) + String(FILENAME);
p = buf;
while (strlen(p) > 0) {
/* list out file name image will be saved as "TestRecordingAudioOnly.mp4"*/
if (strstr(p, FILENAME) != NULL) {
Serial.println("[INFO] Found 'TestRecordingAudioOnly.mp4' in the string.");
Serial.println("[INFO] Processing file...");
} else {
// Serial.println("Substring 'image.jpg' not found in the
// string.");
}
p += strlen(p) + 1;
}
uint8_t *fileinput;
file = fs.open(filepath);
unsigned int fileSize = file.size();
fileinput = (uint8_t *)malloc(fileSize + 1);
file.read(fileinput, fileSize);
fileinput[fileSize] = '\0';
file.close();

// Encode the file data as Base64
int encodedLen = base64_enc_len(fileSize);
char *encodedData = (char *)malloc(encodedLen);
base64_encode(encodedData, (char *)fileinput, fileSize);

if (wifiClient.connect(server, 8000)) {
wifiClient.println("POST /audio HTTP/1.1");
wifiClient.println("Host: " + String(server));
wifiClient.println("Content-Type: application/x-www-form-urlencoded"); // Use appropriate content type
wifiClient.println("Content-Length: " + String(encodedLen)); // Specify the length of the content
wifiClient.println("Connection: keep-alive");
wifiClient.println(); // Empty line indicates the end of headers
wifiClient.print(encodedData); // Send the Base64 encoded audio data directly
Serial.println("Binary sent");
}
}

0 comments on commit 99be127

Please sign in to comment.