"""Runtime settings, read once from environment variables. Every limit can be changed without touching code, e.g. in the Space's "Variables and secrets" page. """ from __future__ import annotations import os def _int(name: str, default: int) -> int: try: return int(os.environ.get(name, default)) except (TypeError, ValueError): return default def _list(name: str, default: list[str]) -> list[str]: raw = os.environ.get(name, "") items = [x.strip() for x in raw.replace("\n", ",").split(",") if x.strip()] return items or list(default) # --- Gemini ----------------------------------------------------------------- # Models are tried in order; a 404 / "not available" moves on to the next one. # GEMINI_MODEL may hold a single name or a comma-separated list. AUDIO_MODELS = _list( "GEMINI_MODEL", ["gemini-3.8-flash", "gemini-flash-latest", "gemini-3.5-flash", "gemini-2.5-flash"], ) # Used for the text-only reasoning steps when the user picks "Deep". DEEP_MODELS = _list( "GEMINI_DEEP_MODEL", ["gemini-pro-latest", "gemini-3.1-pro-preview", "gemini-2.5-pro"], ) REQUEST_TIMEOUT_S = _int("GEMINI_TIMEOUT_S", 600) MAX_RETRIES = _int("GEMINI_MAX_RETRIES", 4) # Files processed at the same time (Gemini calls run in threads). PARALLEL_FILES = max(1, _int("PARALLEL_FILES", 3)) # --- Audio ------------------------------------------------------------------ ANALYSIS_SR = 16_000 # Gemini hears audio at 16 kHz; features use the same rate CHUNK_TARGET_S = _int("CHUNK_SECONDS", 600) # transcription chunk length (~10 min) CHUNK_SLACK_S = 60 # cut at the longest pause within +/- this window OPUS_BITRATE = 32_000 MAX_FILES = _int("MAX_FILES", 20) MAX_MINUTES_PER_FILE = _int("MAX_MINUTES_PER_FILE", 180) MAX_TOTAL_MINUTES = _int("MAX_TOTAL_MINUTES", 600) MAX_UPLOAD_MB = _int("MAX_UPLOAD_MB", 500) AUDIO_EXTENSIONS = [ ".wav", ".mp3", ".m4a", ".aac", ".flac", ".ogg", ".oga", ".opus", ".wma", ".aif", ".aiff", ".amr", ".webm", ".mp4", ".mov", ".mkv", ".3gp", ".caf", ] def api_keys(extra: str | None = None) -> list[str]: """All configured Gemini keys, de-duplicated, user-supplied key first. Sources: the optional key typed in the UI, GEMINI_API_KEYS (comma or newline separated, for rotating between several keys when one hits its quota), GEMINI_API_KEY and GOOGLE_API_KEY. """ keys: list[str] = [] candidates = [extra or ""] candidates += os.environ.get("GEMINI_API_KEYS", "").replace("\n", ",").split(",") candidates += [os.environ.get("GEMINI_API_KEY", ""), os.environ.get("GOOGLE_API_KEY", "")] for k in candidates: k = k.strip().strip('"').strip("'") if k and k not in keys: keys.append(k) return keys