VOD and restreaming service
R0-pre draft
severity: medium
milestone: V.2x demo

[AI comment]: Strong brainstorming capture — codec matrix, nginx/ffmpeg snippets, and UI intent are all useful pre-DR material. Before DR/spec split, add one paragraph up front: **product boundary** (standalone “media hub” vs extension of android cast ingest), **alpha vs post-alpha** (scaling spec already slots F2 transcode + F9 3rd-party streaming as post-alpha), and **success criteria** for the first demo (e.g. “one m3u8 in → HLS out + BE config row + web play”).

Problem statement:
- near realtime restreaming service
[AI comment]: Define “near realtime” numerically for this doc — e.g. glass-to-glass target (3 s? 10 s? 30 s?) and whether that applies to **live ingest** only. ffmpeg transcode + HLS segment duration (often 2–6 s) + player buffer usually means **not** sub-second; that is fine if labeled **low-latency VOD/restream**, not WebRTC-class cast.
[foxx answers]: "near realtime" means from 3s delay to infinite (in case of VOD); refine better: let's say 2-10seconds delay from start processing to final destination delivery

- sources: raw audio/video (h264, m4a, mp4, mkv), OBS, VLC, ffmpeg, live and VOD
[AI comment]: Good source list. Add explicit **ingest protocols**: file/URL pull, RTMP push (OBS), optional SRT/RTSP later. Cross-link Janus `:8089` ([INFRA.md](../INFRA.md)) — is live phone cast ever an ingest here, or only file/RTMP/m3u?
[foxx answers]: explicit ingest protocols would be defined as:
- file/URL pull
- OBS RTMP
others to come later (they sill be supported under the hood but not exposed). live phone cast is out of this document, we'll use other technologies for that i suppose.

Requirements:
- limited CPU and RAM on transcode VM
[AI comment]: Tie to [specs/20100612_1_scaling.md](../specs/20100612_1_scaling.md) §12.2 / P7 — transcode must not share the primary DB VM. Document **concurrency model**: N parallel jobs × preset (e.g. 1080p medium) → vCPU/RAM budget; what happens when queue is full (reject, shed resolution, delay).
[foxx answers]: transcode may share DB VM, see no reason not to do it, but the way we expose the DB is debatable; meaning, using DB just via OpenAPI looks way too slow, but exposing the DB as we use it today looks risky and improper. although, MariaDB can be exposed by socket listening which looks like a compromise for demo, I do believe that the real cloud providers have much better and flexible solution to expose a single DB interface for all our service and we don't really care what's behind the hood there and how many terabytes distributed somewhere across the world we're using - we pay money for DB service, our job is just to utilize/integrate its interface. about transcoding - I don't really understand what's the reference between transcoding and db usage. We just need to record some metadata, not so big amount of; like who's the owner of that video, processing pipeline parameters and so on, shareable between different VMs the same way as we'll use other kind of information. if you think otherwise, please share your vision.

- CDN, storage and bandwidth for production
[AI comment]: Needs a **non-goals** line for R0: “no multi-region CDN in v1” vs “must use existing FE/BFF + object store”. Name candidate backends (S3-compatible, local NFS on `be-media`, or FE static) and **egress** ownership (FE vs media worker).[foxx answers]: * no multi-region CDN in v1, local NFS on `BE-media` for feature alpha (demo) release; not really intended to be full-featured, we just need lots of disk space to store videos (~200Gb f0r demo would be enough)

- m3u and youtube as input sources for demo
[AI comment]: **Legal/ToS**: yt-dlp + YouTube as demo input is fine for internal lab; flag as **non-prod** or rights-cleared content only for anything public/commercial. DR should separate “URL ingest” from “YouTube-specific adapter”.
[foxx answers]: good point. any ways to legally grab youtube videos? tagging it as **non-prod** for now, let's see what can we do. rephrasing in general words: not exactly youtube, but any video source that provides pull-alike link (together with access parameters and, probably, in some rare cases - cookies) is acceptable, at least, for lab testing or demo, unless we'll close the gap with legal notes. the mindset there is - better to have the feature and keep it disabled rather not to have it but suddenly being requested to implement it just yesterday; thus we need to hurry up and whole infra is almost ready, we don't have to do any refactoring, etc.

- m3u as output for demo
[AI comment]: Clarify m3u vs m3u8 — playlist **master** vs **media** playlist, and whether output is **HLS** (`.m3u8` + `.ts`/fMP4) served by nginx or plain redirect URLs.
[foxx answers]: see the examples - assuming .m3u8+ts as the most easier way to deliver the content, but AFAIK there should be a master playlist anyway, no? this looks like the implementation details, not a design, correct me if i'm wrong

- nginx and ffmpeg as core
[AI comment]: Reasonable for Alpine lab. Note **nginx-rtmp-module** maintenance/long-term: acceptable for demo; DR should compare **nginx-rtmp + ffmpeg** vs **ffmpeg-only** (publish HLS to disk/object store without RTMP hop) vs dedicated packager (e.g. MediaMTX, SRS) for prod.
[foxx answers]: this is what i'm expecting from you - to close the gaps like that. i don't have deep enough knowledge in that area.

- watermarks
[AI comment]: Distinguish **static burn-in** (ffmpeg overlay, cheap) vs **per-session forensic** (section below). R0 should scope static/logo + optional text; forensic = later phase.
[foxx answers]: totally agree. I will even simplify the things:
Milestone               | Protection feature
-----------------------------------------------------------------------------------------------------------
V.2x demo (unstable)    | No watermarks but keeping this feature in mind to be implemented in near future
V.2x alpha              | Assuming we already published V.1x releases - basic watermarking as a PoC (static burn-in)
V.2x beta               | Introducing per-session forensic watermarking
V.2x                    | All alpha watermarking features plus beta (per-session) as trial feature
-----------------------------------------------------------------------------------------------------------


- stream protection
[AI comment]: Large surface — recommend **phased DR**: (1) signed URLs + short TTL, (2) session-bound tokens via existing BE auth, (3) per-user watermark, (4) ML pirate detection. Do not block core pipeline on (3)–(4).
[foxx comments]: agree, each method deserves its own design. now, since it doesn't require any implementation before V2.x alpha stage. i believe there we'll have feature-rich documentation for stream protection methods we'd like to see.

- parallel disk recording
[AI comment]: Add retention, quota, encryption-at-rest, and whether recordings are **mezzanine** (pre-CDN) or **compliance archive**. Who triggers delete?
[foxx comments]: let's define some details, although, they might change due to experiments and probably the values will be incorrectly established as for now, but:
Key                 | Value (alpha, free of charge) | Value (alpha, pay as you go)        | Value (alpha, subscription paid service emulation)
-----------------------------------------------------------------------------------------------------------------------------------------------------
retention time:     | 5 days                        | per-month payments, so 1 mo         | per-subscription payments, may be up to infinite
quota:              | 3Gb                           | 50Gb/mo, infinite(golden payments)  | infinite till subsription is active
encryption-at-rest  | n/a                           | ?                                   | ?
pre-CDN or...       | not sure I get the question correctly, I think there shouldn't be something before CDN
remove trigger      | cron+script each 5 days       | cron+script, based on pay type      | cron+script, based on subscription/pay type
-----------------------------------------------------------------------------------------------------------------------------------------------------


- BE UI integration, standalone transcode service later
[AI comment]: Good split. Specify **control plane** (PHP/DB: pipeline defs, schedules, ACL) vs **data plane** (ffmpeg workers, nginx). Matches scaling “media worker pool” pattern.
control plane: UI/UX similar page to what we have today, but it will be a bit updated after RBAC review. features:
Type | Value (dev/demo) | Value (staging/prod, v.2x)
dev lang    PHP PHP
web FE      nginx nginx
DB baseline basic metadata and accounting storage (RBAC-linked)   full metadata, accounting info (RBAC-linked), shorthand recording key features, etc.
DB type     mariadb cloud providers distributed DB
DB type     mariadb cloud providers distributed DB
Data plane


UI/UX:
- pipeline config in DB
[AI comment]: Align schema sketch with crash-reporter DB patterns (SQLite/MariaDB?) and whether pipeline state lives in same cluster or dedicated `be-media` DB.

- probe input, select output
[AI comment]: ffprobe JSON → normalized “source profile” table (resolution, codecs, fps, audio channels). Document validation errors for unsupported combos.

- Nuevo Video.js player
[AI comment]: Confirm license (commercial use) and whether Nuevo stays or **Video.js + standard plugins** for alpha. Mobile: native ExoPlayer path vs WebView player — one line each.

- mobile and web playback
[AI comment]: HLS on Android/iOS may need **LL-HLS** or accept standard HLS latency; note **Safari** native HLS vs Chrome MSE.

- popup announcements
[AI comment]: Seems orthogonal to VOD/restream — move to separate “catalog/marketing” DR or mark optional so core media DR stays focused.

Research:
- ffmpeg and nginx on Alpine, 8vcpu, 16gb ram
[AI comment]: Run a **capacity table** (even estimates): e.g. 1× 1080p30 transcode ~X vCPU; max concurrent jobs on 8 vCPU; RAM per ffmpeg (~500MB–2GB). Without this, “limited CPU” requirement is not testable.

- alternatives: cvlc, mediapipe, janus
[AI comment]: **Janus** = WebRTC SFU (F1), not a VOD packager — good for live cast, different from HLS restream. **MediaPipe** = analysis/ML, not a replacement for ffmpeg transcode. **cvlc** = playback/relay edge cases. Keep ffmpeg+nginx as primary; Janus cross-ref for “phone as live source” only.

- ffmpeg build: libx264, libfdk-aac, overlay, ...
[AI comment]: **libfdk-aac is nonfree** — distribution and store policy risk for a commercial app/service. DR must pick: (a) build `--enable-nonfree` for internal lab only, (b) **aac** (native/ffmpeg) or **libopus** for prod, (c) ship codecs only server-side. Document in [COMMERCIAL.md](../COMMERCIAL.md) / license appendix.

- yt-dlp for youtube
[AI comment]: Pin version, update cadence, and failure modes (bot detection, format churn). Wrapper service with timeouts, not shell from PHP directly.

- FFdynamic
[AI comment]: Worth a spike doc: dynamic ffmpeg graphs vs static CLI. If rejected, say why (operational debuggability).

Limitations:
- no dash in Alpine ffmpeg, side load needed
[AI comment]: For R0 **non-goal**: DASH unless side-loaded. **HLS-only** output is enough for demo + most mobile/web if documented. If LL-HLS needed later, separate spec.

How:
- nginx config (rtmp, hls, exec ffmpeg on publish, ...)
[AI comment]: Examples are valuable. Production DR should replace hardcoded IPs (`192.168.122.40`) with templated deploy vars. **exec ffmpeg on publish** couples nginx lifecycle to transcode — prefer **supervisor/systemd** or job queue driving ffmpeg, nginx only serves HLS/RTMP.

- ffmpeg tee + unix pipe multistream
[AI comment]: Clever for 1→N outputs; document **failure modes** (one broken pipe stalls tee?), **ordering** (start nginx-rtmp before publisher), and ops runbook. Simpler v1: single output HLS to disk, add tee in v2.

- 1080p encoding presets
[AI comment]: Good defaults. Add **audio-only** and **copy video + transcode audio** paths to save CPU when source is already H.264.

- Nuevo player HTML fragment
[AI comment]: Fine for spike. Spec should reference **where** this mounts in BE (new vhost vs `apps.f0xx.org` path) — [INFRA.md](../INFRA.md): public apps on FE→BE `:80`, not `:8089`.

Stream protection:
- token/key exchange
[AI comment]: Reuse existing **session/JWT** patterns from 2FA/auth flow where possible; avoid a second ad-hoc crypto system. Short-lived **HLS segment URL signing** (CDN or nginx `secure_link`) is the usual pattern.

- per-user watermarking
[AI comment]: Viable via ffmpeg drawtext/overlay per job; cost = **one transcode per viewer** unless watermark is client-side (weak). DR: forensic vs “good enough” deterrent.

- pirate detection (forensic watermarks, ML vision)
[AI comment]: Mark **R2+ / research** — high cost, false positives, legal workflow. “AI questionable” is fair; do not merge into R0 acceptance criteria.

Open questions:
(awaiting Rev.R0)
[AI comment]: Suggested questions to resolve before DR:
  Q1. Same product as android cast or separate “f0xx media” service?
  Q2. First milestone: live RTMP in, HLS out, or file/VOD only?
  Q3. AuthZ: public unlisted links, logged-in only, or paywall (F5)?
  Q4. Codec policy for prod without libfdk-aac?
  Q5. Object store vs local disk for HLS segments in prod?
  Q6. Observability: per-pipeline metrics (ffmpeg exit code, segment age, bitrate) — Prometheus/Grafana vs logs only?
  Q7. Relationship to scaling **F9** (3rd-party ingest) — is this doc the F9 implementation parent?

[AI comment]: **Suggested DR/spec split** when promoting:
  - DR: architecture choice (control vs data plane, HLS-only, worker sizing, security phases, nonfree codec decision).
  - SPEC-1: pipeline model + DB + BE API + ffprobe.
  - SPEC-2: worker runtime (ffmpeg graphs, nginx-rtmp or alternative, deploy on Alpine).
  - SPEC-3 (optional/post-alpha): stream protection + forensic watermarking.

[AI comment]: **Global verdict** — Yes, the draft is **useful**: it captures real config experiments, constraints (Alpine, CPU), and UI intent. It is **not yet** “well enough described” for implementation without the clarifications above (latency definition, prod codec policy, legal ingest, capacity math, service boundaries, phased security). Recommend **Rev.R0** = answer open questions + trim orthogonal bits (popup announcements) + one demo milestone; then convert to DR + 1–2 specs aligned with `20100612_1_scaling` F2/F9 slots.
