4.4 KiB
Contributing a Source Provider
Complete technical guide for authoring, testing, and contributing a new video scraping resolver to the Vyla SDK.
Overview
The Vyla SDK maintains its high reliability through a distributed collection of independent provider scrapers located in src/sources/. We welcome contributions of new sources that expand coverage for movies, television, and international content.
Scraper Architecture
Every provider module is a self-contained ES Module adhering to a single exported contract:
export async function getStream(args: StreamArgs): Promise<StreamResult | { allUrls: StreamResult[] }>
The args Object
When your scraper's getStream() is invoked, the SDK passes a normalized args context containing:
| Field | Type | Description |
|---|---|---|
id |
string | number |
The TMDB numeric media ID or string IMDb ID. |
s |
number | null |
Season number for television episodes (or null for movies). |
e |
number | null |
Episode number for television episodes (or null for movies). |
clientIP |
string | null |
The viewer's client IP address (if passed from an upstream proxy). |
fetch |
Function |
Node.js fetch wrapper pre-configured with timeout controls. |
imdbId |
string | null |
Automatically resolved IMDb ID (if TMDB API key is configured). |
title |
string | null |
Verified media title string. |
year |
number | null |
Media release year. |
Step-by-Step Implementation Guide
Step 1: Create the Scraper Module
Create a new file in src/sources/<source_name>.js:
const BASE_URL = 'https://provider-domain.example.com';
const DEFAULT_HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
'Referer': `${BASE_URL}/`,
'Origin': BASE_URL,
};
export async function getStream({ id, s, e, imdbId }) {
const isTv = s != null && e != null;
const endpoint = isTv
? `${BASE_URL}/api/tv/${id}/${s}/${e}`
: `${BASE_URL}/api/movie/${id}`;
const response = await fetch(endpoint, {
headers: DEFAULT_HEADERS
});
if (!response.ok) {
throw new Error(`Upstream returned HTTP ${response.status}`);
}
const data = await response.json();
if (!data.streamUrl) {
throw new Error('No stream found in upstream response');
}
return {
url: data.streamUrl,
headers: {
...DEFAULT_HEADERS,
'Referer': data.referer || DEFAULT_HEADERS.Referer
},
server: 'MySource-Primary',
quality: data.quality || '1080p',
type: data.streamUrl.includes('.m3u8') ? 'hls' : 'mp4'
};
}
Step 2: Register in src/config.js
Add your provider configuration to the SOURCES array in src/config.js:
{
key: 'mysource',
label: 'My Source',
sourceFile: 'mysource',
proxyParam: 'ms',
timeout: 12000,
jitter: 400,
retries: 1,
multiUrl: false,
skipProxy: false,
skipVerify: false
}
Configuration Field Guidelines:
key: Lowercase alphanumeric identifier without spaces (e.g.vidlink,cinecat).label: Clean display title shown in UI menus.proxyParam: Unique 2-to-4 character query flag used by the Stream API HLS proxy (must not collide with existing flags).timeout: Maximum execution budget before aborting (typically 8,000ms–15,000ms).jitter: Random delay ceiling (typically 300ms–500ms) to avoid server burst locks.
Step 3: Local Testing
Run your scraper against known TMDB titles using the test runner:
# Test a known movie (The Dark Knight - TMDB 155)
node test/index.js mysource 155
# Test a known TV episode (Breaking Bad S01E01 - TMDB 1396)
node test/index.js mysource 1396 1 1
Verify that:
- A valid URL is printed.
- The
typeis correctly identified as'hls'or'mp4'. - Required upstream headers (
Referer,Origin,User-Agent) are included. - Testing an invalid ID throws a clean error without crashing the process.
Contribution Rules & Checklist
Before submitting a Pull Request to the GitLab repository:
- Code is formatted with clean ES Module syntax.
- No hardcoded personal API keys or credentials.
- Provider does not execute external untrusted
eval()or un-sanitized script execution. - Upstream stream candidate URLs must be verified for playback.
- Errors are thrown with informative messages (
throw new Error(...)).