mirror of
https://gitlab.com/vyla-entertainment/documentation.git
synced 2026-11-14 22:47:26 -05:00
huge doc rewrite
This commit is contained in:
588
sdk/index.html
588
sdk/index.html
@@ -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 & 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
346
sdk/vyla-sdk/index.md
Normal 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.
|
||||
82
sdk/vyla-sdk/quickstart.md
Normal file
82
sdk/vyla-sdk/quickstart.md
Normal 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.
|
||||
Reference in New Issue
Block a user