Skip to content

Repository files navigation

🍿 TMDB Embed API

Modern, configurable streaming metadata + source aggregation API with a secure admin panel and multi-key TMDB rotation.


📸 Screenshots


✨ Features

  • Multi‑TMDB Key Rotation – Supply multiple API keys; one is chosen randomly per request.

  • Provider Aggregation – Pluggable providers (Showbox/FebBox, 4KHDHub, VixSrc, Videasy, Vidlink, LordFlix, NoTorrent, DahmerMovies) with per‑provider enable toggles + default selection.

  • 🔥 Plugin System – Drop new provider files in providers/ and add its exported function to the registry map (providers/registry.jsproviderFunctionMap).

  • Dynamic Filtering – Minimum quality presets, custom JSON quality map, codec exclusion rules (presets + JSON).

  • Runtime Overrides UI – Fully interactive web admin at / (login protected) writing to utils/user-config.json.

  • Session Auth + Rate Limiting – Login system with brute‑force lockouts, logout, password change.

  • Status & Health Panel – Live metrics, provider status, endpoint list, functional provider checks.

  • Config Propagation – Overrides mirrored to process.env for legacy compatibility (no .env required after first save).

  • Back‑Navigation Safe – Cache-control + visibility/session revalidation.

  • Extensible – Simple drop-in provider plugin system.

  • Optional Stream Proxy Layer – When enabled, rewrites returned stream URLs so HLS playlists, TS segments, and subtitles are served through internal endpoints (/m3u8-proxy, /ts-proxy, /sub-proxy) allowing uniform headers, origin shielding, and optional segment caching. When active the API omits per-stream headers objects from responses (they're no longer needed by clients) to avoid leaking upstream header requirements.

    Proxy Tuning Parameters (query flags accepted by /ts-proxy – defaults shown):

    • clampOpen (on) – If a client sends an ambiguous Range: bytes=0-, constrain it to an initial window of openChunkKB (default 4096 KB) to avoid huge first reads.
    • openChunkKB=4096 – Size (KB) used for both clamp window and each progressive expansion increment.
    • progressiveOpen (on) – Grow successive ambiguous head requests (bytes=0-) incrementally instead of one large span. Maintains a per‑URL expansion map.
    • initChunkKB=512 – Size used for a synthetic initial partial (206) when no client range is provided and progressive growth is disabled. Capped 64–2048 KB.
    • noSynth=1 – Disable synthetic initial partial generation (forces pass‑through behavior).
    • force200=1 – Normalize upstream 206 responses to 200 (diagnostics / edge player testing).
    • tailPrefetch (on) – Enable asynchronous tail fetch of the file’s last bytes to satisfy rapid player tail probes.
    • tailPrefetchKB=256 – Tail window size (64–2048 KB). Cached in memory with TTL cleanup. Behavior Notes:
    • Synthetic partials auto‑disable when progressiveOpen is active (real progressive ranges preferred).
    • Player tail probes (e.g., VLC metadata scans) are accelerated by the cached tail window.
    • Forced 200 mode strips Content-Range to emulate full responses for troubleshooting.
    • Host Overrides: pixeldrain.* and video-downloads.googleusercontent.com URLs are routed through /ts-proxy regardless of extension to ensure correct range + MIME handling.

📦 Quick Start

# 1. Install dependencies
npm install
# 2. (Optional) Copy example env if you want an initial TMDB key
cp .env.example .env # then edit TMDB_API_KEY=# 3. Start API with automatic restarts (recommended for local dev)
npm start
# Or production-style single run# node apiServer.js# 4. Open the Admin UI (login page) in browser
http://localhost:8787/
# 5. Health check
curl http://localhost:8787/api/health

🐳 Docker Usage

Pull & Run (Fastest)

If you just want to run it (no building):

docker pull inside4ndroid/tmdb-embed-api:latest
docker run --name tmdb-embed-api -p 8787:8787 \ 
-e TMDB_API_KEY=YOUR_TMDB_KEY \
inside4ndroid/tmdb-embed-api:latest

Or the minimal quick-test run:

docker run -it -p 8787:8787 inside4ndroid/tmdb-embed-api:latest

Persist overrides (Windows PowerShell example) by mounting a local file:

New-Item-ItemType File -Path .\utils\user-config.json -Force |Out-Null
docker run --name tmdb-embed-api -p 8787:8787`-e TMDB_API_KEY=YOUR_TMDB_KEY `-v ${PWD}/utils/user-config.json:/app/utils/user-config.json `
inside4ndroid/tmdb-embed-api:latest

Build Locally

docker build -t tmdb-embed-api .
docker run --name tmdb-embed -p 8787:8787 \
-e TMDB_API_KEY=YOUR_TMDB_KEY \
-v "$(pwd)/utils/user-config.json:/app/utils/user-config.json" \
tmdb-embed-api

After first login + save, the UI writes overrides into the mounted user-config.json so they persist across container restarts.

docker-compose

An example docker-compose.yml is included. Start with:

docker compose up -d --build

Environment variables can be supplied via a .env file in the same directory (Compose automatically loads it). Example .env:

TMDB_API_KEY=first_key

To stop & remove:

docker compose down

Switching to Multiple TMDB Keys

Either set TMDB_API_KEYS to a JSON array string:

docker run -p 8787:8787 \
-e TMDB_API_KEYS='["KEY1","KEY2","KEY3"]' \
tmdb-embed-api

or add / remove keys inside the Admin UI (Keys panel) and save.

Key Environment Variables

VariablePurposeNotes
API_PORTPort the server listens onDefaults to 8787
TMDB_API_KEYSingle TMDB key (legacy)Use if you only have one key
TMDB_API_KEYSJSON array of keysOverrides single key when present
PASSWORD_HASHPre-seed admin password hashOptional (UI can set)
ADMIN_USERNAMEOverride default usernameDefault: admin

If both TMDB_API_KEY and TMDB_API_KEYS are provided, rotation uses the array. Clearing the array in the UI also clears the legacy key.


Updating the Image

docker compose pull # if using an external registry (future)
docker compose up -d --build
### Restart from Admin UI
The Admin panel includes a Restart Server control.
- Local (nodemon): the backend writes a `restart.trigger` file and exits; nodemon detects the change and restarts automatically.
- Docker Compose: the container exits and is restarted by `restart: unless-stopped`.

Healthcheck

Container health relies on GET /api/health. If you disable or modify that route, adjust the Dockerfile / compose healthcheck accordingly.


�🔐 Authentication

The root (/) serves the login page. After successful login a session cookie (session) is issued (HttpOnly; 12h lifetime). All admin pages (e.g. config.html) require an active session.

EndpointMethodPurpose
/auth/loginPOSTAuthenticate (JSON: { username, password })
/auth/logoutPOSTDestroy session
/auth/sessionGETCheck session status
/auth/change-passwordPOSTUpdate password (requires session)

Repeated failed logins trigger exponential lockouts (Retry-After header emitted).


🛠 Configuration Model

All runtime state collapses into a merged object displayed in the UI (Live Config panel). Source order:

  1. Initial environment variables / optional .env
  2. JSON overrides: utils/user-config.json

Saving in the UI writes only changed keys. Setting a field to empty removes the override (reverting to env/default). Removing all TMDB keys (and saving) clears tmdbApiKeys and the legacy tmdbApiKey.

Override File:utils/user-config.json

{
"defaultProviders": ["4khdhub"],
"tmdbApiKeys": ["KEY_A","KEY_B"],
"enable4khdhubProvider": true
}

🎛 Admin UI Sections

PanelSummary
CorePort, default providers, default region
Quality / FiltersMin quality presets & codec exclusion JSON
KeysAdd/remove TMDB API keys (rotated randomly)
AdvancedProvider toggles, cache & validation flags
Server StatusLive metrics, provider functional checks
Live ConfigView merged + override JSON snapshots

Session is revalidated on visibility and back/forward navigation to prevent stale access.


🔌 Providers

The API supports a plugin system. Drop a new provider file in the providers/ folder and register its exported function in providers/registry.js under providerFunctionMap.

Current Built-in Providers

  • showbox - Showbox/FebBox streams (requires FebBox JWT cookie)
  • 4khdhub - 4KHDHub streams
  • vixsrc - VixSrc streams
  • videasy - Videasy streams (10 servers via enc-dec.app)
  • vidlink - Vidlink streams (via enc-dec.app)
  • lordflix - LordFlix streams (9 servers via enc-dec.app)
  • notorrent - NoTorrent streams (Stremio addon API)
  • dahmermovies - DahmerMovies streams (direct file links)

Adding a New Provider

  1. Createproviders/yourprovider.js with your stream fetching logic
  2. Export a function like getYourproviderStreams(tmdbId, mediaType, season, episode)
  3. Register it in providers/registry.jsproviderFunctionMap:
    // providers/registry.jsconstproviderFunctionMap={'Showbox.js': 'getStreamsFromTmdbId','4khdhub.js': 'get4KHDHubStreams','vixsrc.js': 'getVixsrcStreams','videasy.js': 'getVideasyStreams','vidlink.js': 'getVidlinkStreams','lordflix.js': 'getLordflixStreams','notorrent.js': 'getNotorrentStreams','dahmermovies.js': 'getDahmermoviesStreams','yourprovider.js': 'getYourproviderStreams'};
  4. The provider will appear in the admin UI with an enable/disable toggle.

Example Provider (Unified Output):

asyncfunctiongetYourproviderStreams(tmdbId,mediaType,season,episode){// Your scraping/API logic herereturn[{title: "Fight Club - 1080p [YourProvider #1]",url: "https://stream.url/video.mp4",quality: "1080p",provider: "yourprovider",headers: {"User-Agent": "Mozilla/5.0"}}];}module.exports={ getYourproviderStreams };

⚠️ Important: All providers must return streams in the unified JSON format to ensure compatibility with filtering and aggregation.

The system automatically:

  • ✅ Detects new provider files
  • ✅ Adds enable/disable toggles in the admin UI
  • ✅ Includes them in stream aggregation
  • ✅ Applies filtering and quality controls
  • ✅ No core file edits required!

📡 Key Endpoints

EndpointDescription
GET /api/healthBasic heartbeat
GET /api/metricsRuntime counters & summary
GET /api/statusMetrics + providers + endpoints list
GET /api/providersEnabled providers summary
GET /api/providers/:nameSingle provider status
GET /api/streams/:type/:tmdbIdAggregate streams (type = movie
GET /api/streams/:provider/:type/:tmdbIdProvider-specific streams
GET /api/config{ merged, override }
POST /api/configApply override patch

Aggregate endpoint auto-resolves IMDb when needed and merges provider output before filtering.


🧪 Stream Object Schema (Unified)

{
"title": "Fight Club - 1080p [MP4Hydra #2]",
"url": "https://stream.url/video.mp4",
"quality": "1080p",
"provider": "mp4hydra",
"headers": { "User-Agent": "Mozilla/5.0" }
}

Filtering passes through applyFilters to enforce min quality + codec exclusions.

Note: When the enableProxy flag is turned on, provider-specific request headers are stripped from each stream object before responding. Clients should use the proxied URL directly without adding custom Referer/Origin headers.


⚙️ Configuration Flags (Advanced Panel)

FlagDefaultPurpose
disableCachefalseDisables internal caches
disable4khdhubUrlValidationfalseSkip 4khdhub-specific URL validation
enableProxyfalseMounts proxy routes and rewrites stream URLs through them

Toggle enableProxy to activate the internal proxy. This adds lightweight playlist/segment/subtitle rewriting without modifying provider code. Disable it to return direct upstream URLs.


🧩 Quality & Codec Filtering

  • Presets: all, 480p, 720p, 1080p, 1440p, 2160p.
  • Custom quality JSON example:
{ "default": "900p", "4khdhub": "1080p" }
  • Codec exclusion JSON example:
{ "excludeDV": true, "excludeHDR": false }

🔐 Security Notes

  • Admin UI requires login; session cookie is HttpOnly.
  • Cache-control headers disable storing sensitive pages.
  • Login is rate limited with escalating lockouts.
  • Password change endpoint enforces minimum length.

🚀 Deployment Tips

AspectRecommendation
Node Version18+ LTS
Reverse ProxyTerminate TLS (e.g., Nginx) and forward to API port
Persistent ConfigMount / persist utils/user-config.json
LogsPipe stdout to centralized logger
ScalingUse a single instance unless providers are CPU bound

For ephemeral platforms (e.g., Vercel) note that some providers use temporary directories; avoid enabling disk-heavy cache directories.


💡 Troubleshooting

SymptomCause / Fix
TMDB quota issuesAdd more keys under Keys panel
Provider missing in matrixEnsure its enable flag exists & UI updated
Empty merged config after restartuser-config.json deleted or unreadable
Streams low qualityAdjust min quality preset or custom JSON

🤝 Contributing

PRs welcome. Keep changes focused and avoid unrelated formatting churn. For new providers include:

  • A short rationale
  • Retry / timeout safeguards
  • Respect for existing filtering structure

❤️ Sponsorship

If this project helps you, consider sponsoring to support continued development & maintenance:

Sponsor on GitHub

Every contribution accelerates feature delivery & sustainability.


📜 License

MIT. See LICENSE.


🙏 Acknowledgements

Inspired by community scraping/stream aggregation efforts. Credits also to the original NuvioStreamsAddon work for earlier concepts.


Happy streaming & hacking!


About

An api to get embed sources using tmdb id.

Topics

Resources

Stars

129 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages