| from dataclasses import asdict, dataclass, field |
| from pathlib import Path |
| from typing import Any, Dict, List, Optional |
|
|
| from backend.synthesis_catalog import LOCAL_BACKEND, OMNIVOICE_MODEL |
|
|
|
|
| JsonDict = Dict[str, Any] |
|
|
|
|
| @dataclass |
| class Chapter: |
| id: str |
| label: str |
| title: str |
| text: str |
| chars: int |
| est_minutes: int |
| included: bool = True |
| start_seconds: int = 0 |
|
|
| def to_dict(self) -> JsonDict: |
| data = asdict(self) |
| data["n"] = data["label"] |
| return data |
|
|
|
|
| @dataclass |
| class SessionRecord: |
| session_id: str |
| root: Path |
| created_at: float |
| touched_at: float |
|
|
|
|
| @dataclass |
| class VoiceConfig: |
| mode: str = "auto" |
| model: str = OMNIVOICE_MODEL |
| backend: str = LOCAL_BACKEND |
| narrator_id: Optional[str] = None |
| sample_path: Optional[str] = None |
| reference_text: Optional[str] = None |
| design_prompt: Optional[str] = None |
| speaker: Optional[str] = None |
| language: Optional[str] = None |
| apply_text_normalization: bool = False |
|
|
| @classmethod |
| def from_dict(cls, data: JsonDict) -> "VoiceConfig": |
| return cls( |
| mode=data.get("mode", "auto"), |
| model=data.get("model", OMNIVOICE_MODEL), |
| backend=data.get("backend", LOCAL_BACKEND), |
| narrator_id=data.get("narratorId") or data.get("narrator_id"), |
| sample_path=data.get("samplePath") or data.get("sample_path"), |
| reference_text=data.get("referenceText") or data.get("reference_text"), |
| design_prompt=data.get("designPrompt") or data.get("design_prompt"), |
| speaker=data.get("speaker"), |
| language=data.get("language"), |
| apply_text_normalization=bool( |
| data.get("applyTextNormalization", data.get("apply_text_normalization", False)) |
| ), |
| ) |
|
|
| def to_dict(self) -> JsonDict: |
| return { |
| "mode": self.mode, |
| "model": self.model, |
| "backend": self.backend, |
| "narratorId": self.narrator_id, |
| "samplePath": self.sample_path, |
| "referenceText": self.reference_text, |
| "designPrompt": self.design_prompt, |
| "speaker": self.speaker, |
| "language": self.language, |
| "applyTextNormalization": self.apply_text_normalization, |
| } |
|
|
|
|
| @dataclass |
| class RenderArtifact: |
| path: Path |
| duration_seconds: int |
| chapter_id: str |
|
|
|
|
| @dataclass |
| class RenderJob: |
| session_id: str |
| status: str = "idle" |
| current_chapter_id: Optional[str] = None |
| outputs: List[RenderArtifact] = field(default_factory=list) |
|
|