- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import { Blob } from '@google/genai';
|
|
|
|
// Convert base64 string to raw bytes
|
|
export function decode(base64: string): Uint8Array {
|
|
const binaryString = atob(base64);
|
|
const len = binaryString.length;
|
|
const bytes = new Uint8Array(len);
|
|
for (let i = 0; i < len; i++) {
|
|
bytes[i] = binaryString.charCodeAt(i);
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
// Convert raw bytes to base64 string
|
|
export function encode(bytes: Uint8Array): string {
|
|
let binary = '';
|
|
const len = bytes.byteLength;
|
|
for (let i = 0; i < len; i++) {
|
|
binary += String.fromCharCode(bytes[i]);
|
|
}
|
|
return btoa(binary);
|
|
}
|
|
|
|
// Decode raw PCM bytes into an AudioBuffer
|
|
export async function decodeAudioData(
|
|
data: Uint8Array,
|
|
ctx: AudioContext,
|
|
sampleRate: number = 24000,
|
|
numChannels: number = 1
|
|
): Promise<AudioBuffer> {
|
|
const dataInt16 = new Int16Array(data.buffer);
|
|
const frameCount = dataInt16.length / numChannels;
|
|
const buffer = ctx.createBuffer(numChannels, frameCount, sampleRate);
|
|
|
|
for (let channel = 0; channel < numChannels; channel++) {
|
|
const channelData = buffer.getChannelData(channel);
|
|
for (let i = 0; i < frameCount; i++) {
|
|
channelData[i] = dataInt16[i * numChannels + channel] / 32768.0;
|
|
}
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
// Create a Blob formatted for the Gemini Live API (PCM 16kHz)
|
|
export function createPcmBlob(data: Float32Array): Blob {
|
|
const l = data.length;
|
|
const int16 = new Int16Array(l);
|
|
for (let i = 0; i < l; i++) {
|
|
// Clamp values to [-1, 1] to prevent distortion
|
|
const s = Math.max(-1, Math.min(1, data[i]));
|
|
int16[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
|
}
|
|
return {
|
|
data: encode(new Uint8Array(int16.buffer)),
|
|
mimeType: 'audio/pcm;rate=16000',
|
|
};
|
|
}
|