mirror of
https://github.com/Inside4ndroid/TMDB-Embed-API.git
synced 2026-10-22 09:35:11 +00:00
408 lines
16 KiB
Markdown
408 lines
16 KiB
Markdown
# 🍿 TMDB Embed API
|
||
|
||
> Modern, configurable streaming metadata + source aggregation API with a secure admin panel and multi-key TMDB rotation.
|
||
|
||
<p align="center">
|
||
<img src="https://img.shields.io/badge/Node.js-18%2B-brightgreen?style=flat" />
|
||
<img src="https://img.shields.io/badge/Status-Active-success?style=flat" />
|
||
<img src="https://img.shields.io/badge/License-MIT-blue?style=flat" />
|
||
<img src="https://img.shields.io/badge/Version-1.0.7-informational?style=flat" />
|
||
<img src="https://img.shields.io/docker/pulls/inside4ndroid/tmdb-embed-api?label=Docker%20Pulls&style=flat" />
|
||
</p>
|
||
|
||
---
|
||
|
||
## 📸 Screenshots
|
||
<p align="center">
|
||
<img src="screenshots/Screenshot 2025-09-16 174931.png" width="46%" />
|
||
<img src="screenshots/Screenshot 2025-09-16 175002.png" width="46%" />
|
||
</p>
|
||
<p align="center">
|
||
<img src="screenshots/Screenshot 2025-09-16 175008.png" width="46%" />
|
||
<img src="screenshots/Screenshot 2025-09-16 175013.png" width="46%" />
|
||
</p>
|
||
<p align="center">
|
||
<img src="screenshots/Screenshot 2025-09-16 175020.png" width="46%" />
|
||
<img src="screenshots/Screenshot 2025-09-16 175026.png" width="46%" />
|
||
</p>
|
||
<p align="center">
|
||
<img src="screenshots/Screenshot 2025-09-16 175033.png" width="46%" />
|
||
<img src="screenshots/Screenshot 2025-09-16 175040.png" width="46%" />
|
||
</p>
|
||
|
||
---
|
||
|
||
## ✨ Features
|
||
- **Multi‑TMDB Key Rotation** – Supply multiple API keys; one is chosen randomly per request.
|
||
- **Provider Aggregation** – Pluggable providers (Showbox, 4khdhub, MoviesMod, MP4Hydra, VidZee, Vixsrc, UHDMovies) 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.js` → `providerFunctionMap`).
|
||
- **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
|
||
```bash
|
||
# 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):
|
||
```bash
|
||
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:
|
||
```bash
|
||
docker run -it -p 8787:8787 inside4ndroid/tmdb-embed-api:latest
|
||
```
|
||
|
||
Persist overrides (Windows PowerShell example) by mounting a local file:
|
||
```powershell
|
||
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
|
||
```bash
|
||
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:
|
||
```bash
|
||
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
|
||
FEBBOX_COOKIES=cookie1,cookie2
|
||
```
|
||
|
||
To stop & remove:
|
||
```bash
|
||
docker compose down
|
||
```
|
||
|
||
### Switching to Multiple TMDB Keys
|
||
Either set `TMDB_API_KEYS` to a JSON array string:
|
||
```bash
|
||
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
|
||
| Variable | Purpose | Notes |
|
||
|----------|---------|-------|
|
||
| `API_PORT` | Port the server listens on | Defaults to 8787 |
|
||
| `TMDB_API_KEY` | Single TMDB key (legacy) | Use if you only have one key |
|
||
| `TMDB_API_KEYS` | JSON array of keys | Overrides single key when present |
|
||
| `FEBBOX_COOKIES` | Comma separated FebBox cookies | Enables Showbox provider immediately |
|
||
| `PASSWORD_HASH` | Pre-seed admin password hash | Optional (UI can set) |
|
||
| `ADMIN_USERNAME` | Override default username | Default: `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
|
||
```bash
|
||
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.
|
||
|
||
| Endpoint | Method | Purpose |
|
||
|----------|--------|---------|
|
||
| `/auth/login` | POST | Authenticate (JSON: `{ username, password }`) |
|
||
| `/auth/logout` | POST | Destroy session |
|
||
| `/auth/session` | GET | Check session status |
|
||
| `/auth/change-password` | POST | Update 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`
|
||
```json
|
||
{
|
||
"defaultProviders": ["showbox","4khdhub"],
|
||
"tmdbApiKeys": ["KEY_A","KEY_B"],
|
||
"enableShowboxProvider": true
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎛 Admin UI Sections
|
||
| Panel | Summary |
|
||
|-------|---------|
|
||
| Core | Port, default providers, default region |
|
||
| Quality / Filters | Min quality presets & codec exclusion JSON |
|
||
| Keys | Add/remove TMDB API keys (rotated randomly) |
|
||
| FebBox / PStream | Manage FebBox cookies powering Showbox provider |
|
||
| Advanced | Provider toggles, cache & validation flags |
|
||
| Server Status | Live metrics, provider functional checks |
|
||
| Live Config | View 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/PStream integration
|
||
- `4khdhub` - 4KHDHub streams
|
||
- `moviesmod` - MoviesMod streams
|
||
- `mp4hydra` - MP4Hydra streams
|
||
- `vidzee` - VidZee streams
|
||
- `vixsrc` - Vixsrc streams
|
||
- `uhdmovies` - UHD Movies streams
|
||
|
||
|
||
### Adding a New Provider
|
||
1. **Create** `providers/yourprovider.js` with your stream fetching logic
|
||
2. **Export** a function like `getYourproviderStreams(tmdbId, mediaType, season, episode)`
|
||
3. **Register** it in `providers/registry.js` → `providerFunctionMap`:
|
||
```js
|
||
// providers/registry.js
|
||
const providerFunctionMap = {
|
||
'Showbox.js': 'getStreamsFromTmdbId',
|
||
'4khdhub.js': 'get4KHDHubStreams',
|
||
'moviesmod.js': 'getMoviesModStreams',
|
||
'MP4Hydra.js': 'getMP4HydraStreams',
|
||
'VidZee.js': 'getVidZeeStreams',
|
||
'vixsrc.js': 'getVixsrcStreams',
|
||
'uhdmovies.js': 'getUHDMoviesStreams',
|
||
'yourprovider.js': 'getYourproviderStreams'
|
||
};
|
||
```
|
||
4. The provider will appear in the admin UI with an enable/disable toggle.
|
||
|
||
**Example Provider (Unified Output):**
|
||
```javascript
|
||
async function getYourproviderStreams(tmdbId, mediaType, season, episode) {
|
||
// Your scraping/API logic here
|
||
return [{
|
||
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
|
||
| Endpoint | Description |
|
||
|----------|-------------|
|
||
| `GET /api/health` | Basic heartbeat |
|
||
| `GET /api/metrics` | Runtime counters & summary |
|
||
| `GET /api/status` | Metrics + providers + endpoints list |
|
||
| `GET /api/providers` | Enabled providers summary |
|
||
| `GET /api/providers/:name` | Single provider status |
|
||
| `GET /api/streams/:type/:tmdbId` | Aggregate streams (`type` = movie|series) |
|
||
| `GET /api/streams/:provider/:type/:tmdbId` | Provider-specific streams |
|
||
| `GET /api/config` | `{ merged, override }` |
|
||
| `POST /api/config` | Apply override patch |
|
||
|
||
Aggregate endpoint auto-resolves IMDb when needed and merges provider output before filtering.
|
||
|
||
---
|
||
|
||
## 🧪 Stream Object Schema (Unified)
|
||
```json
|
||
{
|
||
"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)
|
||
| Flag | Default | Purpose |
|
||
|------|---------|---------|
|
||
| disableCache | false | Disables internal caches (Showbox + proxy segment cache) |
|
||
| enablePStreamApi | true | Enables Showbox PStream-specific handling |
|
||
| disableUrlValidation | false | Skip general URL pattern validation checks |
|
||
| disable4khdhubUrlValidation | false | Skip 4khdhub-specific URL validation |
|
||
| enableProxy | false | Mounts 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:
|
||
```json
|
||
{ "default": "900p", "showbox": "1080p" }
|
||
```
|
||
- Codec exclusion JSON example:
|
||
```json
|
||
{ "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
|
||
| Aspect | Recommendation |
|
||
|--------|---------------|
|
||
| Node Version | 18+ LTS |
|
||
| Reverse Proxy | Terminate TLS (e.g., Nginx) and forward to API port |
|
||
| Persistent Config | Mount / persist `utils/user-config.json` |
|
||
| Logs | Pipe stdout to centralized logger |
|
||
| Scaling | Use 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
|
||
| Symptom | Cause / Fix |
|
||
|---------|------------|
|
||
| No streams from Showbox | Missing FebBox cookies |
|
||
| TMDB quota issues | Add more keys under Keys panel |
|
||
| Provider missing in matrix | Ensure its enable flag exists & UI updated |
|
||
| Empty merged config after restart | `user-config.json` deleted or unreadable |
|
||
| Streams low quality | Adjust 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:
|
||
|
||
➡️ **GitHub Sponsors:** https://github.com/sponsors/Inside4ndroid
|
||
|
||
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!* ✨
|
||
|
||
---
|