- New services/cost_tracker.py: sync httpx preflight()/record() + async wrappers; BudgetExceeded exception; no-op when COST_TRACKER_BASE_URL is empty - Preflight budget check added before ingestion (Gemini), per-language translation (video-native + traditional), and per-language TTS dispatch - _record_gemini_usage and _record_tts_cost now call cost_tracker directly; removes broken asyncio.get_event_loop() hack from sync Celery worker - Fix: _cost_ctx now threaded into extract_accessibility_targeted (video-native path) - Fix: user_id/cost_project_id now propagated through dispatch_language_tts → synthesize_cue_task.s() and the rerender_accessible_video.py re-render path - Remove oliver-cost-tracker SDK dependency (was commented-out/never installed) - Drop cost_tracker_outbox_path setting and get_cost_tracker() factory - Update COST_TRACKER_BASE_URL default to optical-dev.oliver.solutions in .env.prod.example, docker-compose.yml, and all Cloud Run service yamls - Cloud Run yamls use Secret Manager ref (cost-tracker-api-key) for the API key Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
558 lines
19 KiB
YAML
558 lines
19 KiB
YAML
# =============================================================================
|
|
# Docker Compose Configuration for Accessible Video Processing Platform
|
|
# =============================================================================
|
|
# Services:
|
|
# - api: FastAPI + Gunicorn REST API
|
|
# - worker: Celery worker for background processing (default,ingest,notify,render)
|
|
# - tts-worker: Dedicated TTS worker (tts queue, concurrency=8)
|
|
# - ffmpeg-worker: Dedicated FFmpeg worker (ffmpeg queue, concurrency=1)
|
|
# - whisper-worker: Dedicated Whisper worker (whisper queue, concurrency=1)
|
|
# - mongodb: MongoDB database
|
|
# - redis: Redis for Celery broker and cache
|
|
# =============================================================================
|
|
|
|
version: '3.8'
|
|
|
|
services:
|
|
# ---------------------------------------------------------------------------
|
|
# MongoDB Database
|
|
# ---------------------------------------------------------------------------
|
|
mongodb:
|
|
image: mongo:7.0
|
|
container_name: accessible-video-mongodb
|
|
restart: unless-stopped
|
|
command: ["mongod", "--config", "/etc/mongod.conf", "--quiet"]
|
|
environment:
|
|
MONGO_INITDB_DATABASE: ${MONGODB_DB:-accessible_video}
|
|
volumes:
|
|
- mongodb-data:/data/db
|
|
- mongodb-config:/data/configdb
|
|
- ./config/mongod.conf:/etc/mongod.conf:ro
|
|
networks:
|
|
- accessible-video-network
|
|
healthcheck:
|
|
# TCP port check avoids mongosh connection metadata spam in logs
|
|
test: ["CMD-SHELL", "timeout 5 bash -c '</dev/tcp/localhost/27017' || exit 1"]
|
|
interval: 60s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 15s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Redis Cache and Message Broker
|
|
# ---------------------------------------------------------------------------
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: accessible-video-redis
|
|
restart: unless-stopped
|
|
command: redis-server --appendonly yes --maxmemory 2gb --maxmemory-policy allkeys-lru
|
|
volumes:
|
|
- redis-data:/data
|
|
networks:
|
|
- accessible-video-network
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 5s
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# FastAPI Backend API
|
|
# ---------------------------------------------------------------------------
|
|
api:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
target: api
|
|
container_name: accessible-video-api
|
|
restart: unless-stopped
|
|
depends_on:
|
|
mongodb:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
ports:
|
|
- "8003:8000"
|
|
environment:
|
|
# App configuration
|
|
APP_ENV: ${APP_ENV:-dev}
|
|
API_BASE_URL: ${API_BASE_URL:-http://localhost:8000}
|
|
|
|
# Auth
|
|
JWT_SECRET: ${JWT_SECRET}
|
|
JWT_ALG: ${JWT_ALG:-HS256}
|
|
JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-240}
|
|
JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-7}
|
|
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-ai-sandbox.oliver.solutions}
|
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
|
COOKIE_SAMESITE: ${COOKIE_SAMESITE:-Lax}
|
|
|
|
# Database
|
|
MONGODB_URI: mongodb://mongodb:27017/${MONGODB_DB:-accessible_video}
|
|
MONGODB_DB: ${MONGODB_DB:-accessible_video}
|
|
|
|
# Redis
|
|
REDIS_URL: redis://redis:6379/0
|
|
CELERY_BROKER_URL: redis://redis:6379/0
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
|
|
|
# GCP
|
|
GCP_PROJECT_ID: ${GCP_PROJECT_ID}
|
|
GCS_BUCKET: ${GCS_BUCKET:-accessible-video}
|
|
GOOGLE_APPLICATION_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# AI Services
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|
TRANSLATE_API_KEY: ${TRANSLATE_API_KEY:-}
|
|
ELEVENLABS_API_KEY: ${ELEVENLABS_API_KEY:-}
|
|
|
|
# Email
|
|
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
|
|
EMAIL_FROM: ${EMAIL_FROM:-noreply@ai-sandbox.oliver.solutions}
|
|
CLIENT_BASE_URL: ${CLIENT_BASE_URL:-https://ai-sandbox.oliver.solutions/video-accessibility}
|
|
|
|
# Microsoft Authentication
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
|
|
AZURE_AUTHORITY: ${AZURE_AUTHORITY:-}
|
|
AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
|
|
|
|
# CORS
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:6001,http://localhost:5173,http://localhost:3000}
|
|
|
|
# Observability
|
|
SENTRY_DSN: ${SENTRY_DSN:-}
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-}
|
|
|
|
# AI Cost Tracker
|
|
COST_TRACKER_BASE_URL: ${COST_TRACKER_BASE_URL:-}
|
|
COST_TRACKER_API_KEY: ${COST_TRACKER_API_KEY:-}
|
|
COST_TRACKER_SOURCE_APP: ${COST_TRACKER_SOURCE_APP:-video-accessibility}
|
|
COST_TRACKER_ENABLED: ${COST_TRACKER_ENABLED:-true}
|
|
volumes:
|
|
- ./secrets:/secrets:ro
|
|
- api-logs:/app/logs
|
|
networks:
|
|
- accessible-video-network
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Celery Worker for Background Processing (excludes ffmpeg and whisper queues)
|
|
# ---------------------------------------------------------------------------
|
|
worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
target: worker
|
|
container_name: accessible-video-worker
|
|
restart: unless-stopped
|
|
user: root
|
|
command: >
|
|
sh -c "chown -R app:app /shared-tmp &&
|
|
su app -c 'celery -A celery_worker worker -Q default,ingest,notify,render --loglevel=info --concurrency=${WORKER_CONCURRENCY:-8}'"
|
|
depends_on:
|
|
mongodb:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
environment:
|
|
# Shared temp directory for ffmpeg operations
|
|
TMPDIR: /shared-tmp
|
|
# App configuration
|
|
APP_ENV: ${APP_ENV:-dev}
|
|
|
|
# Cloud Run Service URLs (set these to enable Cloud Run autoscaling)
|
|
# When set, CPU-intensive operations are offloaded to Cloud Run
|
|
WHISPER_SERVICE_URL: ${WHISPER_SERVICE_URL:-}
|
|
FFMPEG_SERVICE_URL: ${FFMPEG_SERVICE_URL:-}
|
|
|
|
# Auth (required by Settings class even though worker doesn't use it)
|
|
JWT_SECRET: ${JWT_SECRET}
|
|
JWT_ALG: ${JWT_ALG:-HS256}
|
|
JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-240}
|
|
JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-7}
|
|
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-ai-sandbox.oliver.solutions}
|
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
|
COOKIE_SAMESITE: ${COOKIE_SAMESITE:-Lax}
|
|
|
|
# Database
|
|
MONGODB_URI: mongodb://mongodb:27017/${MONGODB_DB:-accessible_video}
|
|
MONGODB_DB: ${MONGODB_DB:-accessible_video}
|
|
|
|
# Redis
|
|
REDIS_URL: redis://redis:6379/0
|
|
CELERY_BROKER_URL: redis://redis:6379/0
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
|
|
|
# GCP
|
|
GCP_PROJECT_ID: ${GCP_PROJECT_ID}
|
|
GCS_BUCKET: ${GCS_BUCKET:-accessible-video}
|
|
GOOGLE_APPLICATION_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# AI Services
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|
TRANSLATE_API_KEY: ${TRANSLATE_API_KEY:-}
|
|
ELEVENLABS_API_KEY: ${ELEVENLABS_API_KEY:-}
|
|
GOOGLE_TTS_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# Email
|
|
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
|
|
EMAIL_FROM: ${EMAIL_FROM:-noreply@ai-sandbox.oliver.solutions}
|
|
CLIENT_BASE_URL: ${CLIENT_BASE_URL:-https://ai-sandbox.oliver.solutions/video-accessibility}
|
|
|
|
# Microsoft Authentication
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
|
|
AZURE_AUTHORITY: ${AZURE_AUTHORITY:-}
|
|
AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
|
|
|
|
# CORS
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:6001,http://localhost:5173,http://localhost:3000}
|
|
|
|
# Observability
|
|
SENTRY_DSN: ${SENTRY_DSN:-}
|
|
|
|
# AI Cost Tracker
|
|
COST_TRACKER_BASE_URL: ${COST_TRACKER_BASE_URL:-}
|
|
COST_TRACKER_API_KEY: ${COST_TRACKER_API_KEY:-}
|
|
COST_TRACKER_SOURCE_APP: ${COST_TRACKER_SOURCE_APP:-video-accessibility}
|
|
COST_TRACKER_ENABLED: ${COST_TRACKER_ENABLED:-true}
|
|
volumes:
|
|
- ./secrets:/secrets:ro
|
|
- worker-logs:/app/logs
|
|
- shared-tmp:/shared-tmp
|
|
networks:
|
|
- accessible-video-network
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# TTS Worker - Dedicated worker for TTS synthesis (concurrency=8)
|
|
# ---------------------------------------------------------------------------
|
|
tts-worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
target: worker
|
|
container_name: accessible-video-tts-worker
|
|
restart: unless-stopped
|
|
user: root
|
|
command: >
|
|
sh -c "chown -R app:app /shared-tmp 2>/dev/null || true &&
|
|
su app -c 'celery -A celery_worker worker -Q tts --loglevel=info --concurrency=8'"
|
|
depends_on:
|
|
mongodb:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
environment:
|
|
# Shared temp directory
|
|
TMPDIR: /shared-tmp
|
|
# App configuration
|
|
APP_ENV: ${APP_ENV:-dev}
|
|
|
|
# Auth (required by Settings class even though worker doesn't use it)
|
|
JWT_SECRET: ${JWT_SECRET}
|
|
JWT_ALG: ${JWT_ALG:-HS256}
|
|
JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-240}
|
|
JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-7}
|
|
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-ai-sandbox.oliver.solutions}
|
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
|
COOKIE_SAMESITE: ${COOKIE_SAMESITE:-Lax}
|
|
|
|
# Database
|
|
MONGODB_URI: mongodb://mongodb:27017/${MONGODB_DB:-accessible_video}
|
|
MONGODB_DB: ${MONGODB_DB:-accessible_video}
|
|
|
|
# Redis
|
|
REDIS_URL: redis://redis:6379/0
|
|
CELERY_BROKER_URL: redis://redis:6379/0
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
|
|
|
# GCP
|
|
GCP_PROJECT_ID: ${GCP_PROJECT_ID}
|
|
GCS_BUCKET: ${GCS_BUCKET:-accessible-video}
|
|
GOOGLE_APPLICATION_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# AI Services
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|
TRANSLATE_API_KEY: ${TRANSLATE_API_KEY:-}
|
|
ELEVENLABS_API_KEY: ${ELEVENLABS_API_KEY:-}
|
|
GOOGLE_TTS_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# Email
|
|
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
|
|
EMAIL_FROM: ${EMAIL_FROM:-noreply@ai-sandbox.oliver.solutions}
|
|
CLIENT_BASE_URL: ${CLIENT_BASE_URL:-https://ai-sandbox.oliver.solutions/video-accessibility}
|
|
|
|
# Microsoft Authentication
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
|
|
AZURE_AUTHORITY: ${AZURE_AUTHORITY:-}
|
|
AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
|
|
|
|
# CORS
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:6001,http://localhost:5173,http://localhost:3000}
|
|
|
|
# Observability
|
|
SENTRY_DSN: ${SENTRY_DSN:-}
|
|
|
|
# AI Cost Tracker
|
|
COST_TRACKER_BASE_URL: ${COST_TRACKER_BASE_URL:-}
|
|
COST_TRACKER_API_KEY: ${COST_TRACKER_API_KEY:-}
|
|
COST_TRACKER_SOURCE_APP: ${COST_TRACKER_SOURCE_APP:-video-accessibility}
|
|
COST_TRACKER_ENABLED: ${COST_TRACKER_ENABLED:-true}
|
|
volumes:
|
|
- ./secrets:/secrets:ro
|
|
- tts-worker-logs:/app/logs
|
|
- shared-tmp:/shared-tmp
|
|
networks:
|
|
- accessible-video-network
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# FFmpeg Worker - Dedicated worker for video encoding
|
|
# Concurrency: 1 for local mode (CPU bound), 20 for Cloud Run mode (HTTP calls)
|
|
# ---------------------------------------------------------------------------
|
|
ffmpeg-worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
target: worker
|
|
container_name: accessible-video-ffmpeg-worker
|
|
restart: unless-stopped
|
|
user: root
|
|
command: >
|
|
sh -c "chown -R app:app /shared-tmp 2>/dev/null || true &&
|
|
su app -c 'celery -A celery_worker worker -Q ffmpeg --loglevel=info --concurrency=${FFMPEG_WORKER_CONCURRENCY:-1}'"
|
|
depends_on:
|
|
mongodb:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
environment:
|
|
# Shared temp directory for ffmpeg operations
|
|
TMPDIR: /shared-tmp
|
|
# App configuration
|
|
APP_ENV: ${APP_ENV:-dev}
|
|
|
|
# Cloud Run Service URLs (set these to enable Cloud Run autoscaling)
|
|
# When set, FFmpeg operations are offloaded to Cloud Run (HTTP calls)
|
|
# This allows higher concurrency since workers just wait for HTTP responses
|
|
FFMPEG_SERVICE_URL: ${FFMPEG_SERVICE_URL:-}
|
|
|
|
# Auth (required by Settings class even though worker doesn't use it)
|
|
JWT_SECRET: ${JWT_SECRET}
|
|
JWT_ALG: ${JWT_ALG:-HS256}
|
|
JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-240}
|
|
JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-7}
|
|
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-ai-sandbox.oliver.solutions}
|
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
|
COOKIE_SAMESITE: ${COOKIE_SAMESITE:-Lax}
|
|
|
|
# Database
|
|
MONGODB_URI: mongodb://mongodb:27017/${MONGODB_DB:-accessible_video}
|
|
MONGODB_DB: ${MONGODB_DB:-accessible_video}
|
|
|
|
# Redis
|
|
REDIS_URL: redis://redis:6379/0
|
|
CELERY_BROKER_URL: redis://redis:6379/0
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
|
|
|
# GCP
|
|
GCP_PROJECT_ID: ${GCP_PROJECT_ID}
|
|
GCS_BUCKET: ${GCS_BUCKET:-accessible-video}
|
|
GOOGLE_APPLICATION_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# AI Services
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|
TRANSLATE_API_KEY: ${TRANSLATE_API_KEY:-}
|
|
ELEVENLABS_API_KEY: ${ELEVENLABS_API_KEY:-}
|
|
GOOGLE_TTS_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# Email
|
|
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
|
|
EMAIL_FROM: ${EMAIL_FROM:-noreply@ai-sandbox.oliver.solutions}
|
|
CLIENT_BASE_URL: ${CLIENT_BASE_URL:-https://ai-sandbox.oliver.solutions/video-accessibility}
|
|
|
|
# Microsoft Authentication
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
|
|
AZURE_AUTHORITY: ${AZURE_AUTHORITY:-}
|
|
AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
|
|
|
|
# CORS
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:6001,http://localhost:5173,http://localhost:3000}
|
|
|
|
# Observability
|
|
SENTRY_DSN: ${SENTRY_DSN:-}
|
|
|
|
# AI Cost Tracker
|
|
COST_TRACKER_BASE_URL: ${COST_TRACKER_BASE_URL:-}
|
|
COST_TRACKER_API_KEY: ${COST_TRACKER_API_KEY:-}
|
|
COST_TRACKER_SOURCE_APP: ${COST_TRACKER_SOURCE_APP:-video-accessibility}
|
|
COST_TRACKER_ENABLED: ${COST_TRACKER_ENABLED:-true}
|
|
volumes:
|
|
- ./secrets:/secrets:ro
|
|
- ffmpeg-worker-logs:/app/logs
|
|
- shared-tmp:/shared-tmp
|
|
networks:
|
|
- accessible-video-network
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Whisper Worker - Dedicated worker for Whisper transcription
|
|
# Concurrency: 1 for local mode (RAM bound ~4-6GB), 10 for Cloud Run mode (HTTP calls)
|
|
# Used for refining AD pause points with word-level speech analysis
|
|
# ---------------------------------------------------------------------------
|
|
whisper-worker:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
target: whisper-worker
|
|
container_name: accessible-video-whisper-worker
|
|
restart: unless-stopped
|
|
user: root
|
|
command: >
|
|
sh -c "chown -R app:app /shared-tmp 2>/dev/null || true &&
|
|
su app -c 'celery -A celery_worker worker -Q whisper --loglevel=info --concurrency=${WHISPER_WORKER_CONCURRENCY:-1} --max-tasks-per-child=50'"
|
|
depends_on:
|
|
mongodb:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
environment:
|
|
# Shared temp directory for audio processing
|
|
TMPDIR: /shared-tmp
|
|
# App configuration
|
|
APP_ENV: ${APP_ENV:-dev}
|
|
|
|
# Cloud Run Service URL (set to enable Cloud Run autoscaling)
|
|
# When set, Whisper transcription is offloaded to Cloud Run (HTTP calls)
|
|
# This allows higher concurrency since workers just wait for HTTP responses
|
|
WHISPER_SERVICE_URL: ${WHISPER_SERVICE_URL:-}
|
|
|
|
# Whisper Configuration (for local mode only)
|
|
WHISPER_MODEL: ${WHISPER_MODEL:-medium}
|
|
|
|
# Auth (required by Settings class even though worker doesn't use it)
|
|
JWT_SECRET: ${JWT_SECRET}
|
|
JWT_ALG: ${JWT_ALG:-HS256}
|
|
JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-240}
|
|
JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-7}
|
|
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-ai-sandbox.oliver.solutions}
|
|
COOKIE_SECURE: ${COOKIE_SECURE:-true}
|
|
COOKIE_SAMESITE: ${COOKIE_SAMESITE:-Lax}
|
|
|
|
# Database
|
|
MONGODB_URI: mongodb://mongodb:27017/${MONGODB_DB:-accessible_video}
|
|
MONGODB_DB: ${MONGODB_DB:-accessible_video}
|
|
|
|
# Redis
|
|
REDIS_URL: redis://redis:6379/0
|
|
CELERY_BROKER_URL: redis://redis:6379/0
|
|
CELERY_RESULT_BACKEND: redis://redis:6379/0
|
|
|
|
# GCP
|
|
GCP_PROJECT_ID: ${GCP_PROJECT_ID}
|
|
GCS_BUCKET: ${GCS_BUCKET:-accessible-video}
|
|
GOOGLE_APPLICATION_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# AI Services
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|
TRANSLATE_API_KEY: ${TRANSLATE_API_KEY:-}
|
|
ELEVENLABS_API_KEY: ${ELEVENLABS_API_KEY:-}
|
|
GOOGLE_TTS_CREDENTIALS: /secrets/gcp-credentials.json
|
|
|
|
# Email
|
|
SENDGRID_API_KEY: ${SENDGRID_API_KEY:-}
|
|
EMAIL_FROM: ${EMAIL_FROM:-noreply@ai-sandbox.oliver.solutions}
|
|
CLIENT_BASE_URL: ${CLIENT_BASE_URL:-https://ai-sandbox.oliver.solutions/video-accessibility}
|
|
|
|
# Microsoft Authentication
|
|
AZURE_CLIENT_ID: ${AZURE_CLIENT_ID:-}
|
|
AZURE_AUTHORITY: ${AZURE_AUTHORITY:-}
|
|
AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI:-}
|
|
|
|
# CORS
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:6001,http://localhost:5173,http://localhost:3000}
|
|
|
|
# Observability
|
|
SENTRY_DSN: ${SENTRY_DSN:-}
|
|
|
|
# AI Cost Tracker
|
|
COST_TRACKER_BASE_URL: ${COST_TRACKER_BASE_URL:-}
|
|
COST_TRACKER_API_KEY: ${COST_TRACKER_API_KEY:-}
|
|
COST_TRACKER_SOURCE_APP: ${COST_TRACKER_SOURCE_APP:-video-accessibility}
|
|
COST_TRACKER_ENABLED: ${COST_TRACKER_ENABLED:-true}
|
|
volumes:
|
|
- ./secrets:/secrets:ro
|
|
- whisper-worker-logs:/app/logs
|
|
- shared-tmp:/shared-tmp
|
|
networks:
|
|
- accessible-video-network
|
|
# Memory limit to prevent OOM (Whisper large-v3 model uses ~4-6GB)
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 8G
|
|
reservations:
|
|
memory: 4G
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
|
|
# =============================================================================
|
|
# Networks
|
|
# =============================================================================
|
|
networks:
|
|
accessible-video-network:
|
|
driver: bridge
|
|
name: accessible-video-network
|
|
|
|
# =============================================================================
|
|
# Volumes
|
|
# =============================================================================
|
|
volumes:
|
|
mongodb-data:
|
|
name: accessible-video-mongodb-data
|
|
mongodb-config:
|
|
name: accessible-video-mongodb-config
|
|
redis-data:
|
|
name: accessible-video-redis-data
|
|
api-logs:
|
|
name: accessible-video-api-logs
|
|
worker-logs:
|
|
name: accessible-video-worker-logs
|
|
ffmpeg-worker-logs:
|
|
name: accessible-video-ffmpeg-worker-logs
|
|
tts-worker-logs:
|
|
name: accessible-video-tts-worker-logs
|
|
whisper-worker-logs:
|
|
name: accessible-video-whisper-worker-logs
|
|
shared-tmp:
|
|
name: accessible-video-shared-tmp
|