|
|
@@ -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));
|
|
|
+ }
|
|
|
}
|