This is an extendable multi site scraping framework, which follows the implementation guidelines of the OMSS (Open Media Streaming Standard). It demonstrates how to build a compliant streaming media aggregation service that scrapes content from multiple providers and returns standardized responses. It handles most of the logic already for you. You just have to add the scraping logic!
OMSS is an open standard for streaming media aggregation. It provides a unified API for fetching movie and TV show streaming sources from multiple providers, with built-in proxy support, subtitle handling, and quality selection.
The @omss/framework is the official TypeScript/Node.js implementation framework that makes building OMSS-compliant backends effortless. Instead of manually implementing the specification from scratch, developers can focus solely on writing provider scraping logic while the framework handles all the boilerplate β routing, validation, proxy management, caching, error handling, and response formatting.
- β Standardized API: Consistent response format across all providers
- β Multi-Provider Support: Aggregate sources from multiple streaming providers
- β Built-in Proxy: Automatic URL proxying with header forwarding
- β TMDB Integration: Validation against The Movie Database
- β Caching Layer: Redis or in-memory caching for performance
- β Type Safety: Full TypeScript support
- β Provider Management: Easy enable/disable, automatic discovery
- β Health Checks: Monitor provider availability
- β Refresh API: Force cache invalidation when needed
- Installation
- Quick Start
- Configuration
- Creating Custom Providers
- API Endpoints
- Environment Variables
- Architecture
- OMSS Compliance
- License
There is a template which you can use to easily create your own streaming backend. Check it out here! This is the easiest way to create your own OMSS backend.
- Node.js 18.x or higher
- npm or yarn
- TMDB API Key (Get one here)
- (Optional) Redis server for caching
# npm
npm install @omss/framework
# yarn
yarn add @omss/framework
# pnpm
pnpm add @omss/frameworkMinimal example using the builtβin provider and inβmemory cache:
// src/server.ts
import { OMSSServer } from '@omss/framework';
import { ExampleProvider } from './src/providers/implementations/example-provider';
// Create server instance
const server = new OMSSServer({
name: 'My OMSS Backend',
version: '1.0.0',
host: 'localhost',
port: 3000,
cache: {
type: 'memory',
ttl: {
sources: 7200,
subtitles: 7200,
},
},
tmdb: {
apiKey: process.env.TMDB_API_KEY,
cacheTTL: 86400,
},
});
// Register providers
const registry = server.getRegistry();
registry.register(new ExampleProvider());
// or use the very cool auto-discovery feature
// registry.discoverProviders('./path/to/providerfolder');
// Note: this is relative to where you start the server.
// Start server
await server.start();.env:
TMDB_API_KEY=your_tmdb_key_here
HOST=localhost
PORT=3000
NODE_ENV=developmentRun in dev:
npx tsx src/server.tsAnd then it should work!
interface OMSSConfig {
// Required: Server identification
name: string; // Your server name
version: string; // OMSS Spec version
// Optional: Network settings
host?: string; // Default: 'localhost'
port?: number; // Default: 3000
publicUrl?: string; // For reverse proxy setups
// Optional: Cache configuration
cache?: {
type: 'memory' | 'redis';
ttl: {
sources: number;
subtitles: number;
};
redis?: {
host: string;
port: number;
password?: string;
};
};
// Required: TMDB configuration
tmdb?: {
apiKey?: string; // Can also use TMDB_API_KEY env var
cacheTTL?: number; // Default: 86400 (24 hours)
};
}const server = new OMSSServer({
name: 'OMSS Dev Server',
version: '1.0.0',
host: 'localhost',
port: 3000,
cache: {
type: 'memory',
ttl: {
sources: 7200,
subtitles: 7200,
},
},
tmdb: {
apiKey: process.env.TMDB_API_KEY,
cacheTTL: 86400,
},
});const server = new OMSSServer({
name: 'OMSS Production',
version: '1.0.0',
host: '0.0.0.0',
port: 3000,
publicUrl: 'https://api.mystream.com',
cache: {
type: 'redis',
ttl: {
sources: 7200,
subtitles: 7200,
},
redis: {
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD,
},
},
tmdb: {
apiKey: process.env.TMDB_API_KEY,
cacheTTL: 86400,
},
});const server = new OMSSServer({
name: 'OMSS API',
version: '1.0.0',
host: '0.0.0.0',
port: 3000,
// This is the public URL clients will use
publicUrl: 'https://myapp.com/api',
cache: {
type: 'redis',
redis: {
host: 'redis.internal',
port: 6379,
},
},
tmdb: {
apiKey: process.env.TMDB_API_KEY,
cacheTTL: 86400,
},
});See the detailed Provider Creation Guide for a complete walkthrough.
The easiest way to add a new provider:
-
Create a directory for all of your provider files
touch src/providers/implementations/my-provider.ts
-
Implement the
BaseProviderclass (see example below) in each file. -
In the Setup, use the
discoverProvidersmethod of theProviderRegistryto load all providers from that directory:const registry = server.getRegistry(); registry.discoverProviders('./src/providers/implementations'); // relative to where you start the server from
-
That's it! The provider will be automatically discovered and registered when you start the server!
No imports, no manual registration needed!
import { BaseProvider } from './src/providers/base-provider';
import { ProviderCapabilities, ProviderMediaObject, ProviderResult } from './src/core/types';
export class MyProvider extends BaseProvider {
// Required: Provider identification
readonly id = 'my-provider';
readonly name = 'My Provider';
readonly enabled = true;
// Required: Base URL and headers
readonly BASE_URL = 'https://provider.example.com';
readonly HEADERS = {
'User-Agent': 'Mozilla/5.0',
Referer: 'https://provider.example.com',
};
// Required: Declare what this provider supports
readonly capabilities: ProviderCapabilities = {
supportedContentTypes: ['movies', 'tv'],
};
// Implement movie scraping
async getMovieSources(media: ProviderMediaObject): Promise<ProviderResult> {
this.console.log('Fetching movie sources', media);
try {
// Your scraping logic here
const streamUrl = await this.scrapeMovieUrl(media.tmdbId); // this is just some example function
return {
sources: [
{
url: this.createProxyUrl(streamUrl, this.HEADERS),
type: 'hls',
quality: '1080p',
audioTracks: [
{
language: 'en',
label: 'English',
},
],
provider: {
id: this.id,
name: this.name,
},
},
],
subtitles: [],
diagnostics: [],
};
} catch (error) {
this.console.error('Failed to fetch sources', error, media);
return {
sources: [],
subtitles: [],
diagnostics: [
{
code: 'PROVIDER_ERROR',
message: `${this.name} failed`,
field: '',
severity: 'error',
},
],
};
}
}
// Implement TV scraping
async getTVSources(media: ProviderMediaObject): Promise<ProviderResult> {
// Similar to getMovieSources but for TV
return { sources: [], subtitles: [], diagnostics: [] };
}
// Optional: Custom health check
async healthCheck(): Promise<boolean> {
try {
const response = await fetch(this.BASE_URL);
return response.ok;
} catch {
return false;
}
}
}See the detailed Provider Creation Guide for a complete walkthrough.
Fetch streaming sources for a movie.
Parameters:
tmdbId(path): TMDB movie ID
Response:
{
"responseId": "uuid-v4",
"expiresAt": "2026-01-18T20:00:00.000Z",
"sources": [
{
"url": "/v1/proxy?data=...",
"type": "hls",
"quality": "1080p",
"audioTracks": [
{
"language": "en",
"label": "English"
}
],
"provider": {
"id": "vixsrc",
"name": "VixSrc"
}
}
],
"subtitles": [],
"diagnostics": []
}Fetch streaming sources for a TV episode.
Parameters:
tmdbId(path): TMDB series IDseason(path): Season number (0-99)episode(path): Episode number (1-9999)
Response: Same structure as movies endpoint
Proxy streaming URLs with custom headers.
Query Parameters:
data(required): URL-encoded JSON containing:{ "url": "https://stream.example.com/video.m3u8", "headers": { "Referer": "https://provider.example.com" } }
Force refresh cached sources.
Parameters:
responseId(path): Response ID from previous request
Health check endpoint.
Response:
{
"status": "healthy",
"version": "1.0.0",
"providers": {
"total": 1,
"enabled": 1
}
}# Server Configuration
PORT=3000 # Port number for the server
HOST=0.0.0.0 # Use 'localhost' to restrict to local access
NODE_ENV=development # 'development' | 'production'
# TMDB Configuration
TMDB_API_KEY=your_tmdb_api_key_here
TMDB_CACHE_TTL=86400
# Cache Configuration
CACHE_TYPE=memory # 'memory' | 'redis'
# Redis Configuration (if using Redis cache)
REDIS_HOST=localhost # default Redis host
REDIS_PORT=6379 # default Redis port
REDIS_PASSWORD= # Redis password if requiredβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OMSS Server β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Controllers β
β βββ ContentController (Movies/TV endpoints) β
β βββ ProxyController (Streaming proxy) β
β βββ HealthController (Health checks) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Services β
β βββ SourceService (Aggregates provider results) β
β βββ TMDBService (Validates against TMDB) β
β βββ ProxyService (Handles URL proxying) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Provider Registry β
β βββ Manages all registered providers β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Providers (Implement BaseProvider) β
β βββ YourCustomProvider β
β βββ ... β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Cache Layer β
β βββ MemoryCache (Development) β
β βββ RedisCache (Production) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
This implementation follows the OMSS Specification:
- β Standardized Response Format: All responses follow OMSS schema
- β TMDB Validation: All requests validated against TMDB
- β Proxy Support: Required for all streaming URLs
- β Error Handling: OMSS-compliant error responses
- β Source Identification: Unique IDs for all sources
- β Audio Track Support: Multiple audio tracks per source
- β Subtitle Support: VTT/SRT subtitle formats
- β Quality Indicators: Resolution-based quality tags
- β Provider Attribution: Source provider identification
- β Diagnostics: Detailed error/warning information
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
MIT License - see LICENSE file for details.
- All maintainers
- OMSS specification contributors