Files
MatchLiveTv/docs/REPLAY_MODULE.md
Emiliano Frascaro ab9cb02083 Aggiunge overlay server-side burn-in e stabilizza diretta live.
Tabellone, badge e brand sono ricodificati nel flusso _air via OverlayRelay;
sync punteggio HTTP, volume condiviso rails/sidekiq, qualità 720p migliorata
e badge CONNECTING in ripresa da pausa.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 23:55:17 +02:00

136 lines
4.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Modulo Replay — Match Live TV
## Panoramica
Al termine di ogni diretta Premium, MediaMTX registra i segmenti. Sidekiq unisce i segmenti, genera thumbnail, carica su **Garage (S3-compatible)** e attiva i servizi di notifica, statistiche e (opzionale) republicazione YouTube.
## Piani e retention
| Piano | Registrazione | Retention | Download MP4 | YouTube VOD |
|-------|---------------|-----------|--------------|-------------|
| Free | No | — | No | No |
| Premium Light | Sì | 30 giorni | Sì | No |
| Premium Full | Sì | 90 giorni | Sì | Sì (auto se diretta YouTube) |
## Funzionalità implementate
### 1. Registrazione automatica
Pipeline: `Sessions::Stop``FinalizeSession``UploadJob` → storage.
MediaMTX registra **solo mentre il telefono pubblica** (RTMP connesso). In pausa o con sola slate `alwaysAvailable` la registrazione è disattivata, così il replay non contiene minuti di schermo «Trasmissione in pausa».
### 2. Retention e purge
`Recordings::PurgeExpiredJob` / `rails recordings:purge_expired`
### 3. Archivio Replay
- Web: `/clubs/:id/replays` (gestione società)
- Pubblico: `/replay` con filtro società/squadra
- App: schermata Replay
### 4. Riproduzione
- Player MP4: `/replay/:id` + stream `/replay/:id/stream`
- Contatore visualizzazioni su ogni play (`view_count`)
### 5. Visibilità
Pubblico / Privato (unlisted), modificabile dalladmin società.
### 6. Eliminazione anticipata
`Recordings::Delete` — DB + video + thumbnail su storage.
### 7. Dashboard KPI
Replay disponibili, in scadenza (7 gg), spazio occupato, **visualizzazioni totali**.
### 8. Miglioramenti Premium
| Feature | Descrizione |
|---------|-------------|
| **Email replay pronto** | A owner e membri società quando status → `ready` |
| **Email scadenza** | 7 giorni prima di `expires_at` (`rails recordings:expiry_warnings`) |
| **Thumbnail** | Frame ffmpeg, URL `/replay/:id/thumbnail` |
| **Download MP4** | Premium, link presigned 15 min o `/replay/:id/download` |
| **Statistiche views** | `view_count` su ogni replay |
| **metadata JSONB** | `source_platform`, `auto_publish_youtube`, `ai: {}` per estensioni |
| **YouTube VOD** | Premium Full: upload automatico se diretta era su YouTube; manuale da archivio |
## Storage
```env
REPLAY_STORAGE_ENDPOINT=http://garage:3900
REPLAY_STORAGE_BUCKET=matchlivetv-replays
REPLAY_STORAGE_ACCESS_KEY_ID=...
REPLAY_STORAGE_SECRET_ACCESS_KEY=...
REPLAY_DOWNLOAD_URL_TTL_SECONDS=900
```
Senza endpoint S3: storage locale `/recordings/replays/`.
### Dev locale con Garage
```bash
cd infra
docker compose up -d # include garage
bash scripts/setup_garage_replays.sh # layout, bucket, chiave → .env
docker compose up -d rails sidekiq
# Verifica pipeline (segmento finto → Garage)
docker compose exec -T rails bundle exec rails replay:e2e_garage
```
### Produzione (`/opt/matchlivetv`)
```bash
cd infra
bash scripts/setup_garage_production.sh # garage.prod.toml, bucket, chiavi → .env
# Rails/Sidekiq usano REPLAY_STORAGE_ENDPOINT=http://garage:3900 (rete Docker)
```
**Credenziali in `.env`:** non compilarle a mano in `.env.example`. Lo script scrive in `infra/.env`:
- `REPLAY_STORAGE_ACCESS_KEY_ID` = Key ID Garage (es. `GK...`)
- `REPLAY_STORAGE_SECRET_ACCESS_KEY` = Secret mostrato una sola volta alla creazione chiave
## Cron (produzione)
Installazione sul server:
```bash
cd /opt/matchlivetv/infra
bash scripts/install_production_cron.sh
```
Job attivi (utente `eminux`):
| Orario | Task |
|--------|------|
| 03:00 | `recordings:purge_expired` — elimina replay scaduti (DB + Garage) |
| 08:00 | `recordings:expiry_warnings` — email avviso scadenza (7 gg) |
Log: `/opt/matchlivetv/log/cron-replay.log`
### Capacità Garage
Allinstallazione, `setup_garage_production.sh` assegna ~**(disco libero 20 GB)** al nodo.
Per ridimensionare dopo:
```bash
bash scripts/garage_set_capacity.sh 85G # oppure senza argomento: calcolo automatico
```
## API mobile
- `GET /teams/:id/recordings` — lista con thumbnail, views, download_enabled
- `GET /recordings/:id/download` — URL download temporaneo
- `POST /recordings/:id/publish_youtube` — coda republicazione YouTube
## Estensioni future (metadata.ai)
Campo `metadata["ai"]` predisposto per:
- highlight automatici
- trascrizioni
- articoli generati
- clip / Shorts
Esempio aggiornamento via API:
```json
{ "recording": { "metadata": { "ai": { "transcript_status": "queued" } } } } }
```