huge doc rewrite

This commit is contained in:
2026-10-07 20:03:38 -07:00
parent d6ec1f93b8
commit c28308c389
47 changed files with 3185 additions and 6304 deletions

View File

@@ -1,588 +0,0 @@
<!doctype html>
<html lang="en" class="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SDK Reference — Vyla</title>
<meta name="description"
content="Scrape video streams, fetch subtitles, retrieve download links, and monitor provider health directly from your Node.js application." />
<meta name="keywords"
content="Vyla SDK, Node.js SDK, TypeScript SDK, video streaming, subtitle API, download API, health monitoring, server-side streaming" />
<link rel="canonical" href="https://vyla.cc/sdk.html" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://vyla.cc/sdk.html" />
<meta property="og:title" content="SDK Reference — Vyla" />
<meta property="og:description"
content="Scrape video streams, fetch subtitles, retrieve download links, and monitor provider health directly from your Node.js application." />
<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/sdk.html" />
<meta property="twitter:title" content="SDK Reference — Vyla" />
<meta property="twitter:description"
content="Scrape video streams, fetch subtitles, retrieve download links, and monitor provider health directly from your Node.js application." />
<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": "Vyla SDK",
"description": "Scrape video streams, fetch subtitles, retrieve download links, and monitor provider health directly from your Node.js application.",
"url": "https://vyla.cc/sdk.html",
"applicationCategory": "DeveloperApplication",
"operatingSystem": "Node.js",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
}
}
</script>
<script>
(function () {
var saved = localStorage.getItem('vyla-theme');
var isDark = saved ? saved === 'dark' : true;
document.documentElement.classList.toggle('dark', isDark);
})();
</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"></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">Vyla SDK</p>
<ul>
<li><a class="active" href="/sdk">Sdk</a></li>
<li><a class="" href="/sdk-quickstart">Sdk Quickstart</a></li>
</ul>
</div>
</nav>
<div id="content-col">
<main class="prose">
<h1>SDK Reference</h1>
<p class="page-description">Scrape video streams, fetch subtitles, retrieve download links, and monitor provider
health directly from your Node.js application.</p>
<p>The <strong>Vyla SDK</strong> (<code>@vyla-entertainment/sdk</code>) is a server-side JavaScript/TypeScript
package that provides direct access to Vyla's stream resolvers, health probes, download resolvers, and
subtitle providers.</p>
<p>By embedding the SDK directly into your backend application, provider resolution executes in your own
environment. It is an alternative to operating the Stream API as a separate process: your application owns its
request boundary, caching, authorization, timeouts, and response shape.</p>
<div class="callout callout-note">
<div class="callout-content">
<p>The SDK can be used independently of the self-hosted Stream API. If you prefer to embed Vyla capabilities
in an existing Node.js application rather than run a separate HTTP service, begin with the <a
href="/sdk-quickstart">SDK quickstart</a>.</p>
</div>
</div>
<hr>
<h2 id="features">Features</h2>
<ul>
<li><strong>Direct-to-Client Playback</strong>: Scraped streams link directly to source CDNs. No proxy server
overhead required unless specified by provider headers.</li>
<li><strong>Built-In Health Probing</strong>: Monitor latency and uptime per provider with built-in health
check utilities.</li>
<li><strong>Automated Anime Sub/Dub Routing</strong>: Automatically configures audio track requirements
(<code>sub</code> vs <code>dub</code>) based on provider naming conventions.</li>
<li><strong>Multi-Source Subtitle Aggregation</strong>: Merges subtitle tracks from multiple redundant
subtitle mirrors into a unified VTT/SRT format.</li>
<li><strong>Metadata Fallbacks</strong>: Automatically maps TMDB IDs to external IDs (such as IMDB and
AniList) for smooth stream lookups.</li>
<li><strong>Self-Contained</strong>: No need to deploy a separate API server — all streaming functionality
runs within your existing Node.js application.</li>
</ul>
<hr>
<h2 id="installation">Installation</h2>
<p>Install the package into your Node.js backend using your package manager of choice:</p>
<div class="code-group">
<div class="code-group-tabs"><button class="code-group-tab active" data-tab-index="0" type="button"
onclick="cgSwitch(this)">npm</button><button class="code-group-tab" data-tab-index="1" type="button"
onclick="cgSwitch(this)">pnpm</button><button class="code-group-tab" data-tab-index="2" type="button"
onclick="cgSwitch(this)">yarn</button></div>
<div class="code-group-panels">
<div class="code-group-panel active">
<pre><code class="hljs language-bash">npm <span class="hljs-built_in">install</span> <span class="hljs-string">@vyla-entertainment/sdk</span></code></pre>
</div>
<div class="code-group-panel">
<pre><code class="hljs language-bash">pnpm <span class="hljs-built_in">install</span> <span class="hljs-string">@vyla-entertainment/sdk</span></code></pre>
</div>
<div class="code-group-panel">
<pre><code class="hljs language-bash">yarn <span class="hljs-built_in">add</span> <span class="hljs-string">@vyla-entertainment/sdk</span></code></pre>
</div>
</div>
</div>
<blockquote>
<p><strong>Note</strong>: Node.js <strong>v18+</strong> is required due to modern standard <code>fetch</code>
and <code>AbortSignal.timeout</code> usage.</p>
</blockquote>
<hr>
<h2 id="initialization">Initialization</h2>
<p>Initialize the <code>VylaSDK</code> client by supplying your <strong>TMDB API Key</strong>. The key resolves
media metadata, validates movie/TV show IDs, and translates TMDB IDs into AniList IDs for anime sources.</p>
<p>You may optionally provide a pengu.uk manifest URL to enable the Pengu source.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">import</span> <span class="hljs-title class_">VylaSDK</span> <span class="hljs-keyword">from</span> <span class="hljs-string">"@vyla-entertainment/sdk"</span>;
<span class="hljs-keyword">const</span> sdk = <span class="hljs-keyword">new</span> <span class="hljs-title class_">VylaSDK</span>({
<span class="hljs-attr">tmdbApiKey</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">TMDB_API_KEY</span>,
<span class="hljs-attr">penguManifest</span>: <span class="hljs-string">""</span> <span class="hljs-comment">// Optional, get from pengu.uk</span>
});
</code></pre>
<hr>
<h2 id="core-methods">Core Methods</h2>
<h3 id="getstreamkey-id-s-e-clientip"><code>getStream(key, id, s?, e?, clientIP?)</code></h3>
<p>Scrapes video stream URLs and playability headers for a specified provider key.</p>
<pre><code class="hljs language-javascript"><span class="hljs-comment">// Fetch a movie stream (TMDB ID: 155 - The Dark Knight)</span>
<span class="hljs-keyword">const</span> movieStream = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getStream</span>(<span class="hljs-string">"sourcename"</span>, <span class="hljs-string">"155"</span>);
<span class="hljs-comment">// Fetch a TV show episode (TMDB ID: 1399, Season 1, Episode 1)</span>
<span class="hljs-keyword">const</span> tvStream = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getStream</span>(<span class="hljs-string">"sourcename"</span>, <span class="hljs-string">"1399"</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
<span class="hljs-comment">// Pass client IP for providers that use geo-verification</span>
<span class="hljs-keyword">const</span> geoStream = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getStream</span>(<span class="hljs-string">"sourcename"</span>, <span class="hljs-string">"155"</span>, <span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">"203.0.113.195"</span>);
</code></pre>
<h4 id="parameters">Parameters</h4>
<table>
<thead>
<tr>
<th align="left">Parameter</th>
<th align="left">Type</th>
<th align="left">Required</th>
<th align="left">Default</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>key</code></td>
<td align="left"><code>string</code></td>
<td align="left"><strong>Yes</strong></td>
<td align="left">—</td>
<td align="left">Unique key identifier for the provider (e.g. <code>"sourcename"</code>,
<code>"sourcename"</code>, <code>"sourcename"</code>).
</td>
</tr>
<tr>
<td align="left"><code>id</code></td>
<td align="left"><code>string</code></td>
<td align="left"><strong>Yes</strong></td>
<td align="left">—</td>
<td align="left">TMDB media ID (e.g., <code>"155"</code>).</td>
</tr>
<tr>
<td align="left"><code>s</code></td>
<td align="left"><code>string | number</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>null</code></td>
<td align="left">Season number (required for TV shows).</td>
</tr>
<tr>
<td align="left"><code>e</code></td>
<td align="left"><code>string | number</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>null</code></td>
<td align="left">Episode number (required for TV shows).</td>
</tr>
<tr>
<td align="left"><code>clientIP</code></td>
<td align="left"><code>string</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>null</code></td>
<td align="left">End-user IP address forwarded for geo-restricted scrapers.</td>
</tr>
</tbody>
</table>
<h4 id="example-response-format">Example Response Format</h4>
<pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>
<span class="hljs-attr">"url"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example-cdn.com/hls/manifest.m3u8"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"quality"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"auto"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"isM3U8"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"headers"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span>
<span class="hljs-attr">"Referer"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example.com/"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"Origin"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example.com"</span>
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"allUrls"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
<span class="hljs-punctuation">{</span>
<span class="hljs-attr">"url"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://example-cdn.com/hls/manifest.m3u8"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"quality"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"1080p"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"isM3U8"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span>
<span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<hr>
<h3 id="getsubtitlesid-s-e"><code>getSubtitles(id, s?, e?)</code></h3>
<p>Fetches subtitle files aggregated across multiple subtitle backend mirrors (<code>v1</code>, <code>v2</code>,
<code>febbox</code>). Returns clean VTT and SRT tracks.
</p>
<pre><code class="hljs language-javascript"><span class="hljs-comment">// Fetch movie subtitles</span>
<span class="hljs-keyword">const</span> movieSubs = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getSubtitles</span>(<span class="hljs-string">"155"</span>);
<span class="hljs-comment">// Fetch TV show episode subtitles</span>
<span class="hljs-keyword">const</span> tvSubs = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getSubtitles</span>(<span class="hljs-string">"1399"</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
</code></pre>
<h4 id="parameters-1">Parameters</h4>
<table>
<thead>
<tr>
<th align="left">Parameter</th>
<th align="left">Type</th>
<th align="left">Required</th>
<th align="left">Default</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>id</code></td>
<td align="left"><code>string</code></td>
<td align="left"><strong>Yes</strong></td>
<td align="left">—</td>
<td align="left">TMDB media ID.</td>
</tr>
<tr>
<td align="left"><code>s</code></td>
<td align="left"><code>string | number</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>null</code></td>
<td align="left">Season number (required for TV shows).</td>
</tr>
<tr>
<td align="left"><code>e</code></td>
<td align="left"><code>string | number</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>null</code></td>
<td align="left">Episode number (required for TV shows).</td>
</tr>
</tbody>
</table>
<h4 id="example-response-format-1">Example Response Format</h4>
<pre><code class="hljs language-json"><span class="hljs-punctuation">[</span>
<span class="hljs-punctuation">{</span>
<span class="hljs-attr">"label"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"English"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"file"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://sub.vdrk.site/v1/vtt/movie/155/English.vtt"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"vtt"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"source"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"v1"</span>
<span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-punctuation">{</span>
<span class="hljs-attr">"label"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Spanish"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"file"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://fed-subs.pstream.mov/subtitles/spanish.srt"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"srt"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"source"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"febbox"</span>
<span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">]</span>
</code></pre>
<hr>
<h3 id="getdownloadsid-s-e"><code>getDownloads(id, s?, e?)</code></h3>
<p>Fetches direct downloadable media files (MP4/MKV) paired with resolution and file size descriptors.</p>
<pre><code class="hljs language-javascript"><span class="hljs-comment">// Movie downloads</span>
<span class="hljs-keyword">const</span> downloads = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getDownloads</span>(<span class="hljs-string">"155"</span>);
<span class="hljs-comment">// TV Episode downloads</span>
<span class="hljs-keyword">const</span> tvDownloads = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getDownloads</span>(<span class="hljs-string">"1399"</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
</code></pre>
<h4 id="example-response-format-2">Example Response Format</h4>
<pre><code class="hljs language-json"><span class="hljs-punctuation">[</span>
<span class="hljs-punctuation">{</span>
<span class="hljs-attr">"url"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"https://download-node.com/file/the-dark-knight-1080p.mp4"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"quality"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"1080p"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"size"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"2.14 GB"</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"format"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"MP4"</span>
<span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">]</span>
</code></pre>
<hr>
<h2 id="provider--health-management">Provider &#x26; Health Management</h2>
<h3 id="getsourcesexcludedisabled"><code>getSources(excludeDisabled?)</code></h3>
<p>Retrieves provider configurations registered in the SDK.</p>
<pre><code class="hljs language-javascript"><span class="hljs-comment">// Get all sources including temporarily disabled ones</span>
<span class="hljs-keyword">const</span> allSources = sdk.<span class="hljs-title function_">getSources</span>(<span class="hljs-literal">false</span>);
<span class="hljs-comment">// Get only active/enabled sources</span>
<span class="hljs-keyword">const</span> activeSources = sdk.<span class="hljs-title function_">getSources</span>(<span class="hljs-literal">true</span>);
</code></pre>
<h4 id="parameters-2">Parameters</h4>
<table>
<thead>
<tr>
<th align="left">Parameter</th>
<th align="left">Type</th>
<th align="left">Required</th>
<th align="left">Default</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>excludeDisabled</code></td>
<td align="left"><code>boolean</code></td>
<td align="left"><strong>No</strong></td>
<td align="left"><code>false</code></td>
<td align="left">When <code>true</code>, filters out providers marked as disabled
(<code>disabled: true</code>).</td>
</tr>
</tbody>
</table>
<hr>
<h3 id="probesourcekey"><code>probeSource(key)</code></h3>
<p>Executes a health ping test against a single provider to determine current availability and latency using a
probe payload (<code>TMDB ID: 155</code>).</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">const</span> health = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">probeSource</span>(<span class="hljs-string">"vidrock"</span>);
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(health);
<span class="hljs-comment">// Output: { ok: true, ms: 840 }</span>
</code></pre>
<hr>
<h3 id="probeallsources"><code>probeAllSources()</code></h3>
<p>Executes health tests in parallel across all non-disabled provider modules.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">const</span> results = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">probeAllSources</span>();
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(results);
</code></pre>
<h4 id="example-response-format-3">Example Response Format</h4>
<pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>
<span class="hljs-attr">"sourcename1"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"ok"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"ms"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">420</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"sourcename2"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"ok"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"ms"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1150</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span>
<span class="hljs-attr">"sourcename3"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"ok"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"ms"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">null</span></span> <span class="hljs-punctuation">}</span>
<span class="hljs-punctuation">}</span>
</code></pre>
<hr>
<h2 id="provider-metadata-properties">Provider Metadata Properties</h2>
<p>When calling <code>getSources()</code>, each provider entry returns metadata describing its features and
streaming behavior:</p>
<pre><code class="hljs language-javascript">{
<span class="hljs-attr">key</span>: <span class="hljs-string">'example'</span>,
<span class="hljs-attr">label</span>: <span class="hljs-string">'Example'</span>,
<span class="hljs-attr">sourceFile</span>: <span class="hljs-string">'example'</span>,
<span class="hljs-attr">proxyParam</span>: <span class="hljs-string">'ex'</span>,
<span class="hljs-attr">timeout</span>: <span class="hljs-number">20000</span>,
<span class="hljs-attr">jitter</span>: <span class="hljs-number">800</span>,
<span class="hljs-attr">retries</span>: <span class="hljs-number">3</span>,
<span class="hljs-attr">multiUrl</span>: <span class="hljs-literal">true</span>,
<span class="hljs-attr">skipProxy</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">cdnHeaders</span>: [{
<span class="hljs-attr">pattern</span>: <span class="hljs-regexp">/./</span>,
<span class="hljs-attr">headers</span>: {
<span class="hljs-title class_">Referer</span>: <span class="hljs-string">'https://example.com/'</span>,
<span class="hljs-title class_">Origin</span>: <span class="hljs-string">'https://example.com'</span>
}
}]
}
</code></pre>
<h3 id="property-reference">Property Reference</h3>
<table>
<thead>
<tr>
<th align="left">Field</th>
<th align="left">Type</th>
<th align="left">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><code>key</code></td>
<td align="left"><code>string</code></td>
<td align="left">Unique identifier used in <code>getStream()</code> and <code>probeSource()</code>.</td>
</tr>
<tr>
<td align="left"><code>label</code></td>
<td align="left"><code>string</code></td>
<td align="left">Human-readable name for UI display.</td>
</tr>
<tr>
<td align="left"><code>skipProxy</code></td>
<td align="left"><code>boolean</code></td>
<td align="left">When <code>true</code>, stream URLs can be fed directly to web video players (e.g.,
HLS.js, Video.js) without needing an intermediate backend proxy.</td>
</tr>
<tr>
<td align="left"><code>multiUrl</code></td>
<td align="left"><code>boolean</code></td>
<td align="left">Indicates whether the source returns multiple stream resolution choices.</td>
</tr>
<tr>
<td align="left"><code>timeout</code></td>
<td align="left"><code>number</code></td>
<td align="left">Internal request timeout threshold in milliseconds.</td>
</tr>
<tr>
<td align="left"><code>retries</code></td>
<td align="left"><code>number</code></td>
<td align="left">Max automatic retry attempts executed by health/stream scrapers.</td>
</tr>
<tr>
<td align="left"><code>cdnHeaders</code></td>
<td align="left"><code>Array</code></td>
<td align="left">Regex pattern matching rules detailing required request headers (<code>Referer</code>,
<code>Origin</code>) needed to playback stream segments without <code>403 Forbidden</code> errors.
</td>
</tr>
<tr>
<td align="left"><code>disabled</code></td>
<td align="left"><code>boolean</code></td>
<td align="left">Set to <code>true</code> if a source is down or undergoing maintenance.</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="practical-expressjs-backend-example">Practical Express.js Backend Example</h2>
<p>Here is an example showing how to serve stream links to your client web application while handling custom CDN
playback headers and subtitle merging:</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title class_">VylaSDK</span> <span class="hljs-keyword">from</span> <span class="hljs-string">"@vyla-entertainment/sdk"</span>;
<span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>();
<span class="hljs-keyword">const</span> sdk = <span class="hljs-keyword">new</span> <span class="hljs-title class_">VylaSDK</span>({ <span class="hljs-attr">tmdbApiKey</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">TMDB_API_KEY</span> });
<span class="hljs-comment">// Scrape stream route</span>
app.<span class="hljs-title function_">get</span>(<span class="hljs-string">"/api/stream"</span>, <span class="hljs-title function_">async</span> (req, res) => {
<span class="hljs-keyword">const</span> { provider, tmdbId, season, episode } = req.<span class="hljs-property">query</span>;
<span class="hljs-keyword">const</span> clientIP = req.<span class="hljs-property">headers</span>[<span class="hljs-string">"x-forwarded-for"</span>] || req.<span class="hljs-property">socket</span>.<span class="hljs-property">remoteAddress</span>;
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> streamData = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getStream</span>(
provider,
tmdbId,
season || <span class="hljs-literal">null</span>,
episode || <span class="hljs-literal">null</span>,
clientIP
);
<span class="hljs-keyword">if</span> (!streamData || !streamData.<span class="hljs-property">url</span>) {
<span class="hljs-keyword">return</span> res.<span class="hljs-title function_">status</span>(<span class="hljs-number">404</span>).<span class="hljs-title function_">json</span>({ <span class="hljs-attr">error</span>: <span class="hljs-string">"No stream found for this provider"</span> });
}
<span class="hljs-keyword">return</span> res.<span class="hljs-title function_">json</span>({
<span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
provider,
<span class="hljs-attr">stream</span>: streamData,
});
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-keyword">return</span> res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>({ <span class="hljs-attr">error</span>: error.<span class="hljs-property">message</span> });
}
});
<span class="hljs-comment">// Fetch subtitles route</span>
app.<span class="hljs-title function_">get</span>(<span class="hljs-string">"/api/subtitles"</span>, <span class="hljs-title function_">async</span> (req, res) => {
<span class="hljs-keyword">const</span> { tmdbId, season, episode } = req.<span class="hljs-property">query</span>;
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">const</span> subtitles = <span class="hljs-keyword">await</span> sdk.<span class="hljs-title function_">getSubtitles</span>(
tmdbId,
season || <span class="hljs-literal">null</span>,
episode || <span class="hljs-literal">null</span>
);
<span class="hljs-keyword">return</span> res.<span class="hljs-title function_">json</span>({ subtitles });
} <span class="hljs-keyword">catch</span> (error) {
<span class="hljs-keyword">return</span> res.<span class="hljs-title function_">status</span>(<span class="hljs-number">500</span>).<span class="hljs-title function_">json</span>({ <span class="hljs-attr">subtitles</span>: [] });
}
});
app.<span class="hljs-title function_">listen</span>(<span class="hljs-number">3000</span>, <span class="hljs-function">() =></span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"Vyla SDK Server running on port 3000"</span>));
</code></pre>
<h2 id="sdk-vs-self-hosted-api">SDK vs Self-Hosted API</h2>
<p>The SDK and the self-hosted API server provide the same streaming functionality but in different deployment
models:</p>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>SDK</th>
<th>Self-Hosted API</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Deployment</strong></td>
<td>Embedded in your Node.js app</td>
<td>Separate server process</td>
</tr>
<tr>
<td><strong>Network</strong></td>
<td>Direct source CDN access</td>
<td>Built-in proxy for CORS</td>
</tr>
<tr>
<td><strong>Rate Limiting</strong></td>
<td>None (you control it)</td>
<td>Per-API-key limits</td>
</tr>
<tr>
<td><strong>Setup</strong></td>
<td>npm install + init</td>
<td>Clone repo + configure</td>
</tr>
<tr>
<td><strong>Use Case</strong></td>
<td>Existing Node.js apps</td>
<td>Standalone streaming service</td>
</tr>
</tbody>
</table>
<p>Choose the SDK if you want to integrate streaming directly into an existing Node.js application. Choose the
self-hosted API if you want a standalone streaming service that can be used by multiple clients.</p>
</main>
<aside id="toc">
<p class="toc-title">On this page</p>
<ul>
<li><a href="#features">Features</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#initialization">Initialization</a></li>
<li><a href="#core-methods">Core Methods</a></li>
<li><a href="#provider--health-management">Provider & Health Management</a></li>
<li><a href="#provider-metadata-properties">Provider Metadata Properties</a></li>
<li><a href="#practical-expressjs-backend-example">Practical Express.js Backend Example</a></li>
<li><a href="#sdk-vs-self-hosted-api">SDK vs Self-Hosted API</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>

346
sdk/vyla-sdk/index.md Normal file
View File

@@ -0,0 +1,346 @@
# SDK Reference
<p class="page-description">Scrape video streams, fetch subtitles, retrieve download links, and monitor provider health directly from your Node.js application.</p>
The **Vyla SDK** (`@vyla-entertainment/sdk`) is a server-side JavaScript/TypeScript package that provides direct access to Vyla's stream resolvers, health probes, download resolvers, and subtitle providers.
By embedding the SDK directly into your backend application, provider resolution executes in your own environment. It is an alternative to operating the Stream API as a separate process: your application owns its request boundary, caching, authorization, timeouts, and response shape.
:::callout-note
The SDK can be used independently of the self-hosted Stream API. If you prefer to embed Vyla capabilities in an existing Node.js application rather than run a separate HTTP service, begin with the [SDK quickstart](/sdk/vyla-sdk/quickstart).
:::
---
## Features
- **Direct-to-Client Playback**: Scraped streams link directly to source CDNs. No proxy server overhead required unless specified by provider headers.
- **Built-In Health Probing**: Monitor latency and uptime per provider with built-in health check utilities.
- **Automated Anime Sub/Dub Routing**: Automatically configures audio track requirements (`sub` vs `dub`) based on provider naming conventions.
- **Multi-Source Subtitle Aggregation**: Merges subtitle tracks from multiple redundant subtitle mirrors into a unified VTT/SRT format.
- **Metadata Fallbacks**: Automatically maps TMDB IDs to external IDs (such as IMDB and AniList) for smooth stream lookups.
- **Self-Contained**: No need to deploy a separate API server — all streaming functionality runs within your existing Node.js application.
---
## Installation
Install the package into your Node.js backend using your package manager of choice:
:::code-group
```bash [npm]
npm install @vyla-entertainment/sdk
```
```bash [pnpm]
pnpm install @vyla-entertainment/sdk
```
```bash [yarn]
yarn add @vyla-entertainment/sdk
```
:::
> **Note**: Node.js **v18+** is required due to modern standard `fetch` and `AbortSignal.timeout` usage.
---
## Initialization
Initialize the `VylaSDK` client by supplying your **TMDB API Key**. The key resolves media metadata, validates movie/TV show IDs, and translates TMDB IDs into AniList IDs for anime sources.
You may optionally provide a pengu.uk manifest URL to enable the Pengu source.
```javascript
import VylaSDK from "@vyla-entertainment/sdk";
const sdk = new VylaSDK({
tmdbApiKey: process.env.TMDB_API_KEY,
penguManifest: "" // Optional, get from pengu.uk
});
```
---
## Core Methods
### `getStream(key, id, s?, e?, clientIP?)`
Scrapes video stream URLs and playability headers for a specified provider key.
```javascript
// Fetch a movie stream (TMDB ID: 155 - The Dark Knight)
const movieStream = await sdk.getStream("sourcename", "155");
// Fetch a TV show episode (TMDB ID: 1399, Season 1, Episode 1)
const tvStream = await sdk.getStream("sourcename", "1399", 1, 1);
// Pass client IP for providers that use geo-verification
const geoStream = await sdk.getStream("sourcename", "155", null, null, "203.0.113.195");
```
#### Parameters
| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `key` | `string` | **Yes** | — | Unique key identifier for the provider (e.g. `"sourcename"`). |
| `id` | `string` | **Yes** | — | TMDB media ID (e.g., `"155"`). |
| `s` | `string \| number` | **No** | `null` | Season number (required for TV shows). |
| `e` | `string \| number` | **No** | `null` | Episode number (required for TV shows). |
| `clientIP` | `string` | **No** | `null` | End-user IP address forwarded for geo-restricted scrapers. |
#### Example Response Format
```json
{
"url": "https://example-cdn.com/hls/manifest.m3u8",
"quality": "auto",
"isM3U8": true,
"headers": {
"Referer": "https://example.com/",
"Origin": "https://example.com"
},
"allUrls": [
{
"url": "https://example-cdn.com/hls/manifest.m3u8",
"quality": "1080p",
"isM3U8": true
}
]
}
```
---
### `getSubtitles(id, s?, e?)`
Fetches subtitle files aggregated across multiple subtitle backend mirrors (`v1`, `v2`, `febbox`). Returns clean VTT and SRT tracks.
```javascript
// Fetch movie subtitles
const movieSubs = await sdk.getSubtitles("155");
// Fetch TV show episode subtitles
const tvSubs = await sdk.getSubtitles("1399", 1, 1);
```
#### Parameters
| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `id` | `string` | **Yes** | — | TMDB media ID. |
| `s` | `string \| number` | **No** | `null` | Season number (required for TV shows). |
| `e` | `string \| number` | **No** | `null` | Episode number (required for TV shows). |
#### Example Response Format
```json
[
{
"label": "English",
"file": "https://sub.vdrk.site/v1/vtt/movie/155/English.vtt",
"type": "vtt",
"source": "v1"
},
{
"label": "Spanish",
"file": "https://fed-subs.pstream.mov/subtitles/spanish.srt",
"type": "srt",
"source": "febbox"
}
]
```
---
### `getDownloads(id, s?, e?)`
Fetches direct downloadable media files (MP4/MKV) paired with resolution and file size descriptors.
```javascript
// Movie downloads
const downloads = await sdk.getDownloads("155");
// TV Episode downloads
const tvDownloads = await sdk.getDownloads("1399", 1, 1);
```
#### Example Response Format
```json
[
{
"url": "https://download-node.com/file/the-dark-knight-1080p.mp4",
"quality": "1080p",
"size": "2.14 GB",
"format": "MP4"
}
]
```
---
## Provider & Health Management
### `getSources(excludeDisabled?)`
Retrieves provider configurations registered in the SDK.
```javascript
// Get all sources including temporarily disabled ones
const allSources = sdk.getSources(false);
// Get only active/enabled sources
const activeSources = sdk.getSources(true);
```
#### Parameters
| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `excludeDisabled` | `boolean` | **No** | `false` | When `true`, filters out providers marked as disabled (`disabled: true`). |
---
### `probeSource(key)`
Executes a health ping test against a single provider to determine current availability and latency using a probe payload (`TMDB ID: 155`).
```javascript
const health = await sdk.probeSource("vidrock");
console.log(health);
// Output: { ok: true, ms: 840 }
```
---
### `probeAllSources()`
Executes health tests in parallel across all non-disabled provider modules.
```javascript
const results = await sdk.probeAllSources();
console.log(results);
```
#### Example Response Format
```json
{
"sourcename1": { "ok": true, "ms": 420 },
"sourcename2": { "ok": true, "ms": 1150 },
"sourcename3": { "ok": false, "ms": null }
}
```
---
## Provider Metadata Properties
When calling `getSources()`, each provider entry returns metadata describing its features and streaming behavior:
```javascript
{
key: 'example',
label: 'Example',
sourceFile: 'example',
proxyParam: 'ex',
timeout: 20000,
jitter: 800,
retries: 3,
multiUrl: true,
skipProxy: false,
cdnHeaders: [{
pattern: /./,
headers: {
Referer: 'https://example.com/',
Origin: 'https://example.com'
}
}]
}
```
### Property Reference
| Field | Type | Description |
| --- | --- | --- |
| `key` | `string` | Unique identifier used in `getStream()` and `probeSource()`. |
| `label` | `string` | Human-readable name for UI display. |
| `skipProxy` | `boolean` | When `true`, stream URLs can be fed directly to web video players (e.g., HLS.js, Video.js) without needing an intermediate backend proxy. |
| `multiUrl` | `boolean` | Indicates whether the source returns multiple stream resolution choices. |
| `timeout` | `number` | Internal request timeout threshold in milliseconds. |
| `retries` | `number` | Max automatic retry attempts executed by health/stream scrapers. |
| `cdnHeaders` | `Array` | Regex pattern matching rules detailing required request headers (`Referer`, `Origin`) needed to playback stream segments without `403 Forbidden` errors. |
| `disabled` | `boolean` | Set to `true` if a source is down or undergoing maintenance. |
---
## Practical Express.js Backend Example
Here is an example showing how to serve stream links to your client web application while handling custom CDN playback headers and subtitle merging:
```javascript
import express from "express";
import VylaSDK from "@vyla-entertainment/sdk";
const app = express();
const sdk = new VylaSDK({ tmdbApiKey: process.env.TMDB_API_KEY });
app.get("/api/stream", async (req, res) => {
const { provider, tmdbId, season, episode } = req.query;
const clientIP = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
try {
const streamData = await sdk.getStream(
provider,
tmdbId,
season || null,
episode || null,
clientIP
);
if (!streamData || !streamData.url) {
return res.status(404).json({ error: "No stream found for this provider" });
}
return res.json({
success: true,
provider,
stream: streamData,
});
} catch (error) {
return res.status(500).json({ error: error.message });
}
});
app.get("/api/subtitles", async (req, res) => {
const { tmdbId, season, episode } = req.query;
try {
const subtitles = await sdk.getSubtitles(
tmdbId,
season || null,
episode || null
);
return res.json({ subtitles });
} catch (error) {
return res.status(500).json({ subtitles: [] });
}
});
app.listen(3000, () => console.log("Vyla SDK Server running on port 3000"));
```
## SDK vs Self-Hosted API
The SDK and the self-hosted API server provide the same streaming functionality but in different deployment models:
| Aspect | SDK | Self-Hosted API |
| --- | --- | --- |
| **Deployment** | Embedded in your Node.js app | Separate server process |
| **Network** | Direct source CDN access | Built-in proxy for CORS |
| **Rate Limiting** | None (you control it) | Per-API-key limits |
| **Setup** | npm install + init | Clone repo + configure |
| **Use Case** | Existing Node.js apps | Standalone streaming service |
Choose the SDK if you want to integrate streaming directly into an existing Node.js application. Choose the self-hosted API if you want a standalone streaming service that can be used by multiple clients.

View File

@@ -0,0 +1,82 @@
# SDK quickstart
<p class="page-description">Install Vyla SDK, resolve a source, and build a safe server-side integration.</p>
## Before you start
Vyla SDK is for **server-side Node.js**. It contains provider integrations and makes outbound requests from the process where you install it. Do not import it into a browser bundle or expose provider results, credentials, or internal source keys directly to untrusted clients.
You need Node.js 18 or later and, for sources that resolve title metadata, a TMDB API key.
## Install and initialize
:::code-group
```bash [npm]
npm install @vyla-entertainment/sdk
```
```bash [pnpm]
pnpm install @vyla-entertainment/sdk
```
```bash [yarn]
yarn add @vyla-entertainment/sdk
```
:::
```javascript
import VylaSDK from "@vyla-entertainment/sdk";
const vyla = new VylaSDK({
tmdbApiKey: process.env.TMDB_API_KEY,
penguManifest: process.env.PENGU_MANIFEST
});
```
:::callout-warning
Keep `TMDB_API_KEY` and any deployment configuration in server-side environment variables. Never commit them or send them to a client.
:::
## Resolve a movie
First inspect active providers. Provider availability changes over time, so select a key from the running configuration instead of hard-coding a placeholder.
```javascript
const providers = vyla.getSources(true);
console.table(providers.map(({ key, label }) => ({ key, label })));
const provider = providers[0];
const result = await vyla.getStream(provider.key, 155);
const candidates = result.allUrls ?? [result];
console.log(candidates.map(({ url, type, quality }) => ({ url, type, quality })));
```
`155` is a TMDB movie ID. For an episode, include season and episode:
```javascript
const result = await vyla.getStream(provider.key, 1396, 1, 1);
```
## Make it resilient
Provider results are inherently variable: a source can fail, time out, return more than one candidate, or be temporarily disabled. In production:
1. Probe sources or maintain a recent availability signal before choosing one.
2. Give every provider call a request deadline in your application.
3. Treat `allUrls` as fallback candidates, not a guarantee that every URL will play.
4. Return only the fields your client needs and validate requests at your own API boundary.
5. Cache and rate-limit at your boundary to avoid repeatedly triggering upstream work.
```javascript
const health = await vyla.probeAllSources();
const usableKey = Object.entries(health).find(([, result]) => result.ok)?.[0];
if (!usableKey) throw new Error("No providers are currently available");
const stream = await vyla.getStream(usableKey, 155);
```
## Next steps
- Read the complete [SDK reference](/sdk) for methods and return shapes.
- Learn provider flags, timeout behavior, and source keys in [Providers](/concepts/providers).
- Choose [Stream API](/stream-api/overview) only when an SSE HTTP interface better fits your client architecture.