add sentence service

This commit is contained in:
2026-08-14 19:06:04 +08:00
parent f8a6bf24e4
commit 69d2ba986f
19 changed files with 2379 additions and 109 deletions

62
sentence_api/main.py Normal file
View File

@@ -0,0 +1,62 @@
import os
from pathlib import Path
from typing import Any, Dict
from fastapi import Depends, FastAPI, HTTPException, Path as ApiPath
from .models import SentenceBoundaryDocument
from .store import BoundaryStore
DEFAULT_INDEX_PATH = Path(__file__).resolve().parent / "data" / "sentence_boundaries.json"
def create_app(store: BoundaryStore = None) -> FastAPI:
application = FastAPI(
title="Oral Trainer Sentence Boundary API",
version="1.0.0",
description="Looks up pre-generated sentence boundaries by video SHA-256.",
)
index_path = Path(os.getenv("SENTENCE_BOUNDARIES_FILE", str(DEFAULT_INDEX_PATH)))
application.state.boundary_store = store or BoundaryStore(index_path)
def get_store() -> BoundaryStore:
return application.state.boundary_store
@application.get("/healthz")
def healthz(boundary_store: BoundaryStore = Depends(get_store)) -> Dict[str, Any]:
return {"status": "ok", "video_count": boundary_store.count()}
@application.get(
"/api/v1/videos/{video_hash}/sentence-boundaries",
response_model=SentenceBoundaryDocument,
)
@application.get(
"/api/v1/sentence-boundaries/{video_hash}",
response_model=SentenceBoundaryDocument,
include_in_schema=False,
)
def get_sentence_boundaries(
video_hash: str = ApiPath(
min_length=64,
max_length=64,
pattern=r"^[A-Fa-f0-9]{64}$",
description="SHA-256 hex digest of the exact video bytes",
),
boundary_store: BoundaryStore = Depends(get_store),
) -> SentenceBoundaryDocument:
document = boundary_store.get(video_hash)
if document is None:
raise HTTPException(
status_code=404,
detail={
"code": "SENTENCE_BOUNDARIES_NOT_FOUND",
"message": "No sentence boundaries are registered for this video hash.",
},
)
return document
return application
app = create_app()