Skip to content

omss-spec/framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OMSS Framework

NPM Version License: MIT TypeScript OMSS Spec Node.js

social preview

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!



🎯 What is OMSS?

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.

πŸ” What is the @omss/framework?

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.

Key Features

  • βœ… 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

πŸ“‹ Table of Contents

πŸš€ Installation

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.

Prerequisites

  • Node.js 18.x or higher
  • npm or yarn
  • TMDB API Key (Get one here)
  • (Optional) Redis server for caching

Install Dependencies

# npm
npm install @omss/framework

# yarn
yarn add @omss/framework

# pnpm
pnpm add @omss/framework

πŸš€ Quick start

Minimal 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=development

Run in dev:

npx tsx src/server.ts

And then it should work!

βš™οΈ Configuration

Server Configuration Options

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)
    };
}

Example Configurations

Development

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,
    },
});

Production with Redis

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,
    },
});

Behind Reverse Proxy

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,
    },
});

πŸ”Œ Creating Custom Providers

See the detailed Provider Creation Guide for a complete walkthrough.

Quick Start with Auto-Discovery

The easiest way to add a new provider:

  1. Create a directory for all of your provider files

    touch src/providers/implementations/my-provider.ts
  2. Implement the BaseProvider class (see example below) in each file.

  3. In the Setup, use the discoverProviders method of the ProviderRegistry to load all providers from that directory:

    const registry = server.getRegistry();
    registry.discoverProviders('./src/providers/implementations'); // relative to where you start the server from
  4. That's it! The provider will be automatically discovered and registered when you start the server!

No imports, no manual registration needed!

Minimal Provider Example

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;
        }
    }
}

Full Provider Example

See the detailed Provider Creation Guide for a complete walkthrough.

πŸ“‘ API Endpoints

GET /v1/movies/:tmdbId

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": []
}

GET /v1/tv/:tmdbId/seasons/:season/episodes/:episode

Fetch streaming sources for a TV episode.

Parameters:

  • tmdbId (path): TMDB series ID
  • season (path): Season number (0-99)
  • episode (path): Episode number (1-9999)

Response: Same structure as movies endpoint

GET /v1/proxy

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"
        }
    }

GET /v1/refresh/:responseId

Force refresh cached sources.

Parameters:

  • responseId (path): Response ID from previous request

GET /v1/health

Health check endpoint.

Response:

{
    "status": "healthy",
    "version": "1.0.0",
    "providers": {
        "total": 1,
        "enabled": 1
    }
}

🌍 Environment Variables

# 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

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        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)                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βœ… OMSS Compliance

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

πŸ“š Additional Resources

🀝 Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

πŸ“„ License

MIT License - see LICENSE file for details.

πŸ™ Acknowledgments

  • All maintainers
  • OMSS specification contributors