huge rewrite

This commit is contained in:
2026-11-14 18:21:12 -08:00
parent f465d1ec0d
commit 2cec85a8f3
69 changed files with 11479 additions and 1576 deletions

View File

@@ -1,54 +1,141 @@
# Subtitles and downloads
# Subtitles & Media Downloads
<p class="page-description">Unified media-data paths for movies and TV episodes.</p>
<p class="page-description">REST API reference for retrieving subtitle tracks and direct media download packages for movies and television series.</p>
## Subtitle paths
## Subtitle Endpoints
| Media | Path |
| --- | --- |
| Movie | `GET /subtitles/movie/:id` |
| TV episode | `GET /subtitles/tv/:id/:season/:episode` |
Stream API provides dedicated REST endpoints to fetch subtitle tracks independently from video streams. Subtitles are discovered and parsed into web-standard `.vtt` or `.srt` formats.
The same routes are available under `/api/subtitles`. A successful response is a JSON array of tracks; a missing result returns `404` with an error object.
---
```json
[
{
"label": "English",
"file": "https://example.invalid/subtitles/en.vtt",
"type": "vtt",
"source": "v1"
}
]
### 1. Movie Subtitles
```http
GET /subtitles/movie/:id HTTP/1.1
Host: your-api.example.com
```
`file` is the track URL, `type` is normally `vtt` or `srt`, and `source` identifies the subtitle backend. Prefer the tracks included in the playback `meta` event when you are already opening a playback stream; use these paths when subtitles are fetched separately.
#### Path Parameters
| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `id` | `integer` | Required | Numeric TMDB Movie ID (e.g. `155`) |
## Download paths
| Media | Path |
| --- | --- |
| Movie | `GET /downloads/movie/:id` |
| TV episode | `GET /downloads/tv/:id/:season/:episode` |
The `/api/downloads` prefix is also supported. A successful response is an array; an empty array simply means no candidates were found.
```json
[
{
"url": "https://example.invalid/file.mp4",
"quality": "1080p",
"size": "2.14 GB",
"format": "MP4"
}
]
#### Example Request & Response
```bash
curl https://your-api.example.com/subtitles/movie/155
```
Download URLs are provider results, not durable Vyla-hosted files. Display quality and size as informational fields, and handle expired or unavailable links in your client.
```json
{
"subtitles": [
{
"label": "English",
"file": "https://your-api.example.com/api?url=https%3A%2F%2Fsubtitles.org%2Fen.vtt",
"type": "vtt",
"source": "opensubtitles"
},
{
"label": "Spanish",
"file": "https://your-api.example.com/api?url=https%3A%2F%2Fsubtitles.org%2Fes.vtt",
"type": "vtt",
"source": "opensubtitles"
},
{
"label": "French",
"file": "https://your-api.example.com/api?url=https%3A%2F%2Fsubtitles.org%2Ffr.srt",
"type": "srt",
"source": "subdl"
}
]
}
```
## Request and response rules
---
- IDs are TMDB IDs; TV paths additionally require season and episode numbers.
- Both families return JSON, unlike the SSE playback paths.
- Handle `404` for missing subtitles and `500` for an upstream or resolver failure.
- Do not block first playback on either call. Fetch them in parallel or after the player has started.
### 2. Television Episode Subtitles
```http
GET /subtitles/tv/:id/:season/:episode HTTP/1.1
Host: your-api.example.com
```
#### Path Parameters
| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `id` | `integer` | Required | Numeric TMDB TV Series ID (e.g. `1396`) |
| `season` | `integer` | Required | Season number (e.g. `1`) |
| `episode` | `integer` | Required | Episode number (e.g. `1`) |
#### Example Request
```bash
curl https://your-api.example.com/subtitles/tv/1396/1/1
```
---
## Download Endpoints
Stream API resolves high-speed direct media download packages and torrent/debrid links. Download lookups are separated from playback streams to allow offline caching or background download managers.
---
### 1. Movie Downloads
```http
GET /downloads/movie/:id HTTP/1.1
Host: your-api.example.com
```
#### Example Response
```json
{
"downloads": [
{
"quality": "1080p",
"size": 2450882194,
"type": "mkv",
"active": true,
"url": "https://fast-cdn.example.com/download/the-dark-knight-1080p.mkv"
},
{
"quality": "720p",
"size": 1150428190,
"type": "mkv",
"active": true,
"url": "https://fast-cdn.example.com/download/the-dark-knight-720p.mkv"
}
]
}
```
---
### 2. Television Episode Downloads
```http
GET /downloads/tv/:id/:season/:episode HTTP/1.1
Host: your-api.example.com
```
#### Example Response
```json
{
"downloads": [
{
"quality": "1080p",
"size": 1420882194,
"type": "mkv",
"active": true,
"url": "https://fast-cdn.example.com/download/breaking-bad-s01e01-1080p.mkv"
}
]
}
```
---
## Best Practices for Clients
1. **Do Not Block Initial Playback**: Initiate subtitle and download queries asynchronously. The video player should start playback immediately on the first candidate stream, and subtitles should be attached dynamically as they arrive.
2. **CORS Handling**: Subtitle files proxied through `/api?url=...` are served with `Access-Control-Allow-Origin: *`, ensuring HTML5 `<track>` elements load cleanly in cross-origin browser contexts.
3. **Format Support**: While most modern players prefer `.vtt`, some tracks are returned in `.srt`. If your player strictly requires WebVTT, convert SRT timestamps (`00:01:20,500` -> `00:01:20.500`) client-side before loading.

