+ {devices.map((device, index) => {
+ return (
+
+ );
+ })}
+
+
+ >
+ );
+}
diff --git a/scripts/wav_over_serial/main.py b/scripts/wav_over_serial/main.py
new file mode 100644
index 0000000..43584f8
--- /dev/null
+++ b/scripts/wav_over_serial/main.py
@@ -0,0 +1,36 @@
+import serial
+import wave
+import time
+
+# Configure your serial port settings
+SERIAL_PORT = '/dev/tty.usbmodem2101' # Update this to your serial port name
+BAUD_RATE = 500000
+CHANNELS = 1
+SAMPLE_RATE = 16000
+SAMPLE_WIDTH = 2 # 16 bits = 2 bytes
+RECORD_SECONDS = 10 # Modify as needed
+
+def main():
+ ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
+ wav_file = wave.open('output.wav', 'wb')
+ wav_file.setnchannels(CHANNELS)
+ wav_file.setsampwidth(SAMPLE_WIDTH)
+ wav_file.setframerate(SAMPLE_RATE)
+
+ try:
+ print("Recording...")
+ start_time = time.time()
+ while (time.time() - start_time) < RECORD_SECONDS:
+ data = ser.read(SAMPLE_RATE * SAMPLE_WIDTH * 2)
+ print(len(data))
+ if data:
+ wav_file.writeframes(data)
+ except KeyboardInterrupt:
+ print("Recording stopped.")
+ finally:
+ ser.close()
+ wav_file.close()
+ print("WAV file has been created.")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/wav_over_serial/requirements.txt b/scripts/wav_over_serial/requirements.txt
new file mode 100644
index 0000000..4d1aaa2
--- /dev/null
+++ b/scripts/wav_over_serial/requirements.txt
@@ -0,0 +1 @@
+pyserial==3.5
\ No newline at end of file
diff --git a/supabase/functions/common/cors.ts b/supabase/functions/common/cors.ts
index 32a1cbe..88f49c9 100644
--- a/supabase/functions/common/cors.ts
+++ b/supabase/functions/common/cors.ts
@@ -3,3 +3,4 @@ export const corsHeaders = {
"Access-Control-Allow-Headers": "authorization, x-client-info, apikey, content-type",
"Access-Control-Max-Age": "3600",
};
+
\ No newline at end of file
diff --git a/supabase/functions/process-audio/index.ts b/supabase/functions/process-audio/index.ts
index 9c9d1f4..caa64f8 100644
--- a/supabase/functions/process-audio/index.ts
+++ b/supabase/functions/process-audio/index.ts
@@ -1,8 +1,49 @@
import { serve } from "https://deno.land/std@0.170.0/http/server.ts";
import OpenAI, { toFile } from "https://deno.land/x/openai@v4.26.0/mod.ts";
-import { multiParser } from 'https://deno.land/x/multiparser@0.114.0/mod.ts';
+import { decodeBase64 } from "https://deno.land/std@0.217.0/encoding/base64.ts";
import { corsHeaders } from "../common/cors.ts";
import { supabaseClient } from "../common/supabaseClient.ts";
+import { multiParser } from 'https://deno.land/x/multiparser@0.114.0/mod.ts';
+
+
+function createWavHeader(dataLength: number, sampleRate: number, numChannels: number, bitDepth: number) {
+ const headerLength = 44; // Fixed size for WAV header
+ const buffer = new ArrayBuffer(headerLength);
+ const view = new DataView(buffer);
+
+ // Helper function to write a string to the DataView
+ function writeString(view: DataView, offset: number, value: string) {
+ for (let i = 0; i < value.length; i++) {
+ view.setUint8(offset + i, value.charCodeAt(i));
+ }
+ }
+
+ // Writes a 32-bit unsigned integer to the DataView
+ function writeUint32(view: DataView, offset: number, value) {
+ view.setUint32(offset, value, true);
+ }
+
+ // Writes a 16-bit unsigned integer to the DataView
+ function writeUint16(view: DataView, offset: number, value) {
+ view.setUint16(offset, value, true);
+ }
+
+ writeString(view, 0, "RIFF");
+ writeUint32(view, 4, 36 + dataLength);
+ writeString(view, 8, "WAVE");
+ writeString(view, 12, "fmt ");
+ writeUint32(view, 16, 16);
+ writeUint16(view, 20, 1);
+ writeUint16(view, 22, numChannels);
+ writeUint32(view, 24, sampleRate);
+ writeUint32(view, 28, sampleRate * numChannels * bitDepth / 8);
+ writeUint16(view, 32, numChannels * bitDepth / 8);
+ writeUint16(view, 34, bitDepth);
+ writeString(view, 36, "data");
+ writeUint32(view, 40, dataLength);
+
+ return new Uint8Array(buffer);
+}
const processAudio = async (req: Request) => {
@@ -31,6 +72,17 @@ const processAudio = async (req: Request) => {
const file = form.files.file;
arrayBuffer = file.content.buffer;
filenameTimestamp = file.filename || filenameTimestamp;
+ } else if (contentType.includes('application/json')) {
+ const { data } = await req.json();
+ const audioData = decodeBase64(data);
+
+ console.log('Audio data:', audioData.length);
+ // 1 Channel, 8000 sample rate, 16 bit depth
+ const wavHeader = createWavHeader(audioData.length, 8000, 1, 16);
+ const wavBytes = new Uint8Array(wavHeader.length + audioData.length);
+ wavBytes.set(wavHeader, 0);
+ wavBytes.set(audioData, wavHeader.length);
+ arrayBuffer = wavBytes.buffer;
} else {
arrayBuffer = await req.arrayBuffer();
}
@@ -56,6 +108,7 @@ const processAudio = async (req: Request) => {
(transcriptLowered.includes("thank") &&
transcriptLowered.includes("watch"))
) {
+ console.log("no transcript found");
return new Response(JSON.stringify({ message: "No transcript found." }), {
headers: { ...corsHeaders, "Content-Type": "application/json" },
status: 200,