video-accessibility/backend/app/core/config.py
michael 865fcdc246 feat: add TTS settings panel with model, speed, and style options
- Add model selection (flash vs pro) for quality control
- Add speed slider (0.5x - 2.0x) for pacing adjustment
- Add style presets (neutral, calm, energetic, professional, warm, documentary)
- Add custom style prompt option for advanced customization
- New /tts/options endpoint returns available TTS options
- Voice preview now tests all settings so users hear exact output
- Backward compatible: all new fields have sensible defaults

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 15:22:14 -06:00

198 lines
7 KiB
Python

from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# App
app_env: str = "dev"
api_base_url: str = "http://localhost:8000"
# Auth
jwt_secret: str
jwt_alg: str = "HS256"
jwt_access_ttl_min: int = 15
jwt_refresh_ttl_days: int = 7
cookie_domain: str = "localhost"
cookie_secure: bool = False
cookie_samesite: str = "Lax"
# Database
mongodb_uri: str
mongodb_db: str = "accessible_video"
# Redis
redis_url: str
# Celery
celery_broker_url: str = ""
celery_result_backend: str = ""
# GCP
gcp_project_id: str
gcs_bucket: str = "accessible-video"
google_application_credentials: str = ""
# AI Services
gemini_api_key: str
translate_api_key: str = ""
elevenlabs_api_key: str = ""
google_tts_credentials: str = ""
# TTS Voice Configuration
tts_provider: str = "gemini" # "gemini", "google", or "elevenlabs"
google_tts_voices: dict[str, str] = {
"en-US": "en-US-Neural2-D",
"es-ES": "es-ES-Neural2-A",
"fr-FR": "fr-FR-Neural2-A",
"de-DE": "de-DE-Neural2-B"
}
elevenlabs_voices: dict[str, str] = {
"en-US": "21m00Tcm4TlvDq8ikWAM",
"es-ES": "VR6AewLTigWG4xSOukaG",
"fr-FR": "TxGEqnHWrfWFTfGW9XjX",
"de-DE": "pNInz6obpgDQGcFmaJgB"
}
# Gemini TTS Configuration
gemini_tts_model: str = "gemini-2.5-flash-preview-tts"
gemini_tts_default_voice: str = "Kore"
gemini_tts_voices: list[str] = [
"Zephyr", "Puck", "Charon", "Kore", "Fenrir", "Leda", "Orus", "Aoede",
"Callirrhoe", "Autonoe", "Enceladus", "Iapetus", "Umbriel", "Algieba",
"Despina", "Erinome", "Algenib", "Rasalgethi", "Laomedeia", "Achernar",
"Alnilam", "Schedar", "Gacrux", "Pulcherrima", "Achird", "Zubenelgenubi",
"Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat"
]
gemini_tts_languages: dict[str, str] = {
"en": "en-US",
"es": "es-US",
"fr": "fr-FR",
"de": "de-DE",
"it": "it-IT",
"pt": "pt-BR",
"ja": "ja-JP",
"ko": "ko-KR",
"ar": "ar-EG",
"hi": "hi-IN",
"id": "id-ID",
"nl": "nl-NL",
"pl": "pl-PL",
"ru": "ru-RU",
"th": "th-TH",
"tr": "tr-TR",
"vi": "vi-VN",
"ro": "ro-RO",
"uk": "uk-UA",
"bn": "bn-BD",
"mr": "mr-IN",
"ta": "ta-IN",
"te": "te-IN",
"zh": "zh-CN"
}
gemini_tts_language_names: dict[str, str] = {
"en": "English",
"es": "Spanish",
"fr": "French",
"de": "German",
"it": "Italian",
"pt": "Portuguese",
"ja": "Japanese",
"ko": "Korean",
"ar": "Arabic",
"hi": "Hindi",
"id": "Indonesian",
"nl": "Dutch",
"pl": "Polish",
"ru": "Russian",
"th": "Thai",
"tr": "Turkish",
"vi": "Vietnamese",
"ro": "Romanian",
"uk": "Ukrainian",
"bn": "Bengali",
"mr": "Marathi",
"ta": "Tamil",
"te": "Telugu",
"zh": "Chinese"
}
gemini_tts_preview_samples: dict[str, str] = {
"en": "This is a preview of the audio description voice.",
"es": "Esta es una vista previa de la voz de audiodescripcion.",
"fr": "Ceci est un apercu de la voix de l'audiodescription.",
"de": "Dies ist eine Vorschau der Audiodeskriptionsstimme.",
"it": "Questa e un'anteprima della voce dell'audiodescrizione.",
"pt": "Esta e uma previa da voz da audiodescricao.",
"ja": "これは音声解説の声のプレビューです。",
"ko": "이것은 오디오 설명 음성의 미리보기입니다.",
"ar": "هذه معاينة لصوت الوصف الصوتي.",
"hi": "यह ऑडियो विवरण आवाज का पूर्वावलोकन है।",
"id": "Ini adalah pratinjau suara deskripsi audio.",
"nl": "Dit is een voorbeeld van de audiodescriptiestem.",
"pl": "To jest podglad glosu audiodeskrypcji.",
"ru": "Это предварительный просмотр голоса аудиоописания.",
"th": "นี่คือตัวอย่างเสียงบรรยายภาพ",
"tr": "Bu, sesli betimleme sesinin bir onizlemesidir.",
"vi": "Day la ban xem truoc giong mo ta am thanh.",
"ro": "Aceasta este o previzualizare a vocii descrierii audio.",
"uk": "Це попередній перегляд голосу аудіоопису.",
"bn": "এটি অডিও বর্ণনা ভয়েসের একটি প্রিভিউ।",
"mr": "हे ऑडिओ वर्णन आवाजाचे पूर्वावलोकन आहे.",
"ta": "இது ஆடியோ விளக்க குரலின் முன்னோட்டம்.",
"te": "ఇది ఆడియో వివరణ స్వరం యొక్క ప్రివ్యూ.",
"zh": "这是音频描述语音的预览。"
}
# Gemini TTS Model Options
gemini_tts_models: dict[str, str] = {
"flash": "gemini-2.5-flash-preview-tts", # Fast, cost-efficient
"pro": "gemini-2.5-pro-preview-tts", # Higher quality
}
# Gemini TTS Style Presets - prompts prepended to text for style control
gemini_tts_style_prompts: dict[str, str] = {
"neutral": "", # No modification
"calm": "Speak in a calm, gentle, and soothing manner with a relaxed pace. ",
"energetic": "Speak with energy and enthusiasm, maintaining an upbeat and dynamic tone. ",
"professional": "Speak in a clear, professional, and authoritative manner suitable for corporate content. ",
"warm": "Speak in a warm, friendly, and approachable manner as if speaking to a friend. ",
"documentary": "Speak in a measured, informative tone similar to a documentary narrator, with clear enunciation and appropriate pauses. ",
}
# TTS Speed range configuration
gemini_tts_speed_min: float = 0.5
gemini_tts_speed_max: float = 2.0
gemini_tts_speed_default: float = 1.0
gemini_tts_speed_step: float = 0.1
# Email
sendgrid_api_key: str
email_from: str
client_base_url: str
# Microsoft Authentication (Azure AD)
azure_client_id: str = ""
azure_authority: str = ""
azure_redirect_uri: str = ""
# Observability
sentry_dsn: str = ""
otel_exporter_otlp_endpoint: str = ""
# CORS - comma-separated list of allowed origins
cors_origins: str = "http://localhost:5173,http://localhost:5174,http://localhost:3000,http://localhost:6001"
@property
def cors_origins_list(self) -> list[str]:
"""Parse CORS origins from comma-separated string to list."""
return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()]
class Config:
env_file = ".env"
settings = Settings()
def get_settings():
"""Get settings instance - for dependency injection"""
return settings