Last active
May 22, 2023 00:14
-
-
Save hollyhockberry/174749a9963e9637966161c7afb9bee6 to your computer and use it in GitHub Desktop.
Sample: Using Whisper API with M5 CoreS3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2023 Inaba (@hollyhockberry) | |
// This software is released under the MIT License. | |
// http://opensource.org/licenses/mit-license.php | |
#include <SD.h> | |
#include <M5Unified.h> | |
#include <WiFi.h> | |
#include <HTTPClient.h> | |
#include <ArduinoJson.h> | |
#include <gob_unifiedButton.hpp> | |
constexpr char* ROOT_CA = "openai.comの証明書"; | |
constexpr char* API_KEY = "API KEY"; | |
gob::UnifiedButton unfiedButton; | |
bool transcriptions(File& file, String* result) { | |
char boundary[64] = "------------------------"; | |
for (auto i = 0; i < 2; ++i) { | |
ltoa(random(0x7fffffff), boundary + strlen(boundary), 16); | |
} | |
const char* API_HOST = "api.openai.com"; | |
const uint16_t API_PORT = 443; | |
const char* API_PATH = "/v1/audio/transcriptions"; | |
WiFiClientSecure client; | |
client.setCACert(ROOT_CA); | |
if (!client.connect(API_HOST, API_PORT)) { | |
Serial.println("connection failed"); | |
return false; | |
} | |
const String header = "--" + String(boundary) + "\r\n" | |
"Content-Disposition: form-data; name=\"model\"\r\n\r\nwhisper-1\r\n" | |
"--" + String(boundary) + "\r\n" | |
"Content-Disposition: form-data; name=\"file\"; filename=\"" + file.name() + "\"\r\n" | |
"Content-Type: application/octet-stream\r\n\r\n"; | |
const String footer = "\r\n--" + String(boundary) + "--\r\n"; | |
// header | |
client.printf("POST %s HTTP/1.1\n", API_PATH); | |
client.printf("Host: %s\n", API_HOST); | |
client.println("Accept: */*"); | |
client.printf("Authorization: Bearer %s\n", API_KEY); | |
client.printf("Content-Length: %d\n", header.length() + file.size() + footer.length()); | |
client.printf("Content-Type: multipart/form-data; boundary=%s\n", boundary); | |
client.println(); | |
client.print(header.c_str()); | |
client.flush(); | |
// body | |
uint8_t buf[512]; | |
while (file.available()) { | |
const auto sz = file.read(buf, sizeof(buf)); | |
client.write(buf, sz); | |
client.flush(); | |
} | |
client.flush(); | |
file.close(); | |
// footer | |
client.print(footer.c_str()); | |
client.flush(); | |
// wait response | |
while (client.available() == 0) { | |
} | |
bool isBody = false; | |
String body = ""; | |
while(client.available()){ | |
const auto line = client.readStringUntil('\r'); | |
if (isBody) { | |
body += line; | |
} else if (line.equals("\n")) { | |
isBody = true; | |
} | |
} | |
client.stop(); | |
StaticJsonDocument<200> doc; | |
deserializeJson(doc, body); | |
const auto text = doc["text"].as<String>(); | |
if (text.length() <= 0) { | |
return false; | |
} | |
*result = text; | |
return true; | |
} | |
void setup() { | |
M5.begin(); | |
unfiedButton.begin(&M5.Display); | |
SD.begin(GPIO_NUM_4, SPI, 25000000); | |
WiFi.begin(); | |
while (WiFi.status() != WL_CONNECTED) { | |
::delay(500); | |
} | |
Serial.println("WiFi connected"); | |
::randomSeed(::analogRead(G6)); | |
} | |
void loop() { | |
unfiedButton.update(); | |
M5.update(); | |
if (!M5.BtnA.wasPressed()) { | |
return; | |
} | |
File f = SD.open("/sample.wav"); | |
if (!f) { | |
Serial.println("file open error"); | |
return; | |
} | |
String text; | |
if (transcriptions(f, &text)) { | |
Serial.println(text); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment