feat(api): add backend
routes and WebSockets
This commit is contained in:
74
services/api/app/repositories/audio_repository.py
Normal file
74
services/api/app/repositories/audio_repository.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from sqlalchemy import and_, func, select, text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.audio_data import AudioData
|
||||
|
||||
|
||||
class AudioRepository:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def latest(self, limit: int) -> list[AudioData]:
|
||||
q = select(AudioData).order_by(AudioData.time.desc()).limit(limit)
|
||||
res = await self.db.execute(q)
|
||||
return list(res.scalars().all())
|
||||
|
||||
async def range(self, time_from: datetime, time_to: datetime) -> list[AudioData]:
|
||||
q = (
|
||||
select(AudioData)
|
||||
.where(and_(AudioData.time >= time_from, AudioData.time <= time_to))
|
||||
.order_by(AudioData.time.asc())
|
||||
)
|
||||
res = await self.db.execute(q)
|
||||
return list(res.scalars().all())
|
||||
|
||||
async def loud_samples(
|
||||
self,
|
||||
threshold: float,
|
||||
time_from: datetime | None,
|
||||
time_to: datetime | None,
|
||||
) -> list[AudioData]:
|
||||
cond = [AudioData.rms_db >= threshold]
|
||||
if time_from:
|
||||
cond.append(AudioData.time >= time_from)
|
||||
if time_to:
|
||||
cond.append(AudioData.time <= time_to)
|
||||
|
||||
q = select(AudioData).where(and_(*cond)).order_by(AudioData.time.asc())
|
||||
res = await self.db.execute(q)
|
||||
return list(res.scalars().all())
|
||||
|
||||
async def summary_since(self, since: datetime) -> dict:
|
||||
q = select(
|
||||
func.avg(AudioData.rms_db).label("avg_db"),
|
||||
func.max(AudioData.rms_db).label("max_db"),
|
||||
func.sum(func.case((AudioData.is_silence.is_(True), 1), else_=0)).label(
|
||||
"silence_count"
|
||||
),
|
||||
func.count().label("total_count"),
|
||||
).where(AudioData.time >= since)
|
||||
|
||||
res = await self.db.execute(q)
|
||||
row = res.one()
|
||||
|
||||
# dominant freq excluding silence
|
||||
fq = (
|
||||
select(AudioData.frequency_hz, func.count().label("cnt"))
|
||||
.where(and_(AudioData.time >= since, AudioData.is_silence.is_(False)))
|
||||
.group_by(AudioData.frequency_hz)
|
||||
.order_by(text("cnt DESC"))
|
||||
.limit(1)
|
||||
)
|
||||
fres = await self.db.execute(fq)
|
||||
frow = fres.first()
|
||||
|
||||
return {
|
||||
"avg_db": float(row.avg_db or 0.0),
|
||||
"max_db": float(row.max_db or 0.0),
|
||||
"dominant_freq": int(frow[0]) if frow else 0,
|
||||
"silence_count": int(row.silence_count or 0),
|
||||
"total_count": int(row.total_count or 0),
|
||||
}
|
||||
Reference in New Issue
Block a user