Backend (Phase A): - A1: Adaptive silence buffer — natural_gap_ms persisted per cue; renderer computes per-cue silence_before/silence_after instead of fixed 500ms; per-cue silence files - A2: Forward-preferred snap — snap_pause_point prefers boundaries up to 4s ahead over boundaries within 1.5s behind, reducing mid-scene cuts - A3: Min-gap validation — pause points with < 200ms gap trigger forward search to the next acceptable gap - natural_gap_ms added to PausePointData model and api.ts type - New config fields: whisper_snap_forward_window, whisper_snap_backward_window, ad_silence_buffer_default, ad_silence_buffer_min_after, ad_min_acceptable_gap - Tests: test_whisper_snap.py (13 tests), test_video_renderer_buffers.py Frontend (Phase B): - B1: Drag pause-point markers — pointer state machine with 3px move threshold, clamp to min/max bounds, click-without-move still opens PausePointEditor - B2: Drag freeze blocks — orange blocks translate with linked pause point - B3: Time tooltip visible during drag, hidden on release - Tests: TimelinePreview.drag.test.tsx (10 tests) Fixes: - Share link pointed to ai-sandbox.oliver.solutions — added app_url to Settings with correct optical-dev.oliver.solutions default; share_url now configurable via APP_URL env var - Removed all ai-sandbox.oliver.solutions references from docker-compose, apache config, docs, and scripts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
172 lines
6.8 KiB
Markdown
172 lines
6.8 KiB
Markdown
# Infrastructure — Accessible Video Processing Platform
|
||
|
||
<!-- SCOPE: Declarative inventory of what is deployed and where — servers, services, ports, external dependencies. No procedures (see runbook.md). -->
|
||
<!-- DOC_KIND: explanation -->
|
||
<!-- DOC_ROLE: canonical -->
|
||
<!-- READ_WHEN: Read when you need to know what runs where, which ports are exposed, or which external services are used. -->
|
||
<!-- SKIP_WHEN: Skip when you need deployment steps → runbook.md; API contracts → api_spec.md. -->
|
||
<!-- PRIMARY_SOURCES: docker-compose.yml, backend/app/core/config.py -->
|
||
|
||
**Generated:** 2026-05-01
|
||
|
||
---
|
||
|
||
## Quick Navigation
|
||
|
||
- [Docs Hub](../README.md)
|
||
- [Runbook](runbook.md)
|
||
- [Architecture](architecture.md)
|
||
- [Tech Stack](tech_stack.md)
|
||
|
||
## Agent Entry
|
||
|
||
| Signal | Value |
|
||
|--------|-------|
|
||
| Purpose | Inventory of servers, Docker services, ports, and external dependencies |
|
||
| Read When | You need to know what runs where, port mappings, or external service dependencies |
|
||
| Skip When | You need how-to deploy → runbook.md; API contracts → api_spec.md |
|
||
| Canonical | Yes |
|
||
| Next Docs | [Runbook](runbook.md), [Architecture](architecture.md) |
|
||
| Primary Sources | `docker-compose.yml`, `.env.example` |
|
||
|
||
---
|
||
|
||
## Server Inventory
|
||
|
||
| Server | Role | Environment |
|
||
|--------|------|-------------|
|
||
| `optical-web-1` | Production host — runs all Docker services | Production |
|
||
| Local machine | Developer workstation — Docker Compose local stack | Development |
|
||
|
||
**Production URL:** `https://optical-dev.oliver.solutions/video-accessibility`
|
||
**Production API URL:** `https://optical-dev.oliver.solutions/video-accessibility-back`
|
||
|
||
---
|
||
|
||
## Docker Services
|
||
|
||
All services are defined in `docker-compose.yml` and share the `accessible-video-network` bridge network.
|
||
|
||
| Service | Image / Build | Container Name | Purpose |
|
||
|---------|--------------|----------------|---------|
|
||
| `mongodb` | `mongo:7.0` | `accessible-video-mongodb` | Primary database |
|
||
| `redis` | `redis:7-alpine` | `accessible-video-redis` | Celery broker + result backend |
|
||
| `api` | `./backend` (target: `api`) | `accessible-video-api` | FastAPI REST + WebSocket |
|
||
| `worker` | `./backend` (target: `worker`) | `accessible-video-worker` | Celery: default, ingest, notify, render queues |
|
||
| `tts-worker` | `./backend` (target: `worker`) | `accessible-video-tts-worker` | Celery: tts queue |
|
||
| `ffmpeg-worker` | `./backend` (target: `worker`) | `accessible-video-ffmpeg-worker` | Celery: ffmpeg queue |
|
||
| `whisper-worker` | `./backend` (target: `whisper-worker`) | `accessible-video-whisper-worker` | Celery: whisper queue |
|
||
|
||
---
|
||
|
||
## Port Allocation
|
||
|
||
| Service | Internal Port | External Port | Notes |
|
||
|---------|--------------|---------------|-------|
|
||
| `api` | 8000 | **8012** | Exposed to host |
|
||
| `mongodb` | 27017 | — | Internal only |
|
||
| `redis` | 6379 | — | Internal only |
|
||
| Workers | — | — | No HTTP port |
|
||
|
||
Production: nginx reverse-proxies `optical-web-1:8012` → `https://optical-dev.oliver.solutions/video-accessibility-back`.
|
||
|
||
---
|
||
|
||
## Worker Configuration
|
||
|
||
| Worker | Celery Queues | Concurrency | Memory Limit | Notes |
|
||
|--------|--------------|-------------|--------------|-------|
|
||
| `worker` | `default, ingest, notify, render` | `${WORKER_CONCURRENCY:-8}` | — | General pipeline |
|
||
| `tts-worker` | `tts` | `${TTS_WORKER_CONCURRENCY:-2}` | — | Configurable via env |
|
||
| `ffmpeg-worker` | `ffmpeg` | `${FFMPEG_WORKER_CONCURRENCY:-1}` | — | CPU-bound; 1 local, higher in Cloud Run mode |
|
||
| `whisper-worker` | `whisper` | `${WHISPER_WORKER_CONCURRENCY:-1}` | **8 GB** (4 GB reserved) | RAM-bound; Whisper large-v3 needs ~4–6 GB |
|
||
|
||
Cloud Run offload: when `FFMPEG_SERVICE_URL` or `WHISPER_SERVICE_URL` are set, the respective workers delegate to Cloud Run HTTP endpoints instead of running locally.
|
||
|
||
---
|
||
|
||
## Volumes
|
||
|
||
| Volume Name | Mounted In | Purpose |
|
||
|-------------|-----------|---------|
|
||
| `accessible-video-mongodb-data` | mongodb `/data/db` | MongoDB data |
|
||
| `accessible-video-mongodb-config` | mongodb `/data/configdb` | MongoDB config |
|
||
| `accessible-video-redis-data` | redis `/data` | Redis AOF persistence |
|
||
| `accessible-video-api-logs` | api `/app/logs` | API log files |
|
||
| `accessible-video-worker-logs` | worker `/app/logs` | Worker log files |
|
||
| `accessible-video-tts-worker-logs` | tts-worker `/app/logs` | TTS worker logs |
|
||
| `accessible-video-ffmpeg-worker-logs` | ffmpeg-worker `/app/logs` | FFmpeg worker logs |
|
||
| `accessible-video-whisper-worker-logs` | whisper-worker `/app/logs` | Whisper worker logs |
|
||
| `accessible-video-shared-tmp` | worker, tts/ffmpeg/whisper workers `/shared-tmp` | Shared temp dir for FFmpeg operations |
|
||
| `./secrets` (bind mount) | all services `/secrets:ro` | GCP credentials JSON |
|
||
|
||
---
|
||
|
||
## External Dependencies
|
||
|
||
| Service | Purpose | Config Key |
|
||
|---------|---------|------------|
|
||
| Google Cloud Storage | Video files, VTT, MP3, rendered video | `GCS_BUCKET`, `GOOGLE_APPLICATION_CREDENTIALS` |
|
||
| MongoDB Atlas | Production database (can also run local container) | `MONGODB_URI`, `MONGODB_DB` |
|
||
| Gemini 2.5 Pro | VTT generation, translation | `GEMINI_API_KEY` |
|
||
| Google Cloud Translate | Language translation | `TRANSLATE_API_KEY` |
|
||
| Google Cloud TTS | Audio description synthesis | `GOOGLE_TTS_CREDENTIALS` |
|
||
| ElevenLabs | Premium TTS synthesis | `ELEVENLABS_API_KEY` |
|
||
| SendGrid | Transactional email (notifications, delivery) | `SENDGRID_API_KEY` |
|
||
| Azure AD / Microsoft MSAL | SSO authentication | `AZURE_CLIENT_ID`, `AZURE_AUTHORITY`, `AZURE_REDIRECT_URI` |
|
||
| Sentry | Error tracking and alerting | `SENTRY_DSN` |
|
||
| OpenTelemetry / OTLP | Distributed tracing | `OTEL_EXPORTER_OTLP_ENDPOINT` |
|
||
| AI Cost Tracker | Cross-project AI cost tracking (optical-dev) | `COST_TRACKER_BASE_URL`, `COST_TRACKER_API_KEY` |
|
||
| Google Cloud Run (optional) | Offload FFmpeg and Whisper workloads | `FFMPEG_SERVICE_URL`, `WHISPER_SERVICE_URL` |
|
||
|
||
---
|
||
|
||
## Health Checks
|
||
|
||
| Service | Check | Interval |
|
||
|---------|-------|---------|
|
||
| `mongodb` | TCP port 27017 check | 60s (10s timeout, 3 retries) |
|
||
| `redis` | `redis-cli ping` | 30s (10s timeout, 3 retries) |
|
||
| `api` | Depends on mongodb + redis healthy | — |
|
||
| Workers | Depend on mongodb + redis healthy | — |
|
||
|
||
Admin health endpoint: `GET /api/v1/admin/health/detailed` (requires admin Bearer token).
|
||
|
||
---
|
||
|
||
## Redis Configuration
|
||
|
||
```text
|
||
maxmemory 2gb
|
||
maxmemory-policy allkeys-lru
|
||
appendonly yes
|
||
```
|
||
|
||
---
|
||
|
||
## Log Rotation
|
||
|
||
All services use Docker `json-file` logging:
|
||
|
||
```text
|
||
max-size: 10m
|
||
max-file: 3
|
||
```
|
||
|
||
---
|
||
|
||
## Maintenance
|
||
|
||
**Last Updated:** 2026-05-01
|
||
|
||
**Update Triggers:**
|
||
- New service added to `docker-compose.yml`
|
||
- Port mapping changes
|
||
- New external dependency added
|
||
- Worker queue or concurrency configuration changes
|
||
|
||
**Verification:**
|
||
- [ ] All services in `docker-compose.yml` listed
|
||
- [ ] Port table matches `ports:` sections in compose file
|
||
- [ ] External dependencies match env vars in `.env.example`
|
||
- [ ] Volume names match `volumes:` section in compose file
|