View File

@@ -1,37 +1,107 @@
# Health, testing, and safe operations
# Operations, Health & Diagnostics
<p class="page-description">Observe SDK providers and diagnose a Stream API deployment without making debug data public.</p>
<p class="page-description">Monitoring, cluster diagnostics, live health probing, and testing endpoints in Stream API.</p>
## Health
## The Health Check Endpoint: `GET /health`
`GET /health` (or `/api/health`) probes active providers and returns a JSON summary. It includes a status, timestamp, TMDB-key presence, cache size, and a map of provider keys to `{ ok, ms }` results.
Stream API provides an automated health probe endpoint that executes live responsiveness checks across all registered scraper modules.
Health is a signal, not a promise of playback. Provider behavior can differ by title, client network, and the moment of the request. Use it for observability and source selection-not as a guarantee that a viewer will receive a stream.
## Test one provider
`GET /test/:id?source=:providerKey` resolves a single provider for a movie. Add `season` and `episode` (or `s` and `e`) for TV.
```bash
curl "YOUR_API_URL/test/155?source=provider-key"
curl "YOUR_API_URL/test/1396?season=1&episode=1&source=provider-key"
```http
GET /health HTTP/1.1
Host: your-api.example.com
```
Use source keys reported by the running deployment. A test result reports whether resolution and verification succeeded; clients should inspect the result body rather than relying only on a transport success.
### Response Status Codes
- **`200 OK`**: All active provider sources passed their health probes.
- **`207 Multi-Status`**: One or more providers failed their probes (degraded state), but the API gateway remains functional.
## Debug route
### Example Response Payload
```json
{
"note": "This is a health check endpoint. This is extremely unreliable, be sure to test sources directly.",
"status": "ok",
"timestamp": "2026-11-14T20:30:00.000Z",
"tmdb": true,
"cache": 142,
"probe_id": 155,
"sources": {
"vidlink": { "ok": true, "ms": 420 },
"vixsrc": { "ok": true, "ms": 610 },
"cinecat": { "ok": true, "ms": 890 },
"movy": { "ok": false, "ms": null }
}
}
```
`GET /debug/:id?source=:providerKey` offers detailed candidate and request traces, but it is only available when `ENABLE_DEBUG_ROUTE=true`.
#### Response Fields
| Field | Type | Description |
| :--- | :--- | :--- |
| `status` | `string` | Overall system state (`"ok"` or `"degraded"`). |
| `timestamp` | `string` | ISO 8601 timestamp of probe completion. |
| `tmdb` | `boolean` | `true` if `TMDB_API_KEY` is configured and valid in the environment. |
| `cache` | `integer` | Current number of active cached titles in the primary LRU cache. |
| `probe_id` | `integer` | The standard TMDB ID used to probe source responsiveness. |
| `sources` | `object` | Dictionary of per-source availability (`ok`) and roundtrip latency in milliseconds (`ms`). |
---
## Direct Source Testing: `GET /test/:source`
To test an individual scraper directly without querying all 60 providers:
```http
GET /test/vidlink?id=155 HTTP/1.1
```
For television episodes, pass season and episode query parameters:
```http
GET /test/vixsrc?id=1396&s=1&e=1 HTTP/1.1
```
### Response
Returns the raw resolved candidate object directly from the provider scraper:
```json
{
"source": "vidlink",
"url": "https://upstream.example.com/playlist.m3u8",
"quality": "1080p",
"type": "hls",
"server": "vidlink-cf"
}
```
---
## Deep Debug Route: `GET /debug/:source`
When `ENABLE_DEBUG_ROUTE=true` is set in your environment variables, Stream API exposes a comprehensive diagnostic route:
```http
GET /debug/vidlink?id=155 HTTP/1.1
```
### Diagnostic Output Includes:
1. **Raw Scraper Payload**: Unmodified JSON or HTML received from the upstream host.
2. **Extraction Timings**: Milliseconds spent parsing DOM, solving tokens, and resolving URLs.
3. **Phase 1 Verification**: Status code, response headers, and latency of the `HEAD` request.
4. **Phase 2 Verification**: First 500 bytes of the master M3U8 playlist and test chunk fetch status.
5. **Rewritten URLs**: Preview of how chunk URIs will be rewritten by the proxy.
:::callout-warning
Do not enable the debug route on a public deployment. It can expose upstream request data, raw candidates, and headers. Enable it temporarily in a controlled environment, then disable it again.
**Security Note**: Keep `ENABLE_DEBUG_ROUTE=false` in public production environments to avoid leaking internal scraper tokens or upstream endpoints.
:::
## Production checklist
---
- Set `TMDB_API_KEY` when metadata-dependent sources are required.
- Keep `ENABLE_DEBUG_ROUTE=false` outside controlled troubleshooting.
- Use TLS and enforce your own access policy before making the service remotely reachable.
- Monitor health trends and playback failures separately.
- Run updates and provider changes through your normal deployment process.
- Build player fallbacks instead of assuming a specific provider is always available.
## Cluster & Cache Architecture
### Primary Supervisor & Worker Pool Architecture
- **Central In-Memory Cache**: Holds up to 1,500 verified title entries in a shared LRU table with a 5-minute TTL.
- **Periodic Pruner**: Runs every 30 seconds to clean expired keys and enforce memory ceilings.
- **Worker Lifecycle Supervisor**: Spawns and supervises $N$ worker processes matching CPU core count, automatically restarting terminated workers.
- **IPC Message Dispatcher**: Routes `cache:get` and `cache:set` messages between worker threads and the primary process.
1. **IPC Cache Synchronization**: When a worker resolves a title, it sends a `cache:set` message to the primary process. When another worker receives a request for the same title, it sends a `cache:get` message and receives an instant `cache:hit` without re-scraping upstream hosts.
2. **Cache Pruning**: The primary process evicts stale items older than 300,000ms (5 minutes). If total cache size exceeds 1,500 items, the oldest entries are evicted immediately.
3. **Worker Auto-Restart**: If a worker process exits unexpectedly or exceeds memory limits, the primary cluster supervisor automatically spawns a replacement worker.

View File

@@ -1,72 +1,156 @@
# Paths and playback events
# Paths & Playback Events
<p class="page-description">The complete Stream API playback contract, unified for movies and TV episodes.</p>
<p class="page-description">Detailed API reference for Stream API streaming endpoints, Server-Sent Events contracts, and proxy query parameters.</p>
## Playback paths
## Progressive Playback Endpoints
The API supports both the short paths below and `/api`-prefixed equivalents. A movie needs only `id`; a TV episode also needs `season` and `episode`.
Stream API uses Server-Sent Events (SSE) to deliver real-time discovery events directly to player clients. This eliminates long HTTP timeouts and allows players to begin buffering the moment the first candidate resolves.
| Media | Path | Response |
| --- | --- | --- |
| Movie | `GET /movie?id=:id` | Server-Sent Events |
| TV episode | `GET /tv?id=:id&season=:season&episode=:episode` | Server-Sent Events |
---
`id` is a TMDB ID. For example:
### 1. Movie Stream Endpoint: `GET /movie` (or `/api/movie`)
```bash
curl -N "YOUR_API_URL/movie?id=155"
curl -N "YOUR_API_URL/tv?id=1396&season=1&episode=1"
Establishes an SSE event stream for a movie.
```http
GET /movie?id=155 HTTP/1.1
Host: your-api.example.com
Accept: text/event-stream
```
## Event contract
#### Query Parameters
| Parameter | Type | Required | Description | Example |
| :--- | :--- | :--- | :--- | :--- |
| `id` | `integer` | Required | Numeric TMDB Movie ID | `155` (The Dark Knight) |
Playback routes use `text/event-stream`, not a single JSON document. Read each `data: ` line as JSON.
---
### `meta`
### 2. Television Stream Endpoint: `GET /tv` (or `/api/tv`)
Sent before source resolution completes. It can include TMDB metadata and an array of subtitle tracks.
Establishes an SSE event stream for a television series episode.
```http
GET /tv?id=1396&season=1&episode=1 HTTP/1.1
Host: your-api.example.com
Accept: text/event-stream
```
#### Query Parameters
| Parameter | Type | Required | Description | Example |
| :--- | :--- | :--- | :--- | :--- |
| `id` | `integer` | Required | Numeric TMDB TV Series ID | `1396` (Breaking Bad) |
| `season` | `integer` | Required | Season number | `1` |
| `episode` | `integer` | Required | Episode number | `1` |
---
## Server-Sent Events (SSE) Contract
Connections to `/movie` and `/tv` return `Content-Type: text/event-stream` and emit events sequentially:
### Event 1: `meta` (Emitted Immediately)
Delivers title metadata and parsed subtitle tracks while scrapers are still running.
```json
{
data: {
"type": "meta",
"meta": { "id": 155, "title": "The Dark Knight" },
"subtitles": [{ "label": "English", "file": "https://…", "type": "vtt", "source": "v1" }]
"meta": {
"title": "The Dark Knight",
"year": 2008,
"tmdb_id": 155,
"imdb_id": "tt0468569",
"poster": "https://image.tmdb.org/t/p/w500/...",
"backdrop": "https://image.tmdb.org/t/p/original/..."
},
"subtitles": [
{
"label": "English",
"file": "https://your-api.example.com/api?url=...",
"type": "vtt",
"source": "opensubtitles"
}
]
}
```
### `source`
One event for each candidate that passes the service's verification pipeline.
### Event 2..N: `source` (Emitted Progressively)
Emitted as each provider scraper successfully resolves and passes two-phase verification.
```json
{
data: {
"type": "source",
"source": {
"source": "provider-key",
"label": "Provider name",
"url": "YOUR_API_URL/api?url=…"
"source": "vidlink",
"label": "VidLink Primary",
"url": "https://your-api.example.com/api?url=https%3A%2F%2Fupstream.cdn%2Fmaster.m3u8&vl=1",
"server": "vidlink-cf",
"quality": "1080p",
"type": "hls",
"headers": {
"User-Agent": "Mozilla/5.0 ...",
"Referer": "https://vidlink.pro/"
}
}
```
The `url` is ready for a player. HLS sources may be wrapped by Vyla's proxy so manifest segments and keys can be fetched with the appropriate upstream headers. Some configured sources bypass proxying. Do not assume a filename extension alone determines playback behavior.
### `done`
Sent after the configured attempts are complete.
### Event Final: `done` (Stream Closes)
Emitted when all enabled scrapers have finished resolving or reached their maximum timeout. The server closes the SSE connection immediately after.
```json
{ "type": "done", "total": 3 }
data: {
"type": "done",
"total": 5
}
```
`total: 0` means no playable sources were produced for that request. The SSE connection itself can still be successful.
---
## Client rules
## The Universal Reverse Proxy: `GET /api`
1. Start playback as soon as the first `source` arrives.
2. Queue every later source for manual switching or automatic fallback.
3. Attach subtitle tracks from `meta` without blocking playback.
4. Treat an empty result as a normal product state, not a malformed response.
5. Abort the request when the viewer leaves the page or chooses another title.
The `/api` route handles media proxying, M3U8 rewriting, segment stripping, and TMDB queries.
The [integration guide](/guides/integrations) contains a practical player pattern; [error handling](/guides/error-handling) covers fallback behavior.
### 1. Media Proxying: `/api?url=:encoded_url`
```http
GET /api?url=https%3A%2F%2Fcdn.example.com%2Fvideo.m3u8&proxyHeaders=%7B%22Referer%22%3A%22https%3A%2F%2Fsite.com%22%7D HTTP/1.1
```
#### Query Parameters
| Parameter | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `url` (or `proxy`) | `string` | Required | URL-encoded destination target. |
| `proxyHeaders` | `string` | Optional | URL-encoded JSON dictionary of custom headers to forward upstream. |
| `<source_flag>` | `string` | Optional | Provider flag matching `proxyParam` (e.g. `&vl=1`, `&vx=1`) to apply source-specific referer rules. |
| `tt` | `string` | Optional | Forces the 120-byte image de-masking routine on MPEG-TS video chunks. |
#### Proxy Behaviors
- **M3U8 Playlists**: Rewrites all `.ts` chunk lines and AES `#EXT-X-KEY` URIs so that player requests route through the proxy with permissive CORS headers.
- **Obfuscated Chunks**: If chunks begin with PNG (`0x89`), JPEG (`0xFF`), or null (`0x00`) fake headers, Stream API automatically slices off the leading 120 bytes.
- **Range Seeking**: Forwards `Range: bytes=start-end` headers to upstream servers and returns HTTP `206 Partial Content`, enabling smooth scrubbing in MP4/MKV media.
---
### 2. Active Sources Listing: `/api?sources_meta=1`
Returns the list of active streaming sources currently loaded into the instance:
```json
{
"sources": [
{ "key": "vidlink", "label": "VidLink", "timeout": 12000 },
{ "key": "vixsrc", "label": "VixSrc", "timeout": 10000 },
{ "key": "cinecat", "label": "CineCat", "timeout": 15000 }
]
}
```
---
## HTTP Status Codes & Error Responses
| Status Code | Description | Example Payload |
| :--- | :--- | :--- |
| **`200 OK`** | Request succeeded or SSE stream opened | `text/event-stream` or JSON payload |
| **`206 Partial Content`** | Byte-range media response for video scrubbing | Binary video stream chunk |
| **`400 Bad Request`** | Missing required parameters or invalid TMDB ID | `{"error": "missing id", "route": "/movie?id=:tmdb_id"}` |
| **`404 Not Found`** | Unknown route | `{"error": "not found"}` |
| **`502 Bad Gateway`** | Upstream provider connection failed or timed out | `{"error": "upstream connection timeout"}` |