Browse Source

one ai API 적용

[UC]임종현 7 months ago
parent
commit
6f1cf18422
3 changed files with 88 additions and 8 deletions
  1. 49 6
      public/AudioManager.js
  2. 37 0
      public/api.js
  3. 2 2
      public/main.js

+ 49 - 6
public/AudioManager.js

@@ -1,7 +1,7 @@
 // AudioManager.js (오디오 처리)
 import {state} from "./state.js";
-import {WebSocketManager} from "./WebSocketManager.js";
-import {UIManager} from "./UIManager.js";
+import {oai001B01} from "./api.js";
+import {elements} from "./elements.js";
 
 export const AudioManager = {
     async initWAVMediaRecorder() {
@@ -19,9 +19,9 @@ export const AudioManager = {
             const processor = audioContext.createScriptProcessor(4096, 1, 1);
             let isTransmitting = false;
             
-            processor.onaudioprocess = (event) => {
-                if (!state.isRecording || state.websocket.readyState !== WebSocket.OPEN) return;
-                
+            processor.onaudioprocess = async (event) => {
+                if (!state.isRecording) return;
+
                 const inputData = event.inputBuffer.getChannelData(0); // Float32Array
                 const rms = Math.sqrt(inputData.reduce((sum, sample) => sum + sample * sample, 0) / inputData.length);
                 const pcmData = getPCMData(inputData); // Int16Array로 변환
@@ -46,8 +46,8 @@ export const AudioManager = {
                         }
 
                         // 서버로 전송
-                        WebSocketManager.sendData(combinedData.buffer);
                         console.log("묵음 감지! 서버로 전송");
+                        elements.transcriptionDiv.textContent = await oai001B01(combinedData.buffer);
                         audioChunks = [];
                         speaking = false;
                         silenceStart = 0;
@@ -146,4 +146,47 @@ const getPCMData = (inputBuffer) => {
 
     // 원시 PCM 데이터를 ArrayBuffer로 변환
     return pcmData;
+}
+
+export function encodeWAV(pcmData, sampleRate = 16000) {
+    const numChannels = 1;
+    const bytesPerSample = 2;
+    const blockAlign = numChannels * bytesPerSample;
+    const byteRate = sampleRate * blockAlign;
+    const dataLength = pcmData.length * bytesPerSample;
+    const buffer = new ArrayBuffer(44 + dataLength);
+    const view = new DataView(buffer);
+
+    // RIFF 헤더
+    writeString(view, 0, 'RIFF');
+    view.setUint32(4, 36 + dataLength, true); // chunk size
+    writeString(view, 8, 'WAVE');
+
+    // fmt 서브 청크
+    writeString(view, 12, 'fmt ');
+    view.setUint32(16, 16, true); // 서브청크1 크기
+    view.setUint16(20, 1, true);  // 오디오 포맷(1: PCM)
+    view.setUint16(22, numChannels, true);
+    view.setUint32(24, sampleRate, true);
+    view.setUint32(28, byteRate, true);
+    view.setUint16(32, blockAlign, true);
+    view.setUint16(34, bytesPerSample * 8, true);
+
+    // data 서브 청크
+    writeString(view, 36, 'data');
+    view.setUint32(40, dataLength, true);
+
+    // PCM 데이터 복사
+    let offset = 44;
+    for (let i = 0; i < pcmData.length; i++, offset += 2) {
+        view.setInt16(offset, pcmData[i], true);
+    }
+
+    return new Blob([buffer], { type: 'audio/wav' });
+}
+
+function writeString(view, offset, string) {
+    for (let i = 0; i < string.length; i++) {
+        view.setUint8(offset + i, string.charCodeAt(i));
+    }
 }

+ 37 - 0
public/api.js

@@ -0,0 +1,37 @@
+import {encodeWAV} from "./AudioManager.js";
+
+export async function oai001B01(combinedDataBuffer) {
+    const pcmData = new Int16Array(combinedDataBuffer);
+    const wavBlob = encodeWAV(pcmData); // WAV 포맷으로 변환 (헤더 포함)
+
+    const file = new File([wavBlob], "recording.wav", { type: "audio/wav" });
+
+    const formData = new FormData();
+    formData.append("file", file);
+
+    const headers = {
+        "timestamp": "1699865904641",
+        "transaction-id": "TRANSACTION_ID",
+        "wehago-sign": "0rzS6a+EXzQcJIcP6rsx8tqn5dxRQiNuKwW59KRlzU4=",
+        "Authorization": "Bearer klagoDev|1|TyuElx3MlaqCbLHQ5r8TJg7vQkzVRq"
+    };
+
+    try {
+        const response = await fetch("https://dev.amaranth10.co.kr/oneai/oai001B01", {
+            method: "POST",
+            headers,
+            body: formData
+        });
+
+        const result = await response.json();
+
+        if (result?.resultData) {
+            console.log("📝 변환된 텍스트:", result.resultData);
+            return result.resultData;
+        } else {
+            console.warn("✅ 응답 수신했지만 변환된 텍스트 없음:", result);
+        }
+    } catch (error) {
+        console.error("❌ HTTP 요청 실패:", error);
+    }
+}

+ 2 - 2
public/main.js

@@ -6,14 +6,14 @@ import { elements } from './elements.js';
 
 // 시작버튼 클릭
 elements.startBtn.addEventListener('click', async () => {
-    WebSocketManager.init('wss://whisper-back.jonghyun2.com/audio-stream');
+    // WebSocketManager.init('wss://whisper-back.jonghyun2.com/audio-stream');
     await AudioManager.initWAVMediaRecorder();
     UIManager.onStart();
 });
 
 // 종료버튼 클릭
 elements.stopBtn.addEventListener('click', () => {
-    WebSocketManager.closeConnection();
+    // WebSocketManager.closeConnection();
     AudioManager.cleanup();
     UIManager.onStop();
 });