Files
mediaplayer/sentence_api/main.py
2026-08-14 19:06:04 +08:00

63 lines
2.0 KiB
Python

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()