mediaflow-proxy 2.4.4
A high-performance proxy server for streaming media, supporting HTTP(S), HLS, and MPEG-DASH with real-time DRM decryption.
License: MIT
Requires Python: >=3.10
Keywords: dash, drm, hls, media, proxy, streaming

# MediaFlow Proxy

<div style="text-align: center;">
  <img src="https://cdn.githubraw.com/mhdzumair/mediaflow-proxy/main/mediaflow_proxy/static/logo.png" alt="MediaFlow Proxy Logo" width="200" style="border-radius: 15px;">
</div>

MediaFlow Proxy is a powerful and flexible solution for proxifying various types of media streams. It supports HTTP(S) links, HLS (M3U8) streams, and MPEG-DASH streams, including DRM-protected content. This proxy can convert MPEG-DASH DRM-protected streams to decrypted HLS live streams in real-time, making it one of the fastest live decrypter servers available.

## Features

### Stream Processing
- Convert MPEG-DASH streams (DRM-protected and non-protected) to HLS
- **ClearKey DRM decryption** with support for all CENC encryption modes (see [DASH/MPD Support Status](#dashmpd-support-status))
- Support for **multi-key DRM** streams (different keys for video/audio tracks)
- Support for non-DRM protected DASH live and VOD streams
- Proxy and modify HLS (M3U8) streams in real-time
- **Smart pre-buffering** for both HLS and DASH streams (enabled by default)
- Proxy HTTP/HTTPS links with custom headers

### Proxy & Routing
- Advanced proxy routing system with support for:
  - Domain-based routing rules
  - Protocol-specific routing (HTTP/HTTPS)
  - Subdomain and wildcard patterns
  - Port-specific routing
- Support for HTTP/HTTPS/SOCKS5 proxy forwarding
- Flexible SSL verification control per route
- Support for expired or self-signed SSL certificates
- Public IP address retrieval for Debrid services integration

### Xtream Codes (XC) API Proxy
- **Stateless XC API proxy** for IPTV players
- Support for live streams, VOD, series, and **catch-up/timeshift**
- Compatible with any XC-compatible IPTV player (TiviMate, IPTV Smarters, etc.)
- Automatic URL rewriting for seamless proxying

### Acestream Proxy
- **Acestream P2P stream proxy** - Proxy Acestream content through MediaFlow (inspired by [Acexy](https://github.com/Javinator9889/acexy))
- Support for both **HLS manifest** and **MPEG-TS stream** output formats
- **Stream multiplexing** - Multiple clients can watch the same stream simultaneously
- Automatic **session management** with cross-process coordination
- Works with content IDs (`acestream://...`) and infohashes (magnet links)
- Compatible with any media player that supports HLS or MPEG-TS

### Telegram MTProto Proxy
- **Telegram video streaming** - Stream videos from Telegram channels, groups, and DMs through MediaFlow
- **High-speed parallel downloads** using FastTelethon technique (up to 20+ MB/s)
- **Full range-request support** - Seeking works seamlessly in video players
- Support for **t.me links** and direct file references
- Works with public channels, private channels (if member), groups, and DMs
- Persistent session management with automatic reconnection

### Security
- API password protection against unauthorized access & Network bandwidth abuse prevention
- Parameter encryption to hide sensitive information
- Optional IP-based access control for encrypted URLs
- URL expiration support for encrypted URLs

### On-the-fly Transcoding
- **Universal video/audio transcoding** to browser-compatible fMP4 (H.264 + AAC)
- **GPU hardware acceleration** (NVIDIA NVENC, Apple VideoToolbox, Intel VAAPI/QSV) with automatic CPU fallback
- Supports **any input container** (MKV, MP4, TS, WebM, FLV, etc.) and codec (HEVC, VP8/VP9, MPEG-2, MPEG-4, AC3, EAC3, Vorbis, Opus, etc.)
- **On-the-fly streaming** -- no full-file buffering; pipe-based demuxing for MKV/TS/WebM and moov-atom probing for MP4
- **Smart format detection** -- filename extension hints + magic byte sniffing to avoid wasteful probe attempts
- Available on **all proxy endpoints**: `/proxy/stream`, Telegram, Acestream, and Xtream Codes
- Triggered by `&transcode=true` query parameter with optional `&start=<seconds>` for seeking

### Additional Features
- Built-in speed test for RealDebrid and AllDebrid services
- Custom header injection and modification
- **Response header removal** - Remove problematic headers from upstream responses (e.g., incorrect Content-Length)
- **Resolution selection** - Select specific resolution (e.g., 720p, 1080p) for HLS and DASH streams
- Real-time HLS manifest manipulation
- HLS Key URL modifications for bypassing stream restrictions
- **Base64 URL Support** - Automatic detection and processing of base64 encoded URLs
- **Segment Skipping** - Skip specific time ranges in HLS and DASH streams (intro/outro skipping, ad removal)
- **Stream Transformers** - Handle host-specific stream obfuscation (e.g., PNG-wrapped MPEG-TS segments)

### DASH/MPD Support Status

#### MPD Segment Addressing Types

| Type | Status | Notes |
|------|--------|-------|
| SegmentTemplate (fixed duration) | ✅ Supported | Most common for VOD content |
| SegmentTemplate (SegmentTimeline) | ✅ Supported | Variable duration segments |
| SegmentBase | ✅ Supported | Single file with byte ranges |
| SegmentList | ✅ Supported | Explicit segment URLs in MPD |

#### MPD Presentation Types

| Type | Status | Notes |
|------|--------|-------|
| Static (VOD) | ✅ Supported | Fixed duration content |
| Dynamic (Live) | ✅ Supported | Live streaming with availabilityStartTime |

#### DRM/Encryption Support

**Supported (ClearKey):**

| Mode | Scheme | Status | Notes |
|------|--------|--------|-------|
| AES-CTR (cenc) | Full sample CTR | ✅ Supported | Standard CENC encryption |
| AES-CTR Pattern (cens) | Subsample CTR | ✅ Supported | Pattern encryption with CTR |
| AES-CBC (cbc1) | Full sample CBC | ✅ Supported | Full sample CBC mode |
| AES-CBC Pattern (cbcs) | Subsample CBC | ✅ Supported | Used by Apple FairPlay |

**Not Supported (Commercial DRM):**

| DRM System | Status | Notes |
|------------|--------|-------|
| Widevine | ❌ Not Supported | Requires license server communication |
| PlayReady | ❌ Not Supported | Microsoft's DRM system |
| FairPlay | ❌ Not Supported | Apple's DRM system (keys not extractable) |
| PrimeTime | ❌ Not Supported | Adobe's DRM system |

> **Note**: MediaFlow Proxy only supports **ClearKey** DRM where the decryption keys are provided directly. Commercial DRM systems (Widevine, PlayReady, FairPlay) require license server communication and hardware-backed security that cannot be bypassed by this proxy.

#### IV Size Support

| Size | Status | Notes |
|------|--------|-------|
| 8-byte IV | ✅ Supported | GPAC default |
| 16-byte IV | ✅ Supported | Bento4 default |
| Constant IV | ✅ Supported | Used by CBCS streams |

#### Multi-Key Support

| Feature | Status | Notes |
|---------|--------|-------|
| Single Key (all tracks) | ✅ Supported | Same key for video and audio |
| Multi-Key (per track) | ✅ Supported | Different keys for video/audio tracks |
| Key rotation | ❌ Not Supported | Keys changing mid-stream |

### Pre-buffering (HLS & DASH)

MediaFlow Proxy includes intelligent pre-buffering for both HLS and DASH streams, **enabled by default** to improve playback smoothness and reduce buffering.

#### How Pre-buffering Works

| Feature | HLS | DASH |
|---------|-----|------|
| Enabled by default | ✅ Yes | ✅ Yes |
| Smart variant selection | ✅ Only buffers the variant being played | ✅ Only buffers requested profiles |
| Live stream support | ✅ Buffers from end of playlist | ✅ Buffers from end of playlist |
| VOD support | ✅ Buffers from start | ✅ Buffers from start |
| Inactivity cleanup | ✅ Stops after 60s idle | ✅ Stops after 60s idle |
| Memory management | ✅ Configurable limits | ✅ Configurable limits |

#### Key Behaviors

1. **Smart Variant Selection (HLS)**: When a master playlist is requested, pre-buffering does NOT automatically buffer all quality variants. It only starts buffering when the player actually requests segments from a specific variant, saving bandwidth and memory.

2. **Inactivity Cleanup**: Both HLS and DASH pre-buffers automatically stop refreshing playlists and clean up resources after 60 seconds of inactivity (no segment requests). This prevents memory leaks when streams are stopped.

3. **Live Stream Optimization**: For live streams, segments are buffered from the END of the playlist (most recent) rather than the beginning, ensuring the player has the freshest content available.

4. **Memory Protection**: Pre-buffering respects configurable memory limits and will stop buffering if system memory usage exceeds thresholds.

## Configuration

Set the following environment variables:

- `API_PASSWORD`: Optional. Protects against unauthorized access and API network abuses.
- `ENABLE_STREAMING_PROGRESS`: Optional. Enable streaming progress logging. Default is `false`.
- `DISABLE_SSL_VERIFICATION_GLOBALLY`: Optional. Disable SSL verification for all requests globally. Default is `false`.
- `DISABLE_HOME_PAGE`: Optional. Disables the home page UI. Returns 403 for the root path and direct access to index.html. Default is `false`.
- `DISABLE_DOCS`: Optional. Disables the API documentation (Swagger UI). Returns 403 for the /docs path. Default is `false`.
- `DISABLE_SPEEDTEST`: Optional. Disables the speedtest UI. Returns 403 for the /speedtest path and direct access to speedtest.html. Default is `false`.
- `CLEAR_CACHE_ON_STARTUP`: Optional. Clears all caches (extractor cache, etc.) when the server starts. Useful for development and testing. Default is `false`.
- `STREMIO_PROXY_URL`: Optional. Stremio server URL for alternative content proxying. Example: `http://127.0.0.1:11470`.
- `M3U8_CONTENT_ROUTING`: Optional. Routing strategy for M3U8 content URLs: `mediaflow` (default), `stremio`, or `direct`.
- `ENABLE_HLS_PREBUFFER`: Optional. Enables HLS pre-buffering for improved streaming performance. Default: `true`. Pre-buffering downloads upcoming segments ahead of playback to reduce buffering. Set to `false` to disable for low-memory environments.
- `HLS_PREBUFFER_SEGMENTS`: Optional. Number of HLS segments to pre-buffer ahead. Default: `5`. Only effective when `ENABLE_HLS_PREBUFFER` is `true`.
- `HLS_PREBUFFER_CACHE_SIZE`: Optional. Maximum number of HLS segments to keep in memory cache. Default: `50`. Only effective when `ENABLE_HLS_PREBUFFER` is `true`.
- `HLS_PREBUFFER_MAX_MEMORY_PERCENT`: Optional. Maximum percentage of system memory to use for HLS pre-buffer cache. Default: `80`. Only effective when `ENABLE_HLS_PREBUFFER` is `true`.
- `HLS_PREBUFFER_EMERGENCY_THRESHOLD`: Optional. Emergency threshold (%) to trigger aggressive HLS cache cleanup. Default: `90`. Only effective when `ENABLE_HLS_PREBUFFER` is `true`.
- `HLS_PREBUFFER_INACTIVITY_TIMEOUT`: Optional. Seconds of inactivity before stopping HLS playlist refresh. Default: `60`. Helps clean up resources when streams are stopped.
- `LIVESTREAM_START_OFFSET`: Optional. Default start offset (in seconds) for live streams (HLS and MPD). Default: `-18`. This injects `#EXT-X-START:TIME-OFFSET` into live media playlists, causing players to start behind the live edge. This creates headroom for prebuffering to work effectively on live streams. Set to empty/unset to disable automatic injection for live streams.
- `ENABLE_DASH_PREBUFFER`: Optional. Enables DASH pre-buffering for improved streaming performance. Default: `true`. Pre-buffering downloads upcoming segments ahead of playback to reduce buffering. Set to `false` to disable for low-memory environments.
- `DASH_PREBUFFER_SEGMENTS`: Optional. Number of DASH segments to pre-buffer ahead. Default: `5`. Only effective when `ENABLE_DASH_PREBUFFER` is `true`.
- `DASH_PREBUFFER_CACHE_SIZE`: Optional. Maximum number of DASH segments to keep in memory cache. Default: `50`. Only effective when `ENABLE_DASH_PREBUFFER` is `true`.
- `DASH_PREBUFFER_MAX_MEMORY_PERCENT`: Optional. Maximum percentage of system memory to use for DASH pre-buffer cache. Default: `80`. Only effective when `ENABLE_DASH_PREBUFFER` is `true`.
- `DASH_PREBUFFER_EMERGENCY_THRESHOLD`: Optional. Emergency threshold (%) to trigger aggressive DASH cache cleanup. Default: `90`. Only effective when `ENABLE_DASH_PREBUFFER` is `true`.
- `DASH_PREBUFFER_INACTIVITY_TIMEOUT`: Optional. Seconds of inactivity before cleaning up DASH stream state. Default: `60`. Helps clean up resources when streams are stopped.
- `DASH_SEGMENT_CACHE_TTL`: Optional. TTL in seconds for cached DASH segments. Default: `60`. Longer values help with slow network playback.
- `FORWARDED_ALLOW_IPS`: Optional. Controls which IP addresses are trusted to provide forwarded headers (X-Forwarded-For, X-Forwarded-Proto, etc.) when MediaFlow Proxy is deployed behind reverse proxies or load balancers. Default: `127.0.0.1`. See [Forwarded Headers Configuration](#forwarded-headers-configuration) for detailed usage.

### Redis Configuration (Optional)

Redis enables cross-worker coordination for rate limiting and caching. This is **recommended** when running with multiple workers (`--workers N`) to prevent CDN rate-limiting issues (e.g., Vidoza 509 errors).

- `REDIS_URL`: Optional. Redis connection URL. Default: `None` (disabled). Example: `redis://localhost:6379` or `redis://user:pass@host:6379/0`.

**When to use Redis:**
- Running multiple uvicorn workers (`--workers 4` or more)
- Streaming from rate-limited CDNs like Vidoza
- Need shared caching across workers (extractor results, HEAD responses, segments)

**Features enabled by Redis:**
- **Rate limiting**: Prevents rapid-fire requests that trigger CDN 509 errors
- **HEAD cache**: Serves repeated HEAD probes (e.g., ExoPlayer) without upstream connections
- **Stream gate**: Serializes initial connections to rate-limited URLs
- **Extractor cache**: Shares extraction results across all workers
- **Segment cache**: Shares downloaded segments across workers

**Docker Compose example with Redis:**
```yaml
services:
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  mediaflow-proxy:
    image: mhdzumair/mediaflow-proxy:latest
    ports:
      - "8888:8888"
    environment:
      - API_PASSWORD=your_password
      - REDIS_URL=redis://redis:6379
    depends_on:
      redis:
        condition: service_healthy
```

**Note**: If Redis is not configured, MediaFlow Proxy works normally but rate limiting features are disabled. This is fine for single-worker deployments or CDNs that don't rate-limit aggressively.

### Acestream Configuration

MediaFlow Proxy can act as a proxy for Acestream P2P streams, converting them to HLS or MPEG-TS format that any media player can consume.

**Requirements**: You need a running Acestream engine accessible from MediaFlow Proxy.

- `ENABLE_ACESTREAM`: Optional. Enable Acestream proxy support. Default: `false`.
- `ACESTREAM_HOST`: Optional. Acestream engine host. Default: `localhost`.
- `ACESTREAM_PORT`: Optional. Acestream engine port. Default: `6878`.
- `ACESTREAM_SESSION_TIMEOUT`: Optional. Session timeout (seconds) for cleanup of inactive sessions. Default: `60`.
- `ACESTREAM_KEEPALIVE_INTERVAL`: Optional. Interval (seconds) for session keepalive polling. Default: `15`.

#### Acestream Endpoints

| Endpoint | Description |
|----------|-------------|
| `/proxy/acestream/stream` | MPEG-TS stream proxy (recommended) |
| `/proxy/acestream/manifest.m3u8` | HLS manifest proxy |
| `/proxy/acestream/status` | Get session status |

#### Acestream URL Parameters

| Parameter | Description |
|-----------|-------------|
| `id` | Acestream content ID (alternative to infohash) |
| `infohash` | Acestream infohash (40-char hex from magnet link) |
| `transcode` | Set to `true` to transcode to browser-compatible fMP4 (H.264 + AAC) |
| `start` | Seek start time in seconds (used with `transcode=true`) |

**Example URLs:**
```
# MPEG-TS stream (recommended)
https://your-mediaflow/proxy/acestream/stream?id=YOUR_CONTENT_ID&api_password=your_password

# MPEG-TS stream (infohash from magnet)
https://your-mediaflow/proxy/acestream/stream?infohash=b04372b9543d763bd2dbd2a1842d9723fd080076&api_password=your_password

# Transcode to browser-compatible fMP4
https://your-mediaflow/proxy/acestream/stream?id=YOUR_CONTENT_ID&transcode=true&api_password=your_password

# HLS manifest (alternative)
https://your-mediaflow/proxy/acestream/manifest.m3u8?id=YOUR_CONTENT_ID&api_password=your_password
```

#### Docker Compose Example with Acestream

```yaml
services:
  mediaflow-proxy:
    image: mhdzumair/mediaflow-proxy:latest
    ports:
      - "8888:8888"
    environment:
      - API_PASSWORD=your_password
      - ENABLE_ACESTREAM=true
      - ACESTREAM_HOST=acestream
      - ACESTREAM_PORT=6878

  acestream:
    image: ghcr.io/martinbjeldbak/acestream-http-proxy:latest # or build it from https://github.com/sergiomarquezdev/acestream-docker-home
    ports:
      - "6878:6878"
```

### Telegram MTProto Configuration

MediaFlow Proxy can stream Telegram media (videos, documents, photos) through the MTProto protocol, enabling high-speed parallel downloads with full HTTP range request support for seeking.

**Requirements**: 
- Telegram API credentials from [my.telegram.org/apps](https://my.telegram.org/apps)
- A valid session string (generated once, see below)

> **Note**: Telethon and cryptg are included as standard dependencies - no extra installation needed.

#### Configuration

| Environment Variable | Description | Default |
|---------------------|-------------|---------|
| `ENABLE_TELEGRAM` | Enable Telegram proxy support | `false` |
| `TELEGRAM_API_ID` | Telegram API ID from my.telegram.org | Required |
| `TELEGRAM_API_HASH` | Telegram API Hash from my.telegram.org | Required |
| `TELEGRAM_SESSION_STRING` | Persistent session string (see below) | Required |
| `TELEGRAM_MAX_CONNECTIONS` | Max parallel DC connections | `8` |
| `TELEGRAM_REQUEST_TIMEOUT` | Request timeout in seconds | `30` |

#### Generating a Session String

The session string authenticates MediaFlow with Telegram. Generate it using the web UI:

1. Open MediaFlow's URL Generator page at `/url-generator#telegram`
2. Navigate to the **Session String Generator** section
3. Enter your API ID and API Hash (from https://my.telegram.org/apps)
4. Choose authentication method (user account or bot)
5. Complete authentication (phone number + code, or bot token)

Add the generated session string to your configuration:

```env
ENABLE_TELEGRAM=true
TELEGRAM_API_ID=12345678
TELEGRAM_API_HASH=your_api_hash_here
TELEGRAM_SESSION_STRING=your_session_string_here
```

> **Security Note**: The session string is equivalent to a password. Keep it secret!

#### Telegram Endpoints

| Endpoint | Description |
|----------|-------------|
| `/proxy/telegram/stream` | Stream media from t.me link or file_id |
| `/proxy/telegram/stream/{filename}` | Stream with custom filename |
| `/proxy/telegram/transcode/playlist.m3u8` | HLS transcode playlist (recommended for browser playback and smooth seeking) |
| `/proxy/telegram/transcode/init.mp4` | fMP4 init segment for Telegram transcode playlist |
| `/proxy/telegram/transcode/segment.m4s` | fMP4 media segment for Telegram transcode playlist |
| `/proxy/telegram/info` | Get media metadata |
| `/proxy/telegram/status` | Session status and health check |

#### URL Parameters

| Parameter | Description |
|-----------|-------------|
| `d` or `url` | t.me link (e.g., `https://t.me/channel/123`) |
| `chat_id` | Chat/Channel ID (use with `message_id`) - numeric ID or @username |
| `message_id` | Message ID within the chat (use with `chat_id`) |
| `file_id` | Bot API file_id (use with `file_size`) |
| `file_size` | File size in bytes (required when using `file_id`) |
| `transcode` | Set to `true` for direct transcode mode on `/proxy/telegram/stream` (URL Generator defaults to `/proxy/telegram/transcode/playlist.m3u8` when no start time is set) |
| `start` | Seek start time in seconds (direct transcode mode only, used with `transcode=true`) |

#### Supported Input Formats

**Option 1: t.me URLs**
- **Public channels**: `https://t.me/channelname/123`
- **Private channels**: `https://t.me/c/123456789/456`
- **User messages**: `https://t.me/username/123`

**Option 2: Direct IDs**
- `chat_id=-1001234567890&message_id=123` - Private channel/supergroup by numeric ID
- `chat_id=@channelname&message_id=123` - Public channel by username

**Option 3: Bot API file_id**
- `file_id=BQACAgI...&file_size=1048576` - Direct streaming by file_id
- Requires `file_size` parameter for range request support (seeking in video players)
- Get file_id and file_size from Telegram Bot API's `getFile` response

#### Example URLs

```bash
# Stream from public channel using t.me link
mpv "http://localhost:8888/proxy/telegram/stream?d=https://t.me/channelname/123&api_password=your_password"

# Stream using chat_id + message_id
mpv "http://localhost:8888/proxy/telegram/stream?chat_id=-1001234567890&message_id=123&api_password=your_password"

# Stream with username instead of numeric ID
mpv "http://localhost:8888/proxy/telegram/stream?chat_id=@channelname&message_id=456&api_password=your_password"

# Stream using Bot API file_id (requires file_size)
mpv "http://localhost:8888/proxy/telegram/stream?file_id=BQACAgIAAxkBAAI...&file_size=52428800&api_password=your_password"

# Stream with custom filename
mpv "http://localhost:8888/proxy/telegram/stream/movie.mp4?d=https://t.me/channelname/123&api_password=your_password"

# Get media info
curl "http://localhost:8888/proxy/telegram/info?d=https://t.me/channelname/123&api_password=your_password"

# Get media info using chat_id + message_id
curl "http://localhost:8888/proxy/telegram/info?chat_id=-1001234567890&message_id=123&api_password=your_password"

# Get media info using file_id
curl "http://localhost:8888/proxy/telegram/info?file_id=BQACAgIAAxkBAAI...&api_password=your_password"

# Check status
curl "http://localhost:8888/proxy/telegram/status?api_password=your_password"
```

### Transport Configuration

MediaFlow Proxy now supports advanced transport configuration using HTTPX's routing system. You can configure proxy and SSL verification settings for different domains and protocols.

#### Basic Configuration

Enable proxy for all routes:
```env
PROXY_URL=http://proxy:8080
ALL_PROXY=true
```

#### Advanced Routing Configuration

Configure different proxy settings for specific patterns:
```env
PROXY_URL=http://proxy:8080
TRANSPORT_ROUTES='{
    "https://internal.company.com": {
        "proxy": false
    },
    "all://streaming.service.com": {
        "proxy_url": "socks5://streaming-proxy:1080",
        "verify_ssl": false
    }
}'
```

The routing system supports various patterns:
- Domain routing: `"all://example.com"`
- Subdomain routing: `"all://*.example.com"`
- Protocol-specific routing: `"https://example.com"`
- Port-specific routing: `"all://*:1234"`
- Wildcard routing: `"all://"`

#### Route Configuration Options

Each route can have the following settings:
- `proxy`: Boolean to enable/disable proxy for this route (default: true)
- `proxy_url`: Optional specific proxy URL for this route (overrides primary proxy_url)
- `verify_ssl`: Boolean to control SSL verification (default: true)

#### Configuration Examples

1. Simple proxy setup with SSL bypass for internal domain:
    ```env
    PROXY_URL=http://main-proxy:8080
    TRANSPORT_ROUTES='{
        "https://internal.domain.com": {
            "proxy": false,
            "verify_ssl": false
        }
    }'
    ```

2. Different proxies for different services:
    ```env
    PROXY_URL=http://default-proxy:8080
    TRANSPORT_ROUTES='{
        "all://*.streaming.com": {
            "proxy": true,
            "proxy_url": "socks5://streaming-proxy:1080"
        },
        "all://*.internal.com": {
            "proxy": false
        },
        "https://api.service.com": {
            "proxy": true,
            "verify_ssl": false
        }
    }'
    ```

3. Global proxy with exceptions:
    ```env
    PROXY_URL=http://main-proxy:8080
    ALL_PROXY=true
    TRANSPORT_ROUTES='{
        "all://local.network": {
            "proxy": false
        },
        "all://*.trusted-service.com": {
            "proxy": false
        }
    }'
    ```

### Forwarded Headers Configuration

When MediaFlow Proxy is deployed behind reverse proxies, load balancers, or CDNs (such as Nginx, Apache, Cloudflare, AWS ALB, etc.), it needs to properly handle forwarded headers to determine the real client IP address and original request protocol. The `FORWARDED_ALLOW_IPS` environment variable and `--forwarded-allow-ips` uvicorn parameter control which IP addresses are trusted to provide these headers.

#### What are Forwarded Headers?

Forwarded headers are HTTP headers that preserve information about the original client request when it passes through intermediary servers:

- **X-Forwarded-For**: Contains the original client IP address
- **X-Forwarded-Proto**: Contains the original request protocol (http/https)
- **X-Real-IP**: Alternative header for client IP address
- **X-Forwarded-Host**: Contains the original host header

#### Security Importance

Only trusted proxy servers should be allowed to set these headers, as malicious clients could potentially spoof them to bypass IP-based restrictions or logging. MediaFlow Proxy uses these headers for:

- **Client IP Detection**: For IP-based access control in encrypted URLs
- **Protocol Detection**: For generating correct URLs with proper schemes
- **Security Logging**: For accurate request tracking and abuse prevention

#### Configuration Options

**Environment Variable (Docker/Production):**
```env
# Trust only localhost (default - most secure)
FORWARDED_ALLOW_IPS=127.0.0.1

# Trust specific proxy IPs
FORWARDED_ALLOW_IPS=10.0.0.1,192.168.1.100

# Trust all IPs (use with caution)
FORWARDED_ALLOW_IPS=*

```
> **⚠️ Security warning**  
> Setting `FORWARDED_ALLOW_IPS=*` disables IP-spoofing protection and must **only** be used in trusted LAN or dev environments.  
> In production, always list the concrete IPs of your reverse-proxy servers.

**Uvicorn Command Line Parameter:**
```bash
# Trust only localhost (recommended for local development)
uvicorn mediaflow_proxy.main:app --forwarded-allow-ips "127.0.0.1"

# Trust specific proxy servers
uvicorn mediaflow_proxy.main:app --forwarded-allow-ips "10.0.0.1,192.168.1.100"

# Trust all IPs (development only - not recommended for production)
uvicorn mediaflow_proxy.main:app --forwarded-allow-ips "*"
```

#### Common Deployment Scenarios

**1. Direct Internet Access (No Proxy)**
```bash
# Remove --forwarded-allow-ips parameter entirely or use localhost only
uvicorn mediaflow_proxy.main:app --host 0.0.0.0 --port 8888
```

**2. Behind Nginx Reverse Proxy**
```env
# Trust the Nginx server IP
FORWARDED_ALLOW_IPS=127.0.0.1
```

**3. Behind Cloudflare**
```env
# Trust Cloudflare IP ranges (example - check current Cloudflare IPs)
FORWARDED_ALLOW_IPS=173.245.48.0,103.21.244.0,103.22.200.0
```

**4. Behind AWS Application Load Balancer**
```env
# Trust the VPC subnet where ALB is deployed
FORWARDED_ALLOW_IPS=10.0.0.0
```

**5. Docker with Host Network**
```env
# Trust the Docker host
FORWARDED_ALLOW_IPS=172.17.0.1
```

**6. Docker Compose with Nginx in Same Network**
```env
# Trust the Docker network range (when nginx and mediaflow-proxy are in same docker network)
FORWARDED_ALLOW_IPS=172.20.0.0
# Or trust all Docker IPs (less secure but simpler for development)
FORWARDED_ALLOW_IPS=*
```

**7. Kubernetes with Ingress**
```env
# Trust the ingress controller pod network
FORWARDED_ALLOW_IPS=10.244.0.0
```

#### Best Practices

1. **Principle of Least Privilege**: Only trust the specific IP addresses of your proxy servers
2. **Regular Updates**: Keep your trusted IP list updated when infrastructure changes
3. **Monitor Logs**: Watch for unexpected forwarded headers from untrusted sources
4. **Test Configuration**: Verify that client IPs are correctly detected after configuration changes

#### Troubleshooting

**Problem**: Client IP always shows as proxy IP
- **Solution**: Add your proxy server's IP to `FORWARDED_ALLOW_IPS`

**Problem**: Security warnings about untrusted forwarded headers
- **Solution**: Restrict `FORWARDED_ALLOW_IPS` to only include your actual proxy servers

**Problem**: IP-based restrictions not working correctly
- **Solution**: Verify that forwarded headers are being processed by checking the trusted IP configuration

**Problem**: Links return 302 redirects when nginx is in the same Docker network
- **Solution**: Set `FORWARDED_ALLOW_IPS=*` or specify the Docker network (e.g., `FORWARDED_ALLOW_IPS=172.20.0.0`)
- **Note**: When nginx and MediaFlow Proxy run in the same Docker network, you must configure `FORWARDED_ALLOW_IPS` to trust the Docker network IP range, otherwise proxy links will not work correctly

#### Example Nginx Configuration

When using Nginx as a reverse proxy, ensure it's properly setting forwarded headers:

```nginx
server {
    listen 80;
    server_name your-domain.com;
    
    location / {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

Then configure MediaFlow Proxy to trust Nginx:
```env
FORWARDED_ALLOW_IPS=127.0.0.1
```

### Reverse Proxy Configuration

MediaFlow Proxy is commonly deployed behind reverse proxies for SSL termination, load balancing, and additional security. Here are detailed configurations for popular reverse proxy solutions.

#### Nginx Configuration

**Basic Nginx Configuration:**

```nginx
server {
    listen 80;
    server_name mediaflow.yourdomain.com;
    
    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name mediaflow.yourdomain.com;
    
    # SSL Configuration
    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # Security Headers
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    # Client settings for streaming
    client_max_body_size 0;
    client_body_timeout 60s;
    client_header_timeout 60s;
    
    location / {
        # Proxy settings
        proxy_pass http://127.0.0.1:8888;
        proxy_http_version 1.1;
        proxy_cache_bypass $http_upgrade;
        
        # Headers for forwarded information
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # Headers for streaming support
        proxy_set_header Range $http_range;
        proxy_set_header If-Range $http_if_range;
        proxy_set_header Connection "";
        
        # Timeout settings for streaming
        proxy_connect_timeout 60s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
        
        # Disable buffering for streaming
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_max_temp_file_size 0;
        
        # Handle redirects
        proxy_redirect off;
    }
    
    # Optional: Specific location for streaming endpoints with extended timeouts
    location ~* ^/proxy/(stream|hls|mpd)/ {
        proxy_pass http://127.0.0.1:8888;
        proxy_http_version 1.1;
        
        # Extended timeouts for large streams
        proxy_connect_timeout 60s;
        proxy_send_timeout 600s;
        proxy_read_timeout 600s;
        
        # Streaming optimizations
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_max_temp_file_size 0;
        
        # Forward all necessary headers
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Range $http_range;
        proxy_set_header If-Range $http_if_range;
        proxy_set_header Connection "";
    }
    
    # Access and error logs
    access_log /var/log/nginx/mediaflow_access.log;
    error_log /var/log/nginx/mediaflow_error.log;
}
```

**MediaFlow Proxy Configuration for Nginx:**
```env
# Trust Nginx server
FORWARDED_ALLOW_IPS=127.0.0.1

# Other recommended settings
API_PASSWORD=your_secure_password
```

#### Nginx Proxy Manager Configuration

Nginx Proxy Manager provides a web-based interface for managing Nginx reverse proxy configurations.

**Step 1: Create Proxy Host**

In the Nginx Proxy Manager web interface:

**Details Tab:**
- **Domain Names**: `mediaflow.yourdomain.com`
- **Scheme**: `http`
- **Forward Hostname/IP**: `127.0.0.1` (or MediaFlow Proxy container IP)
- **Forward Port**: `8888`
- **Cache Assets**: ❌ (disabled)
- **Block Common Exploits**: ❌ (disabled)
- **Websockets Support**: ❌ (not required)
- **Access List**: None (unless you need IP restrictions)

**Step 2: SSL Configuration**

**SSL Tab:**
- **SSL Certificate**: Select your certificate (Let's Encrypt recommended)
- **Force SSL**: ✅ (redirect HTTP to HTTPS)
- **HTTP/2 Support**: ✅ (recommended for performance)
- **HSTS Enabled**: ✅ (recommended for security)
- **HSTS Subdomains**: ✅ (if applicable)

**Step 3: Advanced Configuration**

**Advanced Tab - Custom Nginx Configuration:**

```nginx
# Headers for forwarded information
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

# Headers for streaming support
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
proxy_set_header Connection "";

# Timeout settings for streaming
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;

# Disable buffering for streaming
proxy_buffering off;
proxy_request_buffering off;
proxy_max_temp_file_size 0;

# Client settings
client_max_body_size 0;
client_body_timeout 60s;
client_header_timeout 60s;

# Handle redirects
proxy_redirect off;

# HTTP version
proxy_http_version 1.1;

# Security headers
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Hide server information
proxy_hide_header X-Powered-By;
server_tokens off;
```

**Step 4: MediaFlow Proxy Configuration**

Configure MediaFlow Proxy to trust Nginx Proxy Manager:

**If running on the same server:**
```env
FORWARDED_ALLOW_IPS=127.0.0.1
```

**If running in Docker with custom network:**
```env
# Use the Docker network range
FORWARDED_ALLOW_IPS=172.18.0.0/16
```

**If Nginx Proxy Manager is on a different server:**
```env
# Replace with actual Nginx Proxy Manager IP
FORWARDED_ALLOW_IPS=10.0.0.5
```

**Step 5: Docker Compose Example**

Complete Docker Compose setup with Nginx Proxy Manager:

```yaml
version: '3.8'

services:
  nginx-proxy-manager:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81'  # Admin interface
    volumes:
      - ./npm-data:/data
      - ./npm-letsencrypt:/etc/letsencrypt
    networks:
      - proxy-network

  mediaflow-proxy:
    image: 'mhdzumair/mediaflow-proxy:latest'
    restart: unless-stopped
    ports:
      - '8888:8888'
    environment:
      - API_PASSWORD=your_secure_password
      - FORWARDED_ALLOW_IPS=172.18.0.0/16
    networks:
      - proxy-network

networks:
  proxy-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.18.0.0/16
```

#### Important Notes for Nginx Proxy Manager

**Block Common Exploits Setting:**

The "Block Common Exploits" feature in Nginx Proxy Manager provides automatic protection against common web attacks but may occasionally block legitimate streaming URLs that contain special characters. 

**What it blocks:**
- Path traversal attempts (`../`, `..%2F`)
- SQL injection patterns
- XSS attempts
- Suspicious file extensions
- Very long URLs (>2000 characters)
- Base64-like patterns

**Recommendation:**
- **Enable it initially** for security
- **Monitor logs** for false positives
- **Disable only if necessary** for specific streaming services

**If you experience issues with legitimate URLs being blocked:**

1. **Check the logs** in Nginx Proxy Manager for 403 errors
2. **Test problematic URLs** directly
3. **Consider disabling** "Block Common Exploits" if it interferes with streaming
4. **Implement alternative security** measures (Cloudflare WAF, fail2ban, etc.)

#### Troubleshooting Reverse Proxy Issues

**Problem: MediaFlow Proxy shows proxy IP instead of client IP**
- **Solution**: Verify `FORWARDED_ALLOW_IPS` includes your proxy server IP
- **Check**: Ensure proxy is sending `X-Forwarded-For` headers

**Problem: Streaming timeouts or interruptions**
- **Solution**: Increase timeout values in proxy configuration
- **Check**: Disable proxy buffering with `proxy_buffering off`

**Problem: Large file uploads fail**
- **Solution**: Set `client_max_body_size 0` in Nginx configuration
- **Check**: Verify `proxy_request_buffering off` is set

**Problem: SSL/HTTPS issues**
- **Solution**: Ensure `X-Forwarded-Proto` header is properly set
- **Check**: Verify SSL certificates are valid and properly configured

**Problem: 502/504 Gateway errors**
- **Solution**: Check MediaFlow Proxy is running and accessible
- **Check**: Verify network connectivity between proxy and MediaFlow Proxy
- **Check**: Review timeout settings in proxy configuration

### Speed Test Feature

MediaFlow Proxy now includes a built-in speed test feature for testing RealDebrid and AllDebrid network speeds. To access the speed test:

1. Open your browser and navigate to `http://your-server:8888/speedtest.html`
2. The speed test page allows you to:
   - Test download speeds from RealDebrid servers
   - Test download speeds from AllDebrid servers


## Installation

### Option 1: Self-Hosted Deployment

#### Using Docker from Docker Hub

1. Pull & Run the Docker image:
   ```
   docker run -p 8888:8888 -e API_PASSWORD=your_password mhdzumair/mediaflow-proxy
   ```
### Using Docker Compose

1. Set the `API_PASSWORD` and other environment variables in `.env`:

   ```
   echo "API_PASSWORD=your_password" > .env
   ```
2. Bring up the Docker Container:

   ```
   docker compose up --detach
   ```

#### Using pip

> [!IMPORTANT]
> Ensure that you have Python 3.10 or higher installed.

1. Install the package:
   ```
   pip install mediaflow-proxy
   ```

2. Set the `API_PASSWORD` and other environment variables in `.env`:
   ```
   echo "API_PASSWORD=your_password" > .env
   ```

3. Run the MediaFlow Proxy server:
   ```
   mediaflow-proxy
   ```
   You can access the server at `http://localhost:8888`.

4. To run the server with uvicorn options: (Optional)
   ```
   uvicorn mediaflow_proxy.main:app --host 0.0.0.0 --port 8888 --workers 4 --forwarded-allow-ips "*"
   ```

   > **Note**
   > > Omit `--forwarded-allow-ips "*"` when running locally.

#### Using git & uv

> [!IMPORTANT]
> Ensure that you have Python 3.10 or higher and [uv](https://docs.astral.sh/uv/getting-started/installation/) installed.


1. Clone the repository:
   ```
   git clone https://github.com/mhdzumair/mediaflow-proxy.git
   cd