108 lines
4.2 KiB
Python
108 lines
4.2 KiB
Python
"""Endpoint pro přepis audia.
|
|
|
|
POST /transcribe — udělá vše najednou: audio přepíše paralelně Deepgramem i OpenAI
|
|
(whisper-1) a oba texty sloučí přes OpenAI Chat podle `combine_prompt` do jednoho
|
|
co nejlepšího přepisu.
|
|
|
|
Audio přichází jako proměnná (upload `file` ve form-data). Všechny ostatní parametry
|
|
jsou v POST těle (form fields). API klíče jsou v X- hlavičkách (viz credentials.py).
|
|
Výstup je vždy JSON: {"gpt": ..., "deepgram": ..., "merge": ...}.
|
|
"""
|
|
import asyncio
|
|
|
|
from fastapi import APIRouter, Depends, File, Form, UploadFile
|
|
from pydantic import BaseModel, Field
|
|
|
|
from ..clients import deepgram_client, openai_client
|
|
from ..config import (
|
|
DEFAULT_CHAT_MODEL,
|
|
DEFAULT_DEEPGRAM_MODEL,
|
|
DEFAULT_LANGUAGE,
|
|
DEFAULT_WHISPER_MODEL,
|
|
)
|
|
from ..credentials import Credentials, get_credentials
|
|
from ..errors import BadRequestError
|
|
from ..logging_config import get_logger
|
|
from ..prompts import DEFAULT_COMBINE_PROMPT
|
|
|
|
log = get_logger("audio-transcription.transcribe")
|
|
|
|
router = APIRouter(tags=["transcribe"])
|
|
|
|
|
|
class TranscribeResult(BaseModel):
|
|
gpt: str = Field(..., description="Přepis z OpenAI (model whisper-1).")
|
|
deepgram: str = Field(..., description="Přepis z Deepgramu.")
|
|
merge: str = Field(..., description="Sloučený, co nejpřesnější výsledný přepis.")
|
|
|
|
|
|
async def _read_upload(file: UploadFile) -> tuple[bytes, str, str]:
|
|
"""Načte upload do paměti a vrátí (bytes, filename, content_type)."""
|
|
audio = await file.read()
|
|
if not audio:
|
|
raise BadRequestError("Nahraný soubor je prázdný.")
|
|
filename = file.filename or "audio.mp3"
|
|
content_type = file.content_type or "application/octet-stream"
|
|
return audio, filename, content_type
|
|
|
|
|
|
@router.post(
|
|
"/dual-with-merge",
|
|
response_model=TranscribeResult,
|
|
summary="Přepis audia (Deepgram + OpenAI) a AI sloučení — vše najednou",
|
|
description="Přijme audio soubor, vytvoří paralelně přepis z Deepgramu i z OpenAI "
|
|
"(whisper-1) a poté je sloučí přes OpenAI Chat podle `combine_prompt` do jediného, "
|
|
"co nejpřesnějšího českého přepisu. Vrací JSON `{gpt, deepgram, merge}`.",
|
|
)
|
|
async def transcribe(
|
|
file: UploadFile = File(..., description="Audio soubor k přepisu (proměnná)."),
|
|
combine_prompt: str = Form(
|
|
DEFAULT_COMBINE_PROMPT,
|
|
description="System prompt pro sloučení. Nezadáš-li, použije se výchozí "
|
|
"'Czech Transcript Merger'.",
|
|
),
|
|
deepgram_model: str = Form(DEFAULT_DEEPGRAM_MODEL, description="Deepgram model."),
|
|
whisper_model: str = Form(DEFAULT_WHISPER_MODEL, description="OpenAI přepisový model."),
|
|
chat_model: str = Form(DEFAULT_CHAT_MODEL, description="OpenAI chat model pro sloučení."),
|
|
language: str = Form(DEFAULT_LANGUAGE, description="Jazyk audia (ISO kód, např. cs)."),
|
|
diarize: bool = Form(True, description="Deepgram diarizace (rozlišení mluvčích)."),
|
|
smart_format: bool = Form(True, description="Deepgram smart formatting."),
|
|
creds: Credentials = Depends(get_credentials),
|
|
) -> TranscribeResult:
|
|
deepgram_key = creds.require_deepgram()
|
|
openai_key = creds.require_openai()
|
|
|
|
audio, filename, content_type = await _read_upload(file)
|
|
|
|
# Oba přepisy paralelně.
|
|
text_deepgram, text_gpt = await asyncio.gather(
|
|
deepgram_client.transcribe(
|
|
api_key=deepgram_key,
|
|
audio=audio,
|
|
content_type=content_type,
|
|
model=deepgram_model,
|
|
language=language,
|
|
diarize=diarize,
|
|
smart_format=smart_format,
|
|
),
|
|
openai_client.transcribe(
|
|
api_key=openai_key,
|
|
audio=audio,
|
|
filename=filename,
|
|
content_type=content_type,
|
|
model=whisper_model,
|
|
language=language,
|
|
),
|
|
)
|
|
|
|
prompt = combine_prompt.strip() if combine_prompt and combine_prompt.strip() else DEFAULT_COMBINE_PROMPT
|
|
merged = await openai_client.merge_transcripts(
|
|
api_key=openai_key,
|
|
model=chat_model,
|
|
system_prompt=prompt,
|
|
text_deepgram=text_deepgram,
|
|
text_whisper=text_gpt,
|
|
)
|
|
|
|
return TranscribeResult(gpt=text_gpt, deepgram=text_deepgram, merge=merged)
|