Files
documentation/concepts/providers/index.html

293 lines
14 KiB
HTML
Raw 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.
<!doctype html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Providers — Vyla</title>
<meta name="description" content="How Vyla SDK sources are configured, selected, and verified." />
<meta name="keywords"
content="providers, source configuration, stream sources, provider verification, SDK providers, source selection" />
<link rel="canonical" href="https://vyla.cc/concepts/providers.html" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://vyla.cc/concepts/providers.html" />
<meta property="og:title" content="Providers — Vyla" />
<meta property="og:description" content="How Vyla SDK sources are configured, selected, and verified." />
<meta property="og:image" content="https://vyla.cc/assets/images/thumbnail.png" />
<meta property="og:site_name" content="Vyla" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://vyla.cc/concepts/providers.html" />
<meta property="twitter:title" content="Providers — Vyla" />
<meta property="twitter:description" content="How Vyla SDK sources are configured, selected, and verified." />
<meta property="twitter:image" content="https://vyla.cc/assets/images/thumbnail.png" />
<meta property="twitter:site" content="@vylaentertainment" />
<!-- Additional SEO -->
<meta name="robots" content="index, follow" />
<meta name="author" content="Vyla" />
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="/assets/base.css" />
<link rel="stylesheet" href="/assets/highlight.css" />
<link rel="stylesheet" href="/assets/mintlify-overrides.css" />
<!-- JSON-LD Structured Data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Providers",
"description": "How Vyla SDK sources are configured, selected, and verified.",
"url": "https://vyla.cc/concepts/providers.html",
"applicationCategory": "MultimediaApplication",
"operatingSystem": "Windows, macOS, Linux, Android, Android TV",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
}
}
</script>
</head>
<body>
<div id="banner">
<span>Vyla is self-hosted. Run Vyla Home, embed the SDK, or deploy Stream API on infrastructure you control. Rights
holders can request source removal — <a href="/misc/dmca">DMCA policy</a>.</span>
<button id="banner-close" onclick="dismissBanner()" aria-label="Dismiss">✕</button>
</div>
<header id="navbar">
<div class="nav-top">
<a class="brand" href="/"><img src="/assets/images/logo.png" alt="Vyla" id="brand-logo" loading="lazy"
fetchpriority="low"></a>
<button id="search-trigger" type="button" onclick="openSearch()" aria-label="Search"></button>
<div class="links">
<button id="theme-toggle" type="button" onclick="toggleThemeMenu(event)" aria-label="Theme"></button>
</div>
</div>
<nav class="tabs">
<a class="tab-link" href="/">Vyla</a>
<a class="tab-link" href="/sdk">SDK</a>
<a class="tab-link active" href="/stream-api/overview">Stream API</a>
<a class="tab-link" href="/guides/integrations">Resources</a>
<a class="tab-link" href="/misc/credit">Misc</a>
</nav>
</header>
<div id="layout">
<nav id="sidebar">
<div class="group">
<p class="group-title">Start here</p>
<ul>
<li><a class="active" href="/">Introduction</a></li>
</li>
<li><a class="" href="/architecture">Architecture</a></li>
</ul>
</div>
<div class="group">
<p class="group-title">Products</p>
<ul>
<li><a class="" href="/home">Home</a></li>
<li><a class="" href="/go">Go</a></li>
<li><a class="" href="/tv">Tv</a></li>
<li><a class="" href="/player">Player</a></li>
</ul>
</div>
<div class="group">
<p class="group-title">Concepts</p>
<ul>
<li><a class="active" href="/concepts/providers">Providers</a></li>
</ul>
</div>
</nav>
<div id="content-col">
<main class="prose">
<h1>Providers</h1>
<p class="page-description">How Vyla SDK sources are configured, selected, and verified.</p>
<p>Vyla SDK aggregates multiple independent providers. Each has different internal mechanisms, reliability
profiles, and timeout characteristics. This page explains the source layer that powers both direct SDK use and
the optional Stream API.</p>
<div class="callout callout-note">
<div class="callout-content">
<p>Provider availability and performance can vary based on your network environment. When self-hosting,
providers may work differently than on residential connections due to IP-based blocking from upstream
sources.</p>
</div>
</div>
<hr>
<h2 id="how-providers-are-used">How Providers Are Used</h2>
<p>When your app calls <code>getStream()</code>—directly or through Stream API:</p>
<ol>
<li>All active (non-disabled) providers are queried <strong>simultaneously</strong> with per-source random
jitter to stagger upstream requests</li>
<li>Each provider has its own <strong>timeout</strong>, <strong>retry count</strong>, and <strong>backoff
delay</strong></li>
<li>Every returned URL is <strong>verified</strong> — first via a HEAD request to the raw upstream URL, then
via a proxied HLS playability check</li>
<li>Only URLs that pass both verification steps appear in the response as <code>source</code> events</li>
</ol>
<p>Because the endpoint is SSE, <strong>verified sources are emitted immediately as each provider
resolves</strong> — your player receives them progressively. The stream closes once every provider has
either resolved or timed out.</p>
<div class="callout callout-tip">
<div class="callout-content">
<p>Call <code>sdk.getSources(true)</code> to inspect enabled providers and
<code>sdk.probeAllSources()</code> for a live availability signal. If you use Stream API, its <a
href="/stream-api/operations"><code>/health</code></a> endpoint exposes probes over HTTP.
</p>
</div>
</div>
<hr>
<h2 id="provider-configuration">Provider Configuration</h2>
<p>Each provider is defined with the following properties:</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>key</code></td>
<td>Internal identifier used in API responses and the <code>source</code> field</td>
</tr>
<tr>
<td><code>label</code></td>
<td>Human-readable name shown in the <code>label</code> field</td>
</tr>
<tr>
<td><code>proxyParam</code></td>
<td>Short query parameter used to route proxied requests</td>
</tr>
<tr>
<td><code>timeout</code></td>
<td>Maximum time (ms) to wait for a stream URL</td>
</tr>
<tr>
<td><code>sourcesTimeout</code></td>
<td>Optional secondary timeout (ms) for an internal source-listing step, used by some providers</td>
</tr>
<tr>
<td><code>jitter</code></td>
<td>Max random delay (ms) before the request fires, to stagger upstream hits</td>
</tr>
<tr>
<td><code>retries</code></td>
<td>Number of retry attempts on failure</td>
</tr>
<tr>
<td><code>skipProxy</code></td>
<td>If <code>true</code>, stream URLs are returned as-is without proxy wrapping</td>
</tr>
<tr>
<td><code>disabled</code></td>
<td>If <code>true</code>, the provider is excluded from all requests</td>
</tr>
</tbody>
</table>
<p>Providers with <code>disabled: true</code> are completely skipped — they won't appear in health checks or
fanout responses.</p>
<hr>
<h2 id="response-time">Response Time</h2>
<p>The first <code>source</code> event typically arrives within <strong>3–8 seconds</strong>. Subsequent sources
stream in as each provider resolves. The stream closes once the <strong>slowest configured provider</strong>
times out — in the worst case this can be 60+ seconds (e.g. <code>cinezo</code> has a 60 s timeout), though
most sources emit well before then.</p>
<p><strong>Best practice:</strong> always show a loading state, begin playback on the first <code>source</code>
event, and implement a client-side timeout for the overall stream. See the <a
href="/guides/error-handling">Error Handling</a> guide.</p>
<hr>
<h2 id="caching">Caching</h2>
<p>Results are cached in-memory with a <strong>5-minute TTL</strong>. The per-source stream cache is keyed by
<code>source_key + tmdb_id + season + episode</code>; the aggregate source-results cache is keyed by
<code>tmdb_id + season + episode + base</code>. Cache hits skip the provider fetch entirely and return
near-instantly.
</p>
<pre><code>CACHE_TTL = 5 minutes
</code></pre>
<p>The cache resets on server restart. Cache size is reported in the <code>/api/health</code> response under the
<code>cache</code> field.
</p>
<hr>
<h2 id="the-hls-proxy">The HLS Proxy</h2>
<p>All provider stream URLs are wrapped in the server proxy (unless <code>skipProxy: true</code>):</p>
<pre><code>http://localhost:7860/api?url=&#x3C;encoded_stream_url>&#x26;&#x3C;proxyParam>=1
</code></pre>
<p>When your player fetches this path from your self-hosted instance, the server:</p>
<ol>
<li>Fetches the upstream M3U8 with the correct <code>Referer</code>, <code>Origin</code>, and any
provider-specific headers</li>
<li>Rewrites all segment URLs and encryption key URIs in the playlist to route through the same proxy</li>
<li>Returns the rewritten playlist with <code>Access-Control-Allow-Origin: *</code></li>
</ol>
<p>This means <strong>your player never talks to the provider directly</strong> — all HLS traffic flows through
the proxy, keeping CORS and rate-limiting issues fully contained.</p>
<hr>
<h2 id="stream-verification">Stream Verification</h2>
<p>Before a URL is emitted as a <code>source</code> event, it passes two verification steps:</p>
<ol>
<li><strong><code>verifyStream</code></strong> — a HEAD request to the raw upstream URL (skipped for
<code>SKIP_VERIFY</code> sources). Must return HTTP <code>&#x3C; 400</code>.
</li>
<li><strong><code>verifyPlayable</code></strong> — fetches the proxied URL, validates <code>#EXTM3U</code>,
checks for <code>#EXTINF</code> or <code>#EXT-X-STREAM-INF</code>, then fetches the first segment with a
range request.</li>
</ol>
<p>Sources that fail either step — HTTP errors, timeouts, non-HLS/non-MP4 content — are silently dropped. MP4
sources skip the <code>#EXTM3U</code> check and are verified via HEAD + content-type inspection instead. HTTP
429 responses and timeout/abort errors are treated as <strong>passing</strong> (stream exists but is
rate-limited).</p>
<div class="callout callout-note">
<div class="callout-content">
<p><code>/test</code> runs the same two-step verification pipeline as <code>/movie</code> and
<code>/tv</code>. Check the <code>ok</code> field in the response body — HTTP status is always
<code>200</code> regardless of result.
</p>
</div>
</div>
<hr>
<h2 id="disabled-providers">Disabled Providers</h2>
<p>Providers marked <code>disabled: true</code> in config are completely excluded from:</p>
<ul>
<li><code>/api/movie</code> and <code>/api/tv</code> fanout</li>
<li><code>/api/health</code> probes</li>
<li><code>GET /api?sources_meta</code> listings</li>
</ul>
<p>If a provider you expect to see is missing from responses, check whether it's been disabled.</p>
<hr>
<h2 id="multi-url-sources">Multi-URL Sources</h2>
<p>Some providers return multiple candidate stream URLs (via <code>allUrls</code>). For these, verification runs
through each candidate in order and returns the first one that passes. If none pass, the source is dropped.
</p>
<p>For providers with <code>SKIP_VERIFY</code>, all candidate URLs are returned as separate source events
without verification. These are not distinguished by numbered labels in the response.</p>
</main>
<aside id="toc">
<p class="toc-title">On this page</p>
<ul>
<li><a href="#how-providers-are-used">How Providers Are Used</a></li>
<li><a href="#provider-configuration">Provider Configuration</a></li>
<li><a href="#response-time">Response Time</a></li>
<li><a href="#caching">Caching</a></li>
<li><a href="#the-hls-proxy">The HLS Proxy</a></li>
<li><a href="#stream-verification">Stream Verification</a></li>
<li><a href="#disabled-providers">Disabled Providers</a></li>
<li><a href="#multi-url-sources">Multi-URL Sources</a></li>
</ul>
</aside>
</div>
</div>
<footer id="site-footer">
<a href="https://discord.gg/5eqRhKeywG" target="_blank" rel="noopener">Discord</a>
<a href="https://gitlab.com/vyla-entertainment/" target="_blank" rel="noopener">GitLab</a>
</footer>
<script src="/assets/app.js"></script>
</body>
</html>