mirror of
https://gitlab.com/vyla-entertainment/documentation.git
synced 2026-11-13 05:57:22 -05:00
293 lines
14 KiB
HTML
293 lines
14 KiB
HTML
<!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=<encoded_stream_url>&<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>< 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> |