- Add Gemini TTS service with 30 voices and 24 languages - Add TTS API endpoints for voice listing and preview - Add per-language voice selection in job creation form - Add voice override at QC approval stage - Add VoiceSelector and VoicePreviewButton components - Update TTSPreferences model with provider and voice mapping 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
96 lines
2.3 KiB
Python
96 lines
2.3 KiB
Python
from typing import Any, Literal, Optional, Union
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from ..models.job import JobStatus, LangOutput, RequestedOutputs, Review, TTSPreferences
|
|
|
|
|
|
class JobResponse(BaseModel):
|
|
id: str
|
|
title: str
|
|
status: JobStatus
|
|
source: dict[str, Any]
|
|
requested_outputs: RequestedOutputs
|
|
review: Review
|
|
outputs: Optional[dict[str, LangOutput]] = None
|
|
created_at: Optional[str] = None
|
|
updated_at: Optional[str] = None
|
|
|
|
|
|
class JobListResponse(BaseModel):
|
|
jobs: list[JobResponse]
|
|
total: int
|
|
page: int
|
|
size: int
|
|
|
|
|
|
class JobCreateRequest(BaseModel):
|
|
title: str
|
|
source_is_english: bool = True # True = English source, False = other language (auto-detect)
|
|
language_hint: Optional[str] = None # Optional hint when source_is_english=False
|
|
requested_outputs: RequestedOutputs
|
|
|
|
|
|
class JobUpdateRequest(BaseModel):
|
|
title: Optional[str] = None
|
|
review_notes: Optional[str] = None
|
|
|
|
|
|
class ApproveEnglishRequest(BaseModel):
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class ApproveSourceRequest(BaseModel):
|
|
"""Request to approve source language content (works for any language)"""
|
|
notes: Optional[str] = None
|
|
tts_preferences: Optional[TTSPreferences] = None # Override TTS voice settings
|
|
|
|
|
|
class RejectJobRequest(BaseModel):
|
|
notes: str
|
|
|
|
|
|
class CompleteJobRequest(BaseModel):
|
|
notes: Optional[str] = None
|
|
|
|
|
|
class VttUpdateRequest(BaseModel):
|
|
captions_vtt: Optional[str] = None
|
|
audio_description_vtt: Optional[str] = None
|
|
language: Optional[str] = None # If None, defaults to source language
|
|
|
|
|
|
class VttTimingAdjustRequest(BaseModel):
|
|
offset_seconds: float
|
|
language: str = "en"
|
|
adjust_captions: bool = True
|
|
adjust_audio_description: bool = True
|
|
|
|
|
|
class JobDownloadsResponse(BaseModel):
|
|
downloads: dict[str, Union[dict[str, str], str]] # language -> {file_type: signed_url} OR source_video -> signed_url
|
|
|
|
|
|
class VttContentResponse(BaseModel):
|
|
captions_vtt: Optional[str] = None
|
|
audio_description_vtt: Optional[str] = None
|
|
|
|
|
|
class AssetValidationResponse(BaseModel):
|
|
is_valid: bool
|
|
errors: list[str]
|
|
warnings: list[str] = []
|
|
|
|
|
|
class JobDeleteResponse(BaseModel):
|
|
message: str
|
|
|
|
|
|
class BulkDeleteRequest(BaseModel):
|
|
job_ids: list[str]
|
|
|
|
|
|
class BulkDeleteResponse(BaseModel):
|
|
deleted_count: int
|
|
total_requested: int
|
|
errors: list[str]
|