Franek-Le's picture
Do something idk.
5eaa3c8
Raw
History Blame Contribute Delete
2.29 kB
import io
import numpy as np
import soundfile as sf
import edge_tts
import miniaudio
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from scipy.signal import resample
from pydantic import BaseModel
from ltm import EmbeddingMemory
app = FastAPI()
memory = EmbeddingMemory()
VOICE = "pl-PL-ZofiaNeural"
class MemoryMessage(BaseModel):
session_id: str
role: str
content: str
class MemoryQuery(BaseModel):
session_id: str | None = None
query: str
top_k: int = 5
@app.post("/tts")
async def tts(data: dict):
text = data.get("text", "").strip()
if not text:
return {"error": "empty text"}
mp3_buffer = io.BytesIO()
communicate = edge_tts.Communicate(text, VOICE)
async for chunk in communicate.stream():
if chunk["type"] == "audio":
mp3_buffer.write(chunk["data"])
mp3_buffer.seek(0)
decoded = miniaudio.decode(mp3_buffer.read())
raw = decoded.samples
if decoded.sample_format == miniaudio.SampleFormat.SIGNED16:
audio = np.frombuffer(raw, dtype=np.int16).astype(np.float32) / 32768.0
elif decoded.sample_format == miniaudio.SampleFormat.FLOAT32:
audio = np.frombuffer(raw, dtype=np.float32)
else:
return {"error": "Unsupported audio format from decoder"}
if decoded.nchannels > 1:
audio = audio.reshape(-1, decoded.nchannels)
audio = np.mean(audio, axis=1)
peak = np.max(np.abs(audio)) if len(audio) else 0
if peak > 0:
audio = audio / max(peak, 1.0)
audio *= 0.3
pitch_factor = 1.1
audio = resample(audio, int(len(audio) / pitch_factor))
audio = np.clip(audio, -1.0, 1.0)
wav_buffer = io.BytesIO()
sf.write(wav_buffer, audio, decoded.sample_rate, format="WAV")
wav_buffer.seek(0)
return StreamingResponse(wav_buffer, media_type="audio/wav")
@app.post("/memory/store")
def store(msg: MemoryMessage):
memory.add_message(
session_id=msg.session_id,
role=msg.role,
content=msg.content
)
return {"status": "saved"}
@app.post("/memory/query")
def search_memory(data: MemoryQuery):
results = memory.search(
query=data.query,
session_id=data.session_id,
top_k=data.top_k
)
return results