mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-03-30 10:56:47 +00:00
* feat: remove network_mode host for standalone by fixing WebRTC port range and ICE candidates aioice hardcodes bind(addr, 0) for ICE UDP sockets, making port mapping impossible in Docker bridge networking. This adds two env-var-gated mechanisms to replace network_mode: host: 1. WEBRTC_PORT_RANGE (e.g. "50000-50100"): monkey-patches aioice to bind UDP sockets within a known range, so they can be mapped in Docker. 2. WEBRTC_HOST (e.g. "host.docker.internal"): rewrites container-internal IPs in SDP answers with the Docker host's real IP, so LAN clients can reach the ICE candidates. Both default to None — no effect on existing deployments. * fix: do not attempt sidecar to detect host ip, use the standalone script to figure out the external ip and use it * style: reformat --------- Co-authored-by: tito <tito@titos-Mac-Studio.local>
179 lines
5.7 KiB
Python
179 lines
5.7 KiB
Python
from pydantic.types import PositiveInt
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
from reflector.schemas.platform import DAILY_PLATFORM, Platform
|
|
from reflector.utils.string import NonEmptyString
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
extra="ignore",
|
|
)
|
|
|
|
ROOT_PATH: str = "/"
|
|
|
|
# WebRTC port range for ICE candidates (e.g. "50000-50100").
|
|
# When set, monkey-patches aioice to bind UDP sockets within this range,
|
|
# allowing Docker port mapping instead of network_mode: host.
|
|
WEBRTC_PORT_RANGE: str | None = None
|
|
# Host IP or hostname to advertise in ICE candidates instead of the
|
|
# container's internal IP. Use "host.docker.internal" in Docker with
|
|
# extra_hosts, or a specific LAN IP. Resolved at connection time.
|
|
WEBRTC_HOST: str | None = None
|
|
|
|
# CORS
|
|
UI_BASE_URL: str = "http://localhost:3000"
|
|
CORS_ORIGIN: str = "*"
|
|
CORS_ALLOW_CREDENTIALS: bool = False
|
|
|
|
# Database
|
|
DATABASE_URL: str = (
|
|
"postgresql+asyncpg://reflector:reflector@localhost:5432/reflector"
|
|
)
|
|
|
|
# local data directory
|
|
DATA_DIR: str = "./data"
|
|
|
|
# Audio Chunking
|
|
# backends: silero, frames
|
|
AUDIO_CHUNKER_BACKEND: str = "frames"
|
|
|
|
# Audio Transcription
|
|
# backends:
|
|
# - whisper: in-process model loading (no HTTP, runs in same process)
|
|
# - modal: HTTP API client (works with Modal.com OR self-hosted gpu/self_hosted/)
|
|
TRANSCRIPT_BACKEND: str = "whisper"
|
|
TRANSCRIPT_URL: str | None = None
|
|
TRANSCRIPT_TIMEOUT: int = 90
|
|
TRANSCRIPT_FILE_TIMEOUT: int = 600
|
|
|
|
# Audio Transcription: modal backend
|
|
TRANSCRIPT_MODAL_API_KEY: str | None = None
|
|
|
|
# Audio transcription storage
|
|
TRANSCRIPT_STORAGE_BACKEND: str | None = None
|
|
|
|
# Storage configuration for AWS
|
|
TRANSCRIPT_STORAGE_AWS_BUCKET_NAME: str = "reflector-bucket"
|
|
TRANSCRIPT_STORAGE_AWS_REGION: str = "us-east-1"
|
|
TRANSCRIPT_STORAGE_AWS_ACCESS_KEY_ID: str | None = None
|
|
TRANSCRIPT_STORAGE_AWS_SECRET_ACCESS_KEY: str | None = None
|
|
TRANSCRIPT_STORAGE_AWS_ENDPOINT_URL: str | None = None
|
|
|
|
# Platform-specific recording storage (follows {PREFIX}_STORAGE_AWS_{CREDENTIAL} pattern)
|
|
# Whereby storage configuration
|
|
WHEREBY_STORAGE_AWS_BUCKET_NAME: str | None = None
|
|
WHEREBY_STORAGE_AWS_REGION: str | None = None
|
|
WHEREBY_STORAGE_AWS_ACCESS_KEY_ID: str | None = None
|
|
WHEREBY_STORAGE_AWS_SECRET_ACCESS_KEY: str | None = None
|
|
|
|
# Daily.co storage configuration
|
|
DAILYCO_STORAGE_AWS_BUCKET_NAME: str | None = None
|
|
DAILYCO_STORAGE_AWS_REGION: str | None = None
|
|
DAILYCO_STORAGE_AWS_ROLE_ARN: str | None = None
|
|
|
|
# Translate into the target language
|
|
TRANSLATION_BACKEND: str = "passthrough"
|
|
TRANSLATE_URL: str | None = None
|
|
TRANSLATE_TIMEOUT: int = 90
|
|
|
|
# Translation: modal backend
|
|
TRANSLATE_MODAL_API_KEY: str | None = None
|
|
|
|
# LLM
|
|
LLM_MODEL: str = "microsoft/phi-4"
|
|
LLM_URL: str | None = None
|
|
LLM_API_KEY: str | None = None
|
|
LLM_CONTEXT_WINDOW: int = 16000
|
|
|
|
LLM_PARSE_MAX_RETRIES: int = (
|
|
3 # Max retries for JSON/validation errors (total attempts = retries + 1)
|
|
)
|
|
LLM_STRUCTURED_RESPONSE_TIMEOUT: int = (
|
|
300 # Timeout in seconds for structured responses (5 minutes)
|
|
)
|
|
|
|
# Diarization
|
|
# backend: modal — HTTP API client (works with Modal.com OR self-hosted gpu/self_hosted/)
|
|
DIARIZATION_ENABLED: bool = True
|
|
DIARIZATION_BACKEND: str = "modal"
|
|
DIARIZATION_URL: str | None = None
|
|
DIARIZATION_FILE_TIMEOUT: int = 600
|
|
|
|
# Diarization: modal backend
|
|
DIARIZATION_MODAL_API_KEY: str | None = None
|
|
|
|
# Audio Padding (Modal.com backend)
|
|
PADDING_URL: str | None = None
|
|
PADDING_MODAL_API_KEY: str | None = None
|
|
|
|
# Sentry
|
|
SENTRY_DSN: str | None = None
|
|
|
|
# User authentication (none, jwt)
|
|
AUTH_BACKEND: str = "none"
|
|
|
|
# User authentication using JWT
|
|
AUTH_JWT_ALGORITHM: str = "RS256"
|
|
AUTH_JWT_PUBLIC_KEY: str | None = "authentik.monadical.com_public.pem"
|
|
AUTH_JWT_AUDIENCE: str | None = None
|
|
|
|
PUBLIC_MODE: bool = False
|
|
PUBLIC_DATA_RETENTION_DAYS: PositiveInt = 7
|
|
|
|
# Min transcript length to generate topic + summary
|
|
MIN_TRANSCRIPT_LENGTH: int = 750
|
|
|
|
# Celery
|
|
CELERY_BROKER_URL: str = "redis://localhost:6379/1"
|
|
CELERY_RESULT_BACKEND: str = "redis://localhost:6379/1"
|
|
|
|
# Redis
|
|
REDIS_HOST: str = "localhost"
|
|
REDIS_PORT: int = 6379
|
|
REDIS_CACHE_DB: int = 2
|
|
|
|
# Secret key
|
|
SECRET_KEY: str = "changeme-f02f86fd8b3e4fd892c6043e5a298e21"
|
|
|
|
# Current hosting/domain
|
|
BASE_URL: str = "http://localhost:1250"
|
|
|
|
# Profiling
|
|
PROFILING: bool = False
|
|
|
|
# Healthcheck
|
|
HEALTHCHECK_URL: str | None = None
|
|
|
|
# Whereby integration
|
|
WHEREBY_API_URL: str = "https://api.whereby.dev/v1"
|
|
WHEREBY_API_KEY: NonEmptyString | None = None
|
|
WHEREBY_WEBHOOK_SECRET: str | None = None
|
|
AWS_PROCESS_RECORDING_QUEUE_URL: str | None = None
|
|
SQS_POLLING_TIMEOUT_SECONDS: int = 60
|
|
|
|
# Daily.co integration
|
|
DAILY_API_KEY: str | None = None
|
|
DAILY_WEBHOOK_SECRET: str | None = None
|
|
DAILY_SUBDOMAIN: str | None = None
|
|
DAILY_WEBHOOK_UUID: str | None = (
|
|
None # Webhook UUID for this environment. Not used by production code
|
|
)
|
|
# Platform Configuration
|
|
DEFAULT_VIDEO_PLATFORM: Platform = DAILY_PLATFORM
|
|
|
|
# Zulip integration
|
|
ZULIP_REALM: str | None = None
|
|
ZULIP_API_KEY: str | None = None
|
|
ZULIP_BOT_EMAIL: str | None = None
|
|
|
|
# Hatchet workflow orchestration (always enabled for multitrack processing)
|
|
HATCHET_CLIENT_TOKEN: str | None = None
|
|
HATCHET_CLIENT_TLS_STRATEGY: str = "none" # none, tls, mtls
|
|
HATCHET_DEBUG: bool = False
|
|
|
|
|
|
settings = Settings()
|