Files
self 1fb848b8cb feat: namespace plugin identity
Adopt canonical plugin id/slug manifest fields, vendor-prefixed OTP app naming, and fully-qualified capability ids for Sender.
2026-05-27 19:05:39 +02:00

182 lines
9.7 KiB
Markdown

# Sender Implementation Progress
This file tracks the planned implementation from plugin template to clustered streaming plugin.
## Phase 0: Architecture and Repo Preparation
- [x] Capture planned architecture in `docs/arch.md`.
- [x] Create this implementation checklist.
- [x] Rename user-facing copy from generic "My Plugin" to Sender/Streaming.
- [x] Update `manifest.json` description, capabilities, `migrations`, and `children`.
- [x] Enable the plugin supervision tree in `mix.exs`.
- [x] Decide initial media backend: supervised `ffmpeg` first, Membrane later behind a behaviour.
- [x] Decide MVP control plane: Legion drives admin/orchestration through Tribes plugin management methods.
- [x] Decide local HLS spool root config key: `config :tribe_one_sender, TribeOne.TribesPlugin.Sender.HLS, spool_root: ...`.
- [x] Document required runtime binaries in deployment packaging: at least `ffmpeg`.
## Phase 1: Ash Domain and Synced Schema
- [x] Add `TribeOne.TribesPlugin.Sender.Streaming` Ash domain.
- [x] Register the domain through the plugin spec `ash_domains`.
- [x] Add migrations for plugin tables.
- [x] Add `Stream` resource with AshNostrSync.
- [x] Add `StreamKey` resource with only hashed/verifier key material.
- [x] Add `StreamGeneration` resource with AshNostrSync.
- [x] Add `MediaEndpoint` resource with AshNostrSync.
- [x] Model endpoint parent links for HLS distribution instead of a separate route graph.
- [x] Add `Rendition` resource with AshNostrSync.
- [x] Add `EndpointSnapshot` resource with AshNostrSync.
- [x] Add a bounded `EndpointHistory` resource or defer it behind a JSON ring buffer.
- [x] Add code interfaces for common actions instead of calling `Ash.*` directly from web modules.
- [x] Add tests for resource creation, sync actions, and soft-delete behavior.
## Phase 2: Single-Node RTMP to HLS MVP
- [x] Add `TribeOne.TribesPlugin.Sender.MediaBackend` behaviour.
- [x] Implement `TribeOne.TribesPlugin.Sender.MediaBackend.FFmpeg`.
- [x] Add role-aware `TribeOne.TribesPlugin.Sender.MediaSession` runtime owner for `origin_ingest`.
- [x] Run FFmpeg through `MuonTrap` instead of bare Erlang ports.
- [x] Supervise ingest pipeline processes.
- [x] Generate a stream key and validate RTMP ingest attempts.
- [x] Declare Sender plugin management methods for Legion:
`capabilities`, `stream.*`, `stream_key.create`,
`media_endpoints.upsert`, `renditions.upsert`,
and `endpoint_snapshots.report`.
- [x] Add management handlers for default stream get/create/update.
- [x] Add management handler for one-time stream key creation, marked sensitive.
- [x] Add management handlers for endpoint, route, and rendition upserts.
- [x] Add `stream.start` management handler with initial `origin_ingest` mode.
- [x] Add `stream.stop` and `stream.status` management handlers.
- [x] Start a `StreamGeneration` when Legion starts a stream.
- [x] Write HLS output to `spool_root/streams/:stream_id/:generation_id`.
- [x] Create initial `Rendition` rows from configured output variants.
- [x] Keep a started generation active across source disconnects/backend exits until admin stop.
- [x] Mark generation `live` once the first playable manifest exists.
- [x] Mark generation `ended` on explicit admin stop.
- [x] Mark generation `failed` when startup cannot create an initial backend session.
- [x] Prune live edge spools and clean stopped generation spools according to retention config.
- [x] Add tests around backend command construction and lifecycle state changes.
## Phase 3: HLS Serving and Playback API
- [x] Add plugin API route for playback metadata.
- [x] Add plugin API route or plug for HLS playlist/segment serving.
- [ ] Enforce stream visibility before returning playback data.
- [x] Add cache headers suitable for live HLS.
- [x] Avoid caching future-segment 404 responses.
- [x] Return generation-scoped URLs only.
- [x] Add basic player LiveView page.
- [x] Replace placeholder JS with a player bootstrap.
- [x] Use TypeScript for the player bootstrap.
- [x] Add Video.js v10 beta to the assets pipeline.
- [x] Render playback with Video.js v10 HTML/custom-elements player.
- [x] Report basic player errors and startup metrics to a plugin API endpoint.
- [x] Add page/API tests for playback authorization and not-found behavior.
## Phase 4: Local Stats and Snapshots
- [x] Track local active viewers by endpoint/generation.
- [x] Track ingress/egress bitrate estimates.
- [x] Track playlist age and last segment timestamp.
- [x] Publish `EndpointSnapshot` rows from the local node only.
- [x] Treat stale local stats as degraded before publishing.
- [x] Add local telemetry events for ingest, segment generation, playback, and errors.
- [x] Add a periodic snapshot worker.
- [x] Add tests for snapshot staleness and ownership rules.
- [x] Align monitoring plan with Tribes' host metrics subsystem: `/metrics`, node-local VictoriaMetrics, synced rollups, and plugin metric declarations.
- [x] Declare initial Sender plugin `viewer_count` metric and map it into host-exported plugin metrics.
- [ ] Add compact rollups for ingress/egress bitrate, playlist age, and segment lag when those local samples are mature enough.
## Phase 5: Cluster-Aware HLS Distribution
- [x] Accept Legion-authored endpoint source links through management methods.
- [x] Fill edge-node local HLS spools from each endpoint's configured source endpoint.
- [ ] Serve HLS from `/sender/hls/` through Vinyl.
- [x] Keep viewer playback on the current node that served the player/API.
- [ ] Add configurable health thresholds.
- [ ] Add tests for endpoint source-link behavior under healthy, degraded, stale, and overloaded endpoints.
- [ ] Make every Tribes node able to answer playback metadata for any synced live stream.
## Phase 6: Pull-Through HLS Edge Mode
- [x] Add endpoint type `tribes_edge`/`external_edge`.
- [x] Implement pull-through fetch from an upstream HLS origin.
- [x] Cache finalized segments locally.
- [x] Keep live playlist caching conservative.
- [ ] Add upstream failover based on endpoint source links.
- [x] Emit cache headers compatible with Vinyl.
- [x] Verify regular HLS origin/edge behavior before enabling LL-HLS edge behavior.
- [ ] Add tests for cache hit, miss, upstream failure, and stale manifest handling.
## Phase 7: External Mux and Fanout Nodes
- [x] Model external mux nodes as `MediaEndpoint(type: :external_origin)`.
- [x] Model external HLS repeaters as `MediaEndpoint(type: :external_edge)`.
- [ ] Accept Legion-reported external endpoint snapshots through management API.
- [ ] Document Legion-owned lifecycle for external media processes.
- [ ] Add signed/token-authenticated stats ingestion API.
- [ ] Add optional polling for external HLS origin health.
- [ ] Validate external endpoint payloads before writing synced snapshots.
- [ ] Support multiple renditions produced by an external mux.
- [ ] Support endpoint source links where external mux fans out to Tribes nodes and external edge nodes.
- [ ] Add tests for external stats auth and endpoint source-link selection.
## Phase 8: LL-HLS
- [ ] Switch or add ffmpeg output mode for CMAF/fMP4 segments.
- [ ] Add LL-HLS playlist settings and target part duration.
- [ ] Handle partial segment serving.
- [ ] Review preload hint and blocking reload behavior.
- [ ] Tighten cache headers for parts and playlists.
- [ ] Add player low-latency config.
- [ ] Add metrics for live edge distance and rebuffering.
- [ ] Test Safari native LL-HLS behavior separately from Video.js' HLS engine path.
## Phase 9: Membrane Evaluation
- [ ] Identify Membrane packages needed for RTMP ingest, HLS output, and optional transcoding.
- [ ] Build a backend prototype behind `TribeOne.TribesPlugin.Sender.MediaBackend`.
- [ ] Compare operational behavior against ffmpeg: startup, failure handling, CPU, memory, latency.
- [ ] Decide whether Membrane becomes primary, optional, or deferred.
- [ ] Keep ffmpeg backend available unless Membrane fully covers production needs.
## Phase 10: Packaging and Operations
- [ ] Add runtime config for ports, spool root, retention, backend, and route thresholds.
- [x] Add Nix deployment packaging for `ffmpeg`.
- [x] Add Nix packaging for Sender as a packaged Tribes plugin.
- [x] Add single-image Docker E2E packaging for a two-node origin/edge scenario.
- [ ] Add spool directory creation and permission checks on startup.
- [ ] Add health checks for required binaries and writable spool.
- [ ] Add optional standalone Sender admin UI for stream setup, endpoint status, and current live sessions.
- [ ] Add runbook docs for OBS configuration.
- [ ] Add runbook docs for Legion-driven single-node deployment.
- [ ] Add runbook docs for multi-node HLS edge deployment.
- [ ] Add runbook docs for external mux/fanout deployment.
## External Dependencies
Required for the first useful MVP:
- [x] `ffmpeg` runtime binary in Nix/Docker packaging.
- [x] Video.js v10 beta HTML player package, `@videojs/html`.
- [ ] Writable local spool directory.
- [ ] Legion client support for Sender plugin management methods.
Already available through the Tribes host or current plugin setup:
- [x] Phoenix/Plug routing for plugin pages and API routes.
- [x] Tribes plugin management methods over `/api/admin/management`.
- [x] Ash and AshPostgres for persisted resources.
- [x] AshNostrSync for cluster-replicated plugin state.
- [x] Telemetry primitives.
- [x] Tribes metrics subsystem: `/metrics`, VictoriaMetrics client, rollup worker, synced rollups, admin API, and plugin metrics contract.
Optional or future:
- [ ] Membrane packages for BEAM-native media routing.
- [x] `MuonTrap` or similar for stricter external process supervision.
- [ ] Vinyl in deployment for HLS caching.
- [x] Declare Vinyl authoritative viewer and playlist rollups for proxied/cached playback.
- [ ] External mux/transcode service for multi-bitrate production.