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>
96 lines
4.3 KiB
Text
96 lines
4.3 KiB
Text
# =============================================================================
|
|
# Apache config fragment — Accessible Video Platform
|
|
# Inject into: /etc/apache2/sites-available/optical-dev.oliver.solutions-ssl.conf
|
|
#
|
|
# Required modules:
|
|
# sudo a2enmod proxy proxy_http proxy_wstunnel rewrite headers
|
|
#
|
|
# Container port map:
|
|
# accessible-video-api → 0.0.0.0:8012->8000/tcp
|
|
# =============================================================================
|
|
|
|
# ── Timeouts for large video uploads (up to 2 GB, ~10 min) ──────────────────
|
|
<IfModule mod_proxy.c>
|
|
ProxyTimeout 600
|
|
</IfModule>
|
|
|
|
# ── WebSocket proxy (MUST be before /api/ HTTP proxy) ───────────────────────
|
|
# disablereuse=on prevents long-lived WS connections from exhausting the pool
|
|
ProxyPassMatch ^/video-accessibility/api/v1/ws/(.*)$ ws://127.0.0.1:8012/api/v1/ws/$1 disablereuse=on
|
|
ProxyPassReverse /video-accessibility/api/v1/ws/ ws://127.0.0.1:8012/api/v1/ws/
|
|
|
|
# ── API proxy ────────────────────────────────────────────────────────────────
|
|
# Strips /video-accessibility prefix — FastAPI sees /api/v1/...
|
|
ProxyPassMatch ^/video-accessibility/api/(.*)$ http://127.0.0.1:8012/api/$1
|
|
ProxyPassReverse /video-accessibility/api/ http://127.0.0.1:8012/api/
|
|
|
|
# Swagger / OpenAPI
|
|
ProxyPassMatch ^/video-accessibility/docs(/.*)?$ http://127.0.0.1:8012/docs$1
|
|
ProxyPassReverse /video-accessibility/docs http://127.0.0.1:8012/docs
|
|
ProxyPassMatch ^/video-accessibility/openapi\.json$ http://127.0.0.1:8012/openapi.json
|
|
ProxyPassReverse /video-accessibility/openapi.json http://127.0.0.1:8012/openapi.json
|
|
|
|
# ── SPA static files ─────────────────────────────────────────────────────────
|
|
Alias /video-accessibility /var/www/html/video-accessibility
|
|
<Directory /var/www/html/video-accessibility>
|
|
Options -Indexes +FollowSymLinks
|
|
AllowOverride None
|
|
Require all granted
|
|
|
|
# Allow video uploads up to 2 GB
|
|
LimitRequestBody 2147483648
|
|
|
|
RewriteEngine On
|
|
RewriteBase /video-accessibility/
|
|
|
|
# Serve real files/directories directly (JS, CSS, assets, fonts)
|
|
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
|
RewriteCond %{REQUEST_FILENAME} -d
|
|
RewriteRule ^ - [L]
|
|
|
|
# Everything else → index.html (React Router handles client-side nav)
|
|
RewriteRule ^ index.html [L]
|
|
|
|
# Cache-bust hashed assets indefinitely; never cache HTML
|
|
<FilesMatch "\.(js|css|woff2?|ttf|eot|png|jpg|jpeg|gif|ico|svg)$">
|
|
Header set Cache-Control "public, max-age=31536000, immutable"
|
|
</FilesMatch>
|
|
<FilesMatch "\.html$">
|
|
Header set Cache-Control "no-cache, no-store, must-revalidate"
|
|
</FilesMatch>
|
|
|
|
# Security headers
|
|
Header always set X-Frame-Options "SAMEORIGIN"
|
|
Header always set X-Content-Type-Options "nosniff"
|
|
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
|
</Directory>
|
|
|
|
# =============================================================================
|
|
# Full VirtualHost skeleton (reference — values match optical-web-1)
|
|
# =============================================================================
|
|
#
|
|
# <VirtualHost *:443>
|
|
# ServerName optical-dev.oliver.solutions
|
|
# DocumentRoot /var/www/html
|
|
#
|
|
# SSLEngine on
|
|
# SSLCertificateFile /path/to/wildcard.crt
|
|
# SSLCertificateKeyFile /path/to/wildcard.key
|
|
#
|
|
# SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
|
|
# SSLCipherSuite HIGH:!aNULL:!MD5
|
|
#
|
|
# # — paste the block above here —
|
|
#
|
|
# ErrorLog ${APACHE_LOG_DIR}/optical-dev-error.log
|
|
# CustomLog ${APACHE_LOG_DIR}/optical-dev-access.log combined
|
|
# </VirtualHost>
|
|
|
|
# =============================================================================
|
|
# Verify
|
|
# =============================================================================
|
|
# sudo apache2ctl configtest
|
|
# sudo systemctl reload apache2
|
|
# curl -I https://optical-dev.oliver.solutions/video-accessibility/
|
|
# curl https://optical-dev.oliver.solutions/video-accessibility/api/v1/health
|
|
# wscat -c wss://optical-dev.oliver.solutions/video-accessibility/api/v1/ws/job-list
|