feat(api): A3 backend skeleton with FastAPI + SQLModel
- 3 tables: Meeting / TranscriptSegment / Summary (with state machine) - Routes: /api/upload-url + /api/upload-complete + meetings CRUD - MinIO presigned PUT for direct browser upload - BackgroundTasks state-machine stub for A5 to flesh out - SQLite for local dev, PostgreSQL+asyncpg for prod - CORS configured for frontend on 4490 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
46
api/app/services/transcribe.py
Normal file
46
api/app/services/transcribe.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Stub for the transcribe + summarize pipeline.
|
||||
|
||||
This module is intentionally a placeholder for A3. The real implementation
|
||||
lands in A5 and will:
|
||||
1. Download the object from MinIO
|
||||
2. Probe duration and size
|
||||
3. If file > 24 MB, ffmpeg silencedetect → split into <20 MB chunks
|
||||
4. Call Groq Whisper for each chunk, shift timestamps, merge
|
||||
5. Call Poe Claude with map-reduce for long audio
|
||||
6. Persist segments + summary, update meeting.status to done
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from sqlmodel import select
|
||||
from ..db import AsyncSessionLocal
|
||||
from ..models import Meeting, MeetingStatus
|
||||
|
||||
|
||||
async def process_meeting(meeting_id: int) -> None:
|
||||
"""Background task launched after upload-complete.
|
||||
|
||||
For A3 we just walk the state machine so the frontend can see status
|
||||
transitions; A5 swaps in real Groq/Poe calls.
|
||||
"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
meeting = await session.get(Meeting, meeting_id)
|
||||
if not meeting:
|
||||
return
|
||||
|
||||
try:
|
||||
for status, delay in [
|
||||
(MeetingStatus.splitting, 1),
|
||||
(MeetingStatus.transcribing, 2),
|
||||
(MeetingStatus.summarizing, 1),
|
||||
(MeetingStatus.done, 0),
|
||||
]:
|
||||
meeting.status = status
|
||||
if status == MeetingStatus.transcribing:
|
||||
meeting.chunks_total = 1
|
||||
meeting.chunks_done = 1
|
||||
await session.commit()
|
||||
await asyncio.sleep(delay)
|
||||
except Exception as exc:
|
||||
meeting.status = MeetingStatus.failed
|
||||
meeting.error = str(exc)
|
||||
await session.commit()
|
||||
Reference in New Issue
Block a user