215 lines
17 KiB
Markdown
215 lines
17 KiB
Markdown
# Feature Research
|
|
|
|
**Domain:** Live Stream Aggregation / Sports Stream Proxy Service
|
|
**Researched:** 2026-02-23
|
|
**Confidence:** MEDIUM
|
|
|
|
---
|
|
|
|
## Feature Landscape
|
|
|
|
### Table Stakes (Users Expect These)
|
|
|
|
Features users assume exist. Missing these = product feels incomplete.
|
|
|
|
| Feature | Why Expected | Complexity | Notes |
|
|
|---------|--------------|------------|-------|
|
|
| Race schedule view | Users need to know when sessions are live without external lookup | LOW | Pull from OpenF1 API (`/sessions` endpoint). Session types: FP1, FP2, FP3, Quali, Sprint, Sprint Quali, Race. Confidence: HIGH (OpenF1 API confirmed). |
|
|
| Live session indicator | Users need to distinguish live vs upcoming vs finished sessions at a glance | LOW | Visual status badge (LIVE / UPCOMING / FINISHED) based on session start time + duration. No polling needed at schedule level. |
|
|
| Stream picker | Multiple stream sources per session — user picks which one to watch | LOW | List available extracted stream links with source label. Core UX of the whole product. |
|
|
| Embedded video player | Users won't navigate to external players for each stream | MEDIUM | HLS.js in Svelte for in-page playback. Must handle m3u8 sources natively. Confidence: HIGH (HLS.js is the standard client-side HLS library). |
|
|
| Stream health indicator | Users don't want to click a dead stream and stare at a spinner | MEDIUM | Backend health-check each extracted URL before displaying. Simple HEAD or short-lived GET on the m3u8 playlist. Mark dead streams visually. |
|
|
| CORS-transparent stream proxy | Browsers block cross-origin HLS requests; streams can't play directly from scraped origins | HIGH | Proxy all m3u8 manifests + .ts/.m4s segments through your own backend. Rewrite manifest URLs to point to your proxy. This is architecturally mandatory, not optional. Confidence: HIGH (HLS-Proxy documentation confirms this). |
|
|
| All F1 session types covered | Users specifically want FP, Quali, Sprint, Race, and pre/post content — not just race day | MEDIUM | Scraper scheduler must run for every session type on the F1 calendar. OpenF1 `/sessions` endpoint returns `session_type` field. |
|
|
| Session countdown timer | For upcoming sessions, users want to know time-until-start without mental math | LOW | Client-side countdown from schedule data already fetched. Zero backend cost. |
|
|
| Stream auto-refresh / re-extraction | Stream links expire (tokens, redirect chains rotate) — stale links silently fail | HIGH | Periodic re-extraction (e.g., every 5-10 min during a live session). Depends on extractor infrastructure. |
|
|
| Multiple quality options (if available) | Users on slow connections need lower bitrate; users on fast connections want max quality | MEDIUM | Expose quality variants from multi-variant HLS playlists if source provides them. Let user pick or default to auto (hls.js handles ABR natively). |
|
|
|
|
---
|
|
|
|
### Differentiators (Competitive Advantage)
|
|
|
|
Features that set the product apart. Not required, but valuable.
|
|
|
|
| Feature | Value Proposition | Complexity | Notes |
|
|
|---------|-------------------|------------|-------|
|
|
| Automatic stream extraction at session start | Zero manual effort — streams appear when the session goes live | HIGH | Cron/scheduler tied to F1 calendar. Triggers extractors N minutes before session start. Eliminates "is there a stream yet?" manual checking. |
|
|
| Per-site extractor isolation | Bypassing CSRF/JS obfuscation cleanly per site without shared code that breaks globally | HIGH | Each extractor is a self-contained module. One site's changes don't break others. Confidence: MEDIUM (pattern from streamlink plugin system). |
|
|
| Session timeline: pre/post shows + press conferences | Competitors (scrapers, IPTV playlists) cover race only; full weekend coverage is rare | MEDIUM | Requires scheduling extractors for non-race events. OpenF1 does not cover pre/post shows — need site-specific session detection. |
|
|
| Stream source labeling | Shows which site/feed each stream came from — users learn which sources are reliable | LOW | Store source metadata with each extracted URL. Display in picker. |
|
|
| Fallback stream ordering | Automatically surfaces known-good streams first when multiple sources exist | MEDIUM | Health-check result + historical success rate drives ordering. Depends on: stream health checking + a minimal persistence layer to store success history. |
|
|
| Proxy-cached segment prefetch | Reduces buffering by prefetching upcoming .ts segments into local cache | HIGH | Node-HLS-Proxy pattern: maintain per-stream segment cache up to N segments ahead. High implementation cost for marginal UX gain at private scale. |
|
|
| Session notes / source reputation | Lightweight annotations (e.g., "this source often drops at lap 40") | LOW | Simple static config or admin-editable markdown. No database needed at MVP. |
|
|
| Race weekend overview page | One page showing all sessions for a Grand Prix weekend — not just next session | LOW | Group sessions by event/round from schedule API. Pure frontend feature once schedule data is available. |
|
|
|
|
---
|
|
|
|
### Anti-Features (Commonly Requested, Often Problematic)
|
|
|
|
Features to explicitly NOT build.
|
|
|
|
| Feature | Why Requested | Why Problematic | Alternative |
|
|
|---------|---------------|-----------------|-------------|
|
|
| DVR / stream recording | Users want to rewatch if they miss something | Massive storage cost, legal exposure, complexity (recording live HLS streams, serving VOD). Out of scope by design. | Live viewing only. Accept the constraint. |
|
|
| Chat / comments | Social viewing experience | Scope creep. You're building a stream aggregator, not a community platform. Auth, moderation, and DB schema all follow. | None — explicitly out of scope. |
|
|
| User accounts / watchlists | "Remember my preferred stream source" | Requires auth layer, session storage, DB. Contradicts the "no auth, private URL" design decision. | Persist last-used quality/source in browser localStorage. Zero backend cost. |
|
|
| Stream transcoding / re-encoding | Normalize quality across sources | Enormous CPU cost, latency, and complexity. An FFmpeg transcoding pipeline per stream is overkill for a private service. | Pass-through proxy only. Let hls.js handle ABR on the client. |
|
|
| Headless browser extraction | Universal extractor that handles any site's JS obfuscation | Puppeteer/Playwright adds 200-400 MB RAM per session, slow cold starts, flaky in containers, and complex cluster scheduling. Per-site custom extractors are faster and more reliable. | Custom per-site extractors (Go/Python HTTP + regex/DOM parser). |
|
|
| Mobile app | Access on phone | Web app with responsive Svelte layout is sufficient. Native app is weeks of work for a private tool. | Responsive web design. PWA if needed. |
|
|
| Discovery / search for new stream sites | Auto-find new sources | Scraping discovery is an unsolved problem and a rabbit hole. You have a fixed list of sites. | User-provided site list. Extractor per site. |
|
|
| Telemetry overlay / timing data | F1 fans love live timing alongside streams | Different product category (timing dashboard vs stream aggregator). OpenF1 has timing data but integrating it is a separate project. | Link to existing timing tools (e.g., openf1.org). |
|
|
| DRM stream support | Some quality sources use Widevine/FairPlay | DRM circumvention is legally distinct from re-streaming. Avoid. | Non-DRM HLS sources only. |
|
|
|
|
---
|
|
|
|
## Feature Dependencies
|
|
|
|
```
|
|
Race Schedule View
|
|
└──requires──> F1 Schedule API Integration (OpenF1 or Ergast)
|
|
└──enables──> Session Countdown Timer
|
|
└──enables──> Automatic Extraction Trigger
|
|
|
|
Stream Picker
|
|
└──requires──> CORS-Transparent Stream Proxy (browser cannot directly fetch cross-origin m3u8)
|
|
└──requires──> Stream Health Indicator (to filter dead streams before display)
|
|
└──requires──> Stream Health Checker (backend periodic HEAD/GET)
|
|
|
|
Embedded Video Player
|
|
└──requires──> CORS-Transparent Stream Proxy (proxied URLs served from same origin)
|
|
└──requires──> Stream Picker (to know which URL to play)
|
|
|
|
Stream Auto-Refresh
|
|
└──requires──> Per-Site Extractor (to re-run extraction)
|
|
└──requires──> Session-live detection (know when to run vs stop)
|
|
|
|
Fallback Stream Ordering
|
|
└──requires──> Stream Health Indicator
|
|
└──enhances──> Stream Picker (surfaces best streams first)
|
|
|
|
Multiple Quality Options
|
|
└──requires──> CORS-Transparent Stream Proxy (proxy must rewrite variant playlist URLs too)
|
|
└──enhances──> Embedded Video Player (user control or ABR)
|
|
|
|
Proxy-Cached Segment Prefetch
|
|
└──requires──> CORS-Transparent Stream Proxy (must be same proxy layer)
|
|
└──conflicts──> Minimal resource footprint (high memory cost)
|
|
|
|
Session Timeline (pre/post/press conf)
|
|
└──requires──> F1 Schedule API Integration (for race events)
|
|
└──requires──> Per-Site Session Detection (API doesn't include pre/post show timing)
|
|
```
|
|
|
|
### Dependency Notes
|
|
|
|
- **Stream Picker requires CORS proxy:** Browsers enforce same-origin policy. A scraped m3u8 URL from `site.com` cannot be fetched by a Svelte app on `f1.viktorbarzin.me`. Every user-facing stream URL must route through the proxy backend. This is a hard architectural dependency, not an option.
|
|
- **Stream health checker enables stream picker quality:** Without health checking, the picker shows dead links. Health checking must run before streams are displayed and periodically during live sessions.
|
|
- **Automatic extraction trigger depends on schedule:** The scheduler must know when sessions start. Schedule API integration is therefore the first thing to build — everything else gates on it.
|
|
- **Multiple quality options conflict with simple proxy:** If the source provides a multi-variant HLS playlist, the proxy must rewrite ALL variant URLs (not just the master manifest). Adds complexity to the proxy rewriting layer.
|
|
- **Fallback ordering conflicts with stateless proxy:** Tracking success history requires at least a lightweight persistence layer (e.g., Redis or SQLite). If staying fully stateless, fall back to health-check-only ordering.
|
|
|
|
---
|
|
|
|
## MVP Definition
|
|
|
|
### Launch With (v1)
|
|
|
|
Minimum viable product — what's needed to validate the concept.
|
|
|
|
- [ ] **F1 Schedule view** — Show upcoming/live sessions for the current season. Single page, no navigation needed.
|
|
- [ ] **CORS-transparent HLS proxy** — Proxy m3u8 manifests + segment URLs through the backend. Without this, nothing plays in the browser.
|
|
- [ ] **Per-site stream extractor(s)** — At least one working extractor for at least one reliable source site. Proves the extraction pipeline end-to-end.
|
|
- [ ] **Stream health checker** — Validate extracted URLs before showing. Dead streams must not surface to users.
|
|
- [ ] **Stream picker** — List available working streams for the current session. User clicks, player loads.
|
|
- [ ] **Embedded HLS player** — HLS.js in Svelte. Plays proxied m3u8 URL in-page.
|
|
- [ ] **Session countdown** — Time-until-start for upcoming sessions. Pure frontend, zero cost.
|
|
- [ ] **Live session indicator** — Visual LIVE/UPCOMING/FINISHED badge. Core navigational signal.
|
|
|
|
### Add After Validation (v1.x)
|
|
|
|
Features to add once core pipeline is working and streams actually play reliably.
|
|
|
|
- [ ] **Stream auto-refresh** — Re-run extractors every 5-10 min during live sessions. Trigger: user reports dead stream or health check fails on previously-valid URL.
|
|
- [ ] **Fallback stream ordering** — Sort by health-check recency and past reliability. Trigger: multiple sources available per session.
|
|
- [ ] **Source labeling in picker** — Show site name with each stream link. Low effort, high trust signal for users.
|
|
- [ ] **Race weekend overview** — All sessions grouped per Grand Prix. Trigger: users navigating between sessions in a weekend.
|
|
- [ ] **Additional extractors** — Expand site coverage once first extractor is stable. Each adds incremental reliability.
|
|
|
|
### Future Consideration (v2+)
|
|
|
|
Features to defer until product-market fit is established.
|
|
|
|
- [ ] **Pre/post show + press conference coverage** — Complex site-specific session detection. Defer until core race coverage is solid.
|
|
- [ ] **Multiple quality options** — Source sites may or may not provide multi-variant playlists. Complexity of rewriting variant URLs in proxy is non-trivial. Validate first if sources actually offer quality tiers.
|
|
- [ ] **Proxy segment prefetch/cache** — High memory cost. Only valuable if buffering is a real user complaint at private scale.
|
|
- [ ] **Session reputation annotations** — Nice UX polish. Not needed at launch.
|
|
|
|
---
|
|
|
|
## Feature Prioritization Matrix
|
|
|
|
| Feature | User Value | Implementation Cost | Priority |
|
|
|---------|------------|---------------------|----------|
|
|
| F1 Schedule view | HIGH | LOW | P1 |
|
|
| CORS-transparent HLS proxy | HIGH | HIGH | P1 (architectural blocker) |
|
|
| Per-site stream extractor | HIGH | HIGH | P1 (core value) |
|
|
| Embedded HLS player | HIGH | LOW | P1 |
|
|
| Stream health checker | HIGH | MEDIUM | P1 |
|
|
| Stream picker | HIGH | LOW | P1 |
|
|
| Session countdown timer | MEDIUM | LOW | P1 |
|
|
| Live session indicator | HIGH | LOW | P1 |
|
|
| Stream auto-refresh | HIGH | MEDIUM | P2 |
|
|
| Source labeling | MEDIUM | LOW | P2 |
|
|
| Fallback stream ordering | MEDIUM | MEDIUM | P2 |
|
|
| Race weekend overview page | MEDIUM | LOW | P2 |
|
|
| Additional extractors | HIGH | MEDIUM | P2 |
|
|
| Multiple quality options | MEDIUM | HIGH | P3 |
|
|
| Pre/post show coverage | MEDIUM | HIGH | P3 |
|
|
| Proxy segment prefetch | LOW | HIGH | P3 |
|
|
| Session reputation annotations | LOW | LOW | P3 |
|
|
|
|
**Priority key:**
|
|
- P1: Must have for launch
|
|
- P2: Should have, add when possible
|
|
- P3: Nice to have, future consideration
|
|
|
|
---
|
|
|
|
## Competitor Feature Analysis
|
|
|
|
Reference products surveyed: RaceControl (unofficial F1TV client), f1viewer (TUI F1TV client), streamlink (stream extraction CLI), HLS-Proxy (node HLS proxy), Threadfin (M3U proxy), ErsatzTV (self-hosted IPTV).
|
|
|
|
| Feature | RaceControl (F1TV client) | Streamlink (CLI extractor) | HLS-Proxy (node) | Our Approach |
|
|
|---------|--------------------------|---------------------------|-----------------|--------------|
|
|
| Session schedule | F1TV API (official, auth required) | None (site-specific) | None | OpenF1/Ergast (free, unauthenticated) |
|
|
| Stream extraction | Official F1TV API | Plugin-per-site Python | N/A | Custom per-site extractors (Go/Python HTTP) |
|
|
| Stream quality selection | Multi-variant picker + Chromecast | CLI flag `--default-stream` | Pass-through | HLS.js ABR + manual picker |
|
|
| Multi-stream view | Yes (layout builder, experimental sync) | Multiple instances | N/A | Single stream (MVP), multi optional later |
|
|
| Health checking | None visible | None | None | Active periodic health checks (our differentiator) |
|
|
| Stream proxy | No (plays direct from F1TV CDN) | No (piped to local player) | Yes (manifest + segment rewrite) | Yes (mandatory for browser CORS) |
|
|
| CORS handling | N/A (desktop app) | N/A (local) | Yes (adds permissive CORS headers) | Yes (same-origin proxy) |
|
|
| Auto-extraction at session start | Via F1TV live schedule | None | None | Yes (scheduler + extractor trigger) |
|
|
| Embedded browser player | No (external VLC/mpv) | No (external player) | N/A | Yes (HLS.js in Svelte) |
|
|
| No auth required | No (F1TV subscription) | Varies by source | None | Yes (private URL, no auth layer) |
|
|
|
|
**Key insight:** Existing tools either require official F1TV credentials (RaceControl, f1viewer) or extract streams to local players (streamlink). None combine automated extraction from unofficial sources + browser-native proxied playback + schedule integration in a single web service. That combination is the product's core novelty.
|
|
|
|
---
|
|
|
|
## Sources
|
|
|
|
- OpenF1 API documentation: https://openf1.org/ — MEDIUM confidence (marketing page, limited technical detail on session endpoints)
|
|
- HLS-Proxy (warren-bank/HLS-Proxy) README — HIGH confidence for proxy architecture requirements (CORS, manifest rewriting, segment caching)
|
|
- HLS.js README (video-dev/hls.js) — HIGH confidence for client-side HLS capabilities (ABR modes, quality switching, error recovery)
|
|
- Streamlink documentation: https://streamlink.github.io/ — HIGH confidence for extraction patterns and plugin architecture
|
|
- yt-dlp README — HIGH confidence for extractor-per-site pattern and format selection
|
|
- RaceControl (robvdpol/RaceControl) README — MEDIUM confidence for F1 streaming UX expectations
|
|
- f1viewer (SoMuchForSubtlety/f1viewer) README — MEDIUM confidence for F1 session coverage expectations
|
|
- Threadfin README — MEDIUM confidence for IPTV/HLS proxy feature patterns
|
|
- Telly README — LOW confidence (Plex-specific, limited relevance)
|
|
- Eyevinn/hls-proxy README — HIGH confidence for HLS manifest manipulation patterns
|
|
|
|
---
|
|
|
|
*Feature research for: F1 Live Stream Aggregation Service*
|
|
*Researched: 2026-02-23*
|