xiaosongshu/rtmp_server

Native PHP RTMP live server with FLV/HLS, MP4 slicing, PHP client, relay & gateway.

Maintainers

Package info

github.com/2723659854/rtmp-server

Type:project

pkg:composer/xiaosongshu/rtmp_server

Transparency log

Statistics

Installs: 37

Dependents: 0

Suggesters: 0

Stars: 5

Open Issues: 0

v2.4.8 2026-07-30 07:27 UTC

README

πŸ‡¨πŸ‡³ δΈ­ζ–‡ζ–‡ζ‘£ β€’ πŸ‡¬πŸ‡§ English Docs

A lightweight RTMP live streaming service built in pure PHP, zero dependencies on FFmpeg, Nginx, or other third-party streaming software, enabling rapid deployment of private live streaming platforms out of the box. On Linux environments, the event extension is automatically enabled for epoll event-driven architecture; on Windows, it automatically falls back to the select I/O model, ensuring full platform compatibility. Project positioning: underlying infrastructure β€” complete self-developed RTMP/HTTP-FLV/WS-FLV protocol stack and asynchronous network engine; upper-layer applications such as business management, authentication, and playback management need to be extended and developed by developers. The project supports H.264 decoding + scaling + watermarking + encoding, enabling re-encoding of FLV, MP4, and HLS streams at different bitrates to adapt to various network environments and devices.

Table of Contents

Requirements

Dependency Requirement Description
PHP >= 8.1, CLI mode only, FPM not supported
sockets extension Mandatory, provides underlying TCP/WS/RTMP communication
event extension Strongly recommended on Linux for epoll high-concurrency event model; Windows automatically falls back to select when not installed

Quick deployment: The project includes a docker-compose.yml file β€” run docker-compose up -d to start the complete runtime environment with one command.

Quick Start

1. Project Installation

composer create-project xiaosongshu/rtmp_server

2. Start the Origin Server

php server.php

Successful startup output example:

[INFO] RTMP Server started on 0.0.0.0:1935
[INFO] HTTP-FLV/WS-FLV Server started on 0.0.0.0:8501
[INFO] HTTP Static Server started on 0.0.0.0:80

3. Quick Push Stream Test

Method 1: Browser-based Push (No Software Required)

  • Screen real-time push: http://127.0.0.1/push.html
  • Local MP4/FLV file loop push: http://127.0.0.1/flv_push.html

Method 2: FFmpeg Standard Push

ffmpeg -re -stream_loop -1 -i video.mp4 -c:v libx264 -c:a aac -f flv rtmp://127.0.0.1:1935/live/stream

Method 3: OBS Studio Push

  • Server: rtmp://127.0.0.1:1935/live/
  • Stream Key: stream

Method 4: Built-in PHP Push Client

php pusher.php test.mp4 http://127.0.0.1:8501/live/stream

4. Quick Live Viewing

Browser access: http://127.0.0.1/index.html

Push/Pull Stream Address Specification

Push Stream Addresses (Unified Format for OBS/FFmpeg/PHP/Web)

Protocol Standard Format Example
RTMP rtmp://host:1935/{app}/{stream} rtmp://127.0.0.1:1935/live/stream
HTTP-FLV http://host:8501/{app}/{stream} http://127.0.0.1:8501/live/stream
WebSocket-FLV ws://host:8501/{app}/{stream} ws://127.0.0.1:8501/live/stream

Field constraints: {app} application name and {stream} channel name may only contain English letters, numbers, and underscores; special characters and Chinese are prohibited.

Live & VOD Access Addresses

Real-Time Live Playback Addresses

Protocol Address Use Case
RTMP rtmp://127.0.0.1:1935/live/stream ffplay, desktop professional players
HTTP-FLV http://127.0.0.1:8501/live/stream.flv Low-latency live streaming on PC browsers
WebSocket-FLV ws://127.0.0.1:8501/live/stream.flv Native WebSocket MSE playback in browsers
HLS-TS http://127.0.0.1:80/hls/live/stream/index.m3u8 Mobile devices, WeChat built-in browser
HLS-FMP4 (Mixed A/V) http://127.0.0.1:80/mp4/live/stream/output_merge/index.m3u8 Mainstream desktop browsers, mobile, WeChat built-in browser, ffplay, VLC, etc.
HLS-FMP4 (Separate A/V) http://127.0.0.1:80/mp4/live/stream/output_separate/index.m3u8 Mainstream desktop browsers, mobile, WeChat built-in browser, ffplay, VLC, etc.

Recorded VOD Playback Addresses

Recorded files are persistently stored in the project root directory, automatically generated upon stream end:

File Type Storage Path Access Example
Standard MP4 file mp4/live/stream/index.mp4 http://127.0.0.1/mp4/live/stream/index.mp4
Raw FLV recording flv/live/stream/index.flv http://127.0.0.1/flv/live/stream/index.flv
HLS TS segment dir hls/live/stream/index.m3u8 http://127.0.0.1:80/hls/live/stream/index.m3u8
HLS-FMP4 Mixed A/V mp4/live/stream/output_merge/index.m3u8 http://127.0.0.1:80/mp4/live/stream/output_merge/index.m3u8
HLS-FMP4 Separate A/V mp4/live/stream/output_separate/index.m3u8 http://127.0.0.1:80/mp4/live/stream/output_separate/index.m3u8

Note: Standard MP4 files are only automatically generated from FLV recordings when multi-process and FLV recording are both enabled. You can also manually convert FLV to MP4 using the xiaosongshu/flv2mp4 toolkit.

Page/Script Usage Guide

Live/VOD Playback Pages

Page File Function Access URL
index.html HTTP-FLV low-latency live player http://127.0.0.1/index.html
play.html HLS mobile-optimized player http://127.0.0.1/play.html
mp4.html MP4 VOD player http://127.0.0.1/mp4.html
video.html FLV VOD player http://127.0.0.1/video.html
play_merge.html fMP4 fragmented live/VOD player (native JS) http://127.0.0.1/play_merge.html
mse.html fMP4 fragmented live/VOD player (hls.js) http://127.0.0.1/mse.html

Web Push Pages

Page File Function Access URL
push.html Browser screen capture push (WS-FLV) http://127.0.0.1/push.html
flv_push.html Local MP4/FLV file loop push http://127.0.0.1/flv_push.html
push_merge.html Multi-stream merge push http://127.0.0.1/push_merge.html
push_transcode.html Frontend multi-bitrate transcoding push for weak networks http://127.0.0.1/push_transcode.html

PHP Built-in Push/Pull Client Scripts

Script Function Example Command
pusher.php Command-line file push client php pusher.php video.mp4 http://127.0.0.1:8501/live/stream
puller.php Command-line pull recording client php puller.php http://127.0.0.1:8501/live/stream.flv output.flv

PHP Built-in Relay Client Scripts

Script Function Example Command
forward.php Command-line live data relay client php forward.php ws://127.0.0.1:8501/a/b.flv rtmp://127.0.0.1:1935/c/d

PHP Built-in Gateway Client Scripts

Script Function Example Command
fileGateway.php Command-line file gateway client php fileGateway.php 0.0.0.0 8100
flvGateway.php Command-line FLV gateway client php flvGateway.php 8080 http://127.0.0.1:8501

PHP Live Startup Scripts

Script Function Example Command
server.php Command-line live service startup php server.php

Project Directory Structure

rtmp_server/
β”œβ”€β”€ config/                     # Global config: ports, multi-process, recording, auth
β”œβ”€β”€ flv/                        # FLV raw stream recording storage
β”œβ”€β”€ mp4/                        # fMP4 segments & merged MP4 after stream ends
β”œβ”€β”€ hls/                        # HLS TS segments, m3u8 index files
β”œβ”€β”€ MediaServer/                # RTMP/FLV/WS-FLV core protocol stack, session management
β”œβ”€β”€ Root/                       # Low-level async I/O, Socket event driver
β”œβ”€β”€ record/                     # Client-side static page assets
β”œβ”€β”€ server.php                  # RTMP origin server entry point
β”œβ”€β”€ flvGateway.php              # FLV live distribution gateway
β”œβ”€β”€ fileGateway.php             # HLS/MP4/static resources HTTP gateway
β”œβ”€β”€ forward.php                 # Live relay client
β”œβ”€β”€ pusher.php                  # PHP push client
β”œβ”€β”€ puller.php                  # PHP pull client
β”œβ”€β”€ encode.php                  # FLV to HLS multi-bitrate client
β”œβ”€β”€ watermark.php               # Watermark generation tool
β”œβ”€β”€ *.html                      # All Web push/pull/playback pages
β”œβ”€β”€ docker-compose.yml          # Docker one-click deployment config
└── LICENSE                     # Apache 2.0 license file

Overall System Architecture

                                    【External Pushers】OBS / FFmpeg / Web
                                         β”‚
                                   RTMP(1935) / HTTP-FLV/WS-FLV(8501) Push Access
                                         β”‚
                                         β–Ό
╔══════════════════════════════════════════════════════════════════════════════════════╗
β•‘                         RTMP Origin Server (Stream Production Core)                 β•‘
β•‘                                                                                      β•‘
β•‘  πŸ“₯ Push/Pull Access: RTMP / HTTP-FLV / WS-FLV, built-in auth validation           β•‘
β•‘  πŸ”„ Protocol Transmuxing: Output HTTP-FLV / WS-FLV / HLS / fMP4 / MP4              β•‘
β•‘  πŸ’Ύ Parallel Recording Tasks (non-blocking, independently toggleable)               β•‘
β•‘        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                            β•‘
β•‘        β”‚FLV Record β”‚fMP4 Seg. β”‚HLS Seg. β”‚                                            β•‘
β•‘        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                            β•‘
β•‘  πŸ“€ Live Output: HTTP-FLV, WS-FLV, HLS live streams                                 β•‘
β•‘  πŸ“¦ VOD Assets: fMP4 segments cached, merged to MP4 after stream ends               β•‘
β•‘  πŸ“ Built-in HTTP static service (port 80): direct page/VOD access, no gateway neededβ•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   β”‚                   β”‚
β–Ό                   β–Ό                   β–Ό
HTTP-FLV Live     HLS Static Segments  fMP4 Static Segments
β”‚                   β”‚                   β”‚
β–Ό                   β–Ό                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ FLV Gateway β”‚    β”‚       Static File Gateway Cluster        β”‚
β”‚   Cluster   β”‚    β”‚    (fileGateway)                        β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚    β”‚    Hosts: HLS/fMP4/MP4/FLV/web assets  β”‚
β”‚ β”‚Level 1   β”‚ β”‚    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚ β”‚(port8080)β”‚ β”‚    β”‚ β”‚Node1  β”‚ β”‚Node2  β”‚ β”‚Node3  β”‚         β”‚
β”‚ β””β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚    β”‚ β”‚(8100) β”‚ β”‚(8101) β”‚ β”‚(8102) β”‚         β”‚
β”‚     β”‚       β”‚    β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”€β”€β”˜         β”‚
β”‚ β”Œβ”€β”€β”€β”΄β”€β”€β”€β”   β”‚    β”‚    β”‚        β”‚        β”‚                 β”‚
β”‚ β–Ό   β–Ό   β–Ό   β”‚    β”‚    β–Ό        β–Ό        β–Ό                 β”‚
β”‚ β”Œβ”€β” β”Œβ”€β” β”Œβ”€β” β”‚    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚ β”‚Sβ”‚ β”‚Sβ”‚ β”‚Sβ”‚ β”‚    β”‚ β”‚End-user Players                β”‚   β”‚
β”‚ β”‚1β”‚ β”‚2β”‚ β”‚3β”‚ β”‚    β”‚ β”‚MSE/HLS/ffplay/browsers         β”‚   β”‚
β”‚ β””β”¬β”€β”˜ β””β”¬β”€β”˜ β””β”¬β”€β”˜ β”‚    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”‚    β”‚    β”‚   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚  β–Ό    β–Ό    β–Ό   β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚Live Viewersβ”‚ β”‚
β”‚ β”‚FLV Players β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Architecture Details

  1. Origin Server (Sole Stream Producer) All external push streams are ingested here, completing protocol parsing, authentication, multi-format transmuxing, and parallel recording. FLV, fMP4, and HLS recording threads are completely isolated and non-blocking. For low-concurrency scenarios, the built-in port 80 static service can be used directly without additional gateways.

  2. FLV Live Distribution Gateway No transcoding β€” pure forwarding with GOP keyframe caching for instant playback. Supports horizontal scaling and multi-level cascading (max 2 levels recommended for production; more levels increase latency). Linux epoll for high concurrency; Windows for testing only. In high-concurrency scenarios, all player pull requests go through the gateway to reduce connection pressure on the origin server.

  3. Static File Gateway Cluster Dedicated hosting for HLS, MP4, FLV, and frontend pages to separate read/write operations. Required for large-scale VOD scenarios to prevent the origin from being overwhelmed by file I/O.

  4. Integrated Live Toolkit The project supports pure PHP push, pull, and relay clients, as well as web-based push, playback, transcoding, and stream merging. Supports both single-process and multi-process modes, plus the xiaosongshu/flv2mp4 media toolkit.

Concurrency Deployment Recommendations

Scale Recommended Setup
Low (< 1,000 viewers) Origin server only (server.php), use built-in ports 80 and 8501, no gateways
Medium (1,000 ~ 5,000 viewers) Origin + single-layer FLV gateway cluster + single-layer static file gateway cluster, with Nginx load balancing
High / Large events (>5,000 viewers) Origin + multi-layer FLV/static gateway clusters with frontend load balancing; for 10k+ events, must use commercial CDN edge distribution β€” never serve all traffic from a single server

Port Constants Configuration

Edit config/app.php to adjust global service ports:

/** HTTP-FLV / WebSocket-FLV main service port */
define('BASE_FLV_PORT', 8501);
/** RTMP standard port 1935 */
define('BASE_RTMP_PORT', 1935);
/** Built-in static web/VOD HTTP port */
define('BASE_WEB_PORT', 80);

Recording Task Toggle Configuration

config/app.php independently controls three recording tasks:

define('FLV_TO_RECORD', true);   // Enable raw FLV recording
define('FLV_TO_MP4', true);      // Enable fMP4 segmentation
define('FLV_TO_HLS', true);      // Enable HLS TS segmentation

Multi-Process Worker Configuration (IPC Stream Sync Core)

Principle

In PHP CLI multi-process mode, each Worker has isolated memory. When one process receives a push stream, others cannot access it, so IPC (Inter-Process Communication) is required to sync live streams. This project uses a custom TCP Socket-based IPC over traditional methods like shared memory or pipes: it allocates a set of internal communication ports, and the receiving Worker actively forwards the stream data to all other Workers via a built-in TCP client, ensuring full stream data sharing across all processes.

Configuration in config/app.php

/** Master switch: enable multi-process Worker mode */
define('ENABLE_MULTI_PROCESS', true);
/** Worker count β€” recommended not to exceed CPU cores */
define('WORKER_COUNT', 3);
/** Starting port for inter-process TCP communication, auto-allocates 8502, 8503... */
define('COPY_PORT_START', 8502);

When multi-process is disabled (ENABLE_MULTI_PROCESS=false), worker count and IPC port settings are ignored, and the service runs in single-process mode without IPC sync.

Port Load Balancing Rules

  1. Linux: Supports port reuse β€” multiple Workers can listen on the same 8501 FLV port. The kernel distributes player connections across Workers automatically.
  2. Windows: Supports SO_REUSEADDR, but new TCP connections are always assigned to the first process that bound to 8501, preventing native load balancing. Use Nginx to reverse-proxy internal ports (8502+) for load distribution.
  3. Internal IPC ports are externally accessible for pull requests, useful for manual load balancing on Windows.

Platform Performance Notes

  • Linux: epoll I/O model β€” single process supports thousands of concurrent connections; multi-process makes full use of multi-core CPUs. Production environment preferred.
  • Windows: select model has low concurrency limits (~256 connections per process) β€” for local development only. Do not deploy in production on Windows.

Push Stream Authentication Configuration

Description

Prevents unauthorized streams from overwriting live channels β€” only push requests with valid stream keys are allowed. Playback pull auth is not currently built-in; developers can implement referer/token validation at the gateway or reverse-proxy layer.

Configuration file config/auth.php:

<?php
return [
    'enabled' => false, // Master auth switch
    'publish' => [
        'require_auth' => true, // Require key for push streams
        'stream_keys' => [
            'live_123456',
            'stream_key_abc',
        ],
    ],
    'global' => [
        'allowed_apps' => ['live'], // Allowed app names
        'deny_apps' => [],
    ],
];

Authenticated Push Address Format

Include key via URL parameter:

  1. RTMP
ffmpeg -re -i video.mp4 -f flv rtmp://127.0.0.1:1935/live/stream?key=live_123456
  1. OBS Stream Key: stream?key=live_123456
  2. HTTP-FLV
ffmpeg -re -i video.mp4 -f flv http://127.0.0.1:8501/live/stream?key=live_123456
  1. WS-FLV PHP client
php pusher.php test.flv "ws://127.0.0.1:8501/live/stream?key=live_123456"

Security Best Practices

  1. Replace default keys with random strings of 32+ characters.
  2. Enable HTTPS/WSS in public environments to prevent plaintext key interception.
  3. Rotate stream keys periodically to reduce leakage risk.
  4. Authentication is disabled by default β€” enable it if needed.

Note: Any changes to the above configs require a service restart to take effect.

FLV Live Distribution Gateway

Overview

Lightweight forwarding service that pulls HTTP-FLV/WS-FLV streams from upstream origin, caches GOP keyframes for instant playback, and supports horizontal scaling and multi-level cascading to share origin load. The gateway supports pulling from HTTP-FLV or WS-FLV sources and uniformly provides both HTTP-FLV and WS-FLV playback addresses.

Startup Commands

# Basic single instance
php flvGateway.php 8080 http://127.0.0.1:8501
php flvGateway.php 8080 ws://127.0.0.1:8501

# Horizontal scaling multiple instances
php flvGateway.php 8080 http://127.0.0.1:8501
php flvGateway.php 8081 http://127.0.0.1:8501
php flvGateway.php 8082 ws://127.0.0.1:8501

# Multi-level cascading (max 2 levels recommended)
php flvGateway.php 8080 http://127.0.0.1:8501    # Level 1
php flvGateway.php 8081 http://127.0.0.1:8080     # Level 2

# Linux background silent mode
php flvGateway.php 8080 http://127.0.0.1:8501 > /dev/null 2>&1 &

Gateway Playback Address Format

http://gateway_ip:port/{app}/{stream}.flv
ws://gateway_ip:port/{app}/{stream}.flv

Example: http://127.0.0.1:8080/live/stream.flv

Static File HTTP Gateway

Overview

A standalone HTTP service for static resources, hosting HLS, MP4, FLV, and frontend pages. Separates file I/O from live streaming to improve VOD stability under high concurrency.

Startup Commands

# Single instance
php fileGateway.php 0.0.0.0 8100

# Horizontal scaling
php fileGateway.php 0.0.0.0 8100
php fileGateway.php 0.0.0.0 8101
php fileGateway.php 0.0.0.0 8102

# Linux background mode
php fileGateway.php 0.0.0.0 8100 > /dev/null 2>&1 &

Nginx Load Balancing Example

upstream filegateway_cluster {
    server 127.0.0.1:8100;
    server 127.0.0.1:8101;
    server 127.0.0.1:8102;
}
server {
    listen 80;
    server_name media.example.com;
    location ~* \.(m3u8|ts|mp4|m4s|flv|html|css|js)$ {
        proxy_pass http://filegateway_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Resource Access Examples

http://127.0.0.1:8100/index.html
http://127.0.0.1:8100/hls/live/stream/index.m3u8
http://127.0.0.1:8100/mp4/live/stream/index.mp4

Multi-Method Pull/Push Stream Access Tutorial

RTMP Push

OBS, FFmpeg, and PHP clients all support standard RTMP: rtmp://host:1935/{app}/{stream}

HTTP-FLV Push

Suitable for command-line or automated push: http://host:8501/{app}/{stream}

WebSocket-FLV Push

Native browser push with latency as low as 50ms; use the built-in push.html page.

PHP Pull Script

For server-side backup and cross-server relay:

php puller.php http://127.0.0.1:8501/live/stream.flv output.flv
php puller.php ws://127.0.0.1:8501/live/stream.flv output.flv

Live Relay Tutorial

This project supports live stream relaying to multiple servers over rtmp/ws-flv/http-flv. See forward.php for details. Example:

php forward.php http://127.0.0.1:8501/a/b.flv "rtmp://127.0.0.1:1935/c/d,ws://127.0.0.1:8501/c/e,http://127.0.0.1:8501/c/f" 

This relays http://127.0.0.1:8501/a/b.flv to rtmp://127.0.0.1:1935/c/d, ws://127.0.0.1:8501/c/e, and http://127.0.0.1:8501/c/f. You can also relay to any platform supporting RTMP, WS-FLV, or HTTP-FLV.

Engineering Recommendations

pusher.php/puller.php/forward.php can be integrated into custom scripts for automated pull-relay and backup recording, creating a complete PHP live streaming workflow without third-party tools.

100K+ Concurrent Cluster Deployment Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         【Layer 1: Multi-Pusher Layer】                                 β”‚
β”‚                                                                                         β”‚
β”‚     Streamer A (OBS/Web/FFmpeg)   Streamer B (OBS/Web/FFmpeg)   Streamer N (...)      β”‚
β”‚            β”‚                              β”‚                             β”‚               β”‚
β”‚      β”Œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”                 β”Œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”                β”Œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”        β”‚
β”‚      β–Ό     β–Ό     β–Ό                 β–Ό     β–Ό     β–Ό                β–Ό     β–Ό     β–Ό        β”‚
β”‚    [Node1] [Node2] [Node3]       [Node1] [Node2] [Node3]      [Node1] [Node2] [Node3] β”‚
β”‚     (Push to multiple origin nodes simultaneously for redundancy)                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                          β”‚
                                          β”‚ RTMP/HTTP-FLV/WS-FLV Push Access
                                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      【Layer 2: Origin Node Cluster (Stream Production)】               β”‚
β”‚                                                                                         β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚    β”‚  Origin A   β”‚   β”‚  Origin B   β”‚   β”‚  Origin C   β”‚   β”‚  Origin D   β”‚             β”‚
β”‚    β”‚ server.php  β”‚   β”‚ server.php  β”‚   β”‚ server.php  β”‚   β”‚ server.php  β”‚             β”‚
β”‚    β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚             β”‚
β”‚    β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚             β”‚
β”‚    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚          β”‚                 β”‚                 β”‚                 β”‚                      β”‚
β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
β”‚                   β”‚                                   β”‚                               β”‚
β”‚              β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                         β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                          β”‚
β”‚              β”‚ forward β”‚                         β”‚ forward β”‚  ← Auto-sync streams      β”‚
β”‚              β”‚ sync    β”‚                         β”‚ sync    β”‚                          β”‚
β”‚              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                         β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜                          β”‚
β”‚                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                               β”‚
β”‚                                  β”‚                                                    β”‚
β”‚                    (All origins back each other up; any failure continues service)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                                   β”‚ forward pulls from origin, pushes to edge
                                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     【Layer 3: Edge Node Cluster (Distribution & Cache)】               β”‚
β”‚                                                                                         β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
β”‚    β”‚  Edge X     β”‚   β”‚  Edge Y     β”‚   β”‚  Edge Z     β”‚   β”‚  Edge W     β”‚             β”‚
β”‚    β”‚ server.php  β”‚   β”‚ server.php  β”‚   β”‚ server.php  β”‚   β”‚ server.php  β”‚             β”‚
β”‚    β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚   β”‚ (multi-proc)β”‚             β”‚
β”‚    β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚   β”‚ rec/seg     β”‚             β”‚
β”‚    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
β”‚          β”‚                 β”‚                 β”‚                 β”‚                      β”‚
β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
β”‚                   β”‚                                   β”‚                               β”‚
β”‚              β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                         β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”                          β”‚
β”‚              β”‚ forward β”‚                         β”‚ forward β”‚  ← Pull from origin, cache β”‚
β”‚              β”‚ sync    β”‚                         β”‚ sync    β”‚                          β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                                                                         β”‚
β”‚  β˜… Any node can be upgraded to origin (accept push) or downgraded to edge (pull only)  β”‚
β”‚  β˜… All nodes record independently for multi-copy backup                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚                           β”‚
                     β–Ό                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   【Layer 4: Gateways】     β”‚ β”‚   【Layer 4: Gateways】     β”‚
β”‚                            β”‚ β”‚                            β”‚
β”‚     flvGateway Cluster     β”‚ β”‚     fileGateway Cluster    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚G1   β”‚ β”‚G2   β”‚ β”‚G3   β”‚ β”‚ β”‚  β”‚G1   β”‚ β”‚G2   β”‚ β”‚G3   β”‚ β”‚
β”‚  β””β”€β”€β”¬β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜ β”‚ β”‚  β””β”€β”€β”¬β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜ β””β”€β”€β”¬β”€β”€β”˜ β”‚
β”‚     β”‚       β”‚       β”‚     β”‚ β”‚     β”‚       β”‚       β”‚     β”‚
β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”˜     β”‚ β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
β”‚             β”‚             β”‚ β”‚             β”‚             β”‚
β”‚   (HTTP-FLV/WS-FLV)       β”‚ β”‚ (HLS/MP4/FLV/VOD/Static) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚                             β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        【Layer 5: Viewers】                                              β”‚
β”‚                                                                                         β”‚
β”‚   PC Browser (MSE/FLV.js)    Mobile (HLS)    ffplay/Players   WebSocket Player        β”‚
β”‚                                                                                         β”‚
β”‚   β˜… Viewers connect to nearest edge gateway via DNS/Nginx/GSLB load balancing          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Architecture Design Notes

1. High Availability Push Layer (Disaster Recovery)

  • Multi-path push: Streamers push to multiple origin nodes simultaneously; if one fails, others continue serving with zero viewer impact.
  • Auto failover: OBS/FFmpeg can configure backup push addresses for primary-backup switching; Web clients can push via JavaScript to multiple destinations.

2. Origin Node Cluster (Stream Production Core)

  • Active-active deployment: All origin nodes are active, receive pushes, and sync streams via forward.php, ensuring each node has a full stream copy.
  • Auto failover: Any origin failure triggers automatic reconnection of sync links; other nodes continue service without interruption.
  • Parallel recording: Each origin node independently records FLV/fMP4/HLS, creating multiple backups to prevent single-point storage loss.

3. Edge Node Cluster (Distribution & Cache)

  • Proximity pulling: Edge nodes pull from origin via forward.php and cache GOP keyframes for low-latency instant playback.
  • Elastic scaling: Add or remove edge nodes dynamically based on load.
  • Flexible roles: Any node can be promoted to origin (accept pushes) or demoted to edge (pull only) by configuration.

4. Gateway Distribution Layer

  • flvGateway Cluster: Dedicated to HTTP-FLV/WS-FLV live streams β€” no transcoding, pure forwarding with GOP caching for instant playback. Supports cascading and horizontal scaling.
  • fileGateway Cluster: Dedicated to HLS segments, MP4 VOD, static pages β€” isolates file I/O from live streaming.

5. Viewer Clients

  • Multi-protocol coverage: RTMP, HTTP-FLV, WS-FLV, HLS β€” supports all platforms.
  • Smart routing: DNS round-robin, Nginx reverse proxy, or GSLB to route viewers to the nearest/lowest-load edge node.

6. Data Flow

  1. Push: Streamer β†’ (multi-path) β†’ Origin cluster β†’ forward syncs to all origins.
  2. Pull (Edge): Edge β†’ forward pulls from origin β†’ caches β†’ serves local viewers.
  3. Playback: Viewer β†’ Load balancer β†’ flvGateway/fileGateway β†’ Edge (or Origin) β†’ stream data.
  4. Recording: All nodes record per configuration; merged to MP4 for VOD after stream end.

7. Disaster Recovery & Backup

  • Node-level: Any node failure triggers automatic reconnection to other live nodes.
  • Region-level: If entire data center fails, DNS can switch to a backup site (requires multiple clusters).
  • Recording backup: Each node stores recordings independently; for critical streams, multiple nodes can record simultaneously.

8. Scalability & Concurrency

  • Horizontal scaling: All layers support adding nodes without restart.
  • 100K+ concurrency: Edge nodes + gateways scale horizontally; with CDN edge acceleration, supports 100K+ concurrent viewers (bandwidth and server resources permitting).
  • Performance: Linux epoll enables thousands of connections per node (varies by server config); multi-node clusters scale linearly.

9. Deployment Recommendations

  • Node-to-node data sync is handled by the built-in forward.php relay client. It supports pulling from any RTMP/HTTP-FLV/WS-FLV source and pushing to one or multiple targets, with authentication parameters (e.g., key) supported. Developers can write scheduling scripts based on actual network topology and business needs β€” integrating health checks, load balancing policies, or business rules β€” to dynamically configure pull sources, target lists, and forwarding parameters for automated stream sync. Origin/edge role switching also relies on external scheduling logic: monitor node metrics (CPU, memory, active connections, push count, etc.) or external traffic distribution policies to trigger script-based role adjustments for elastic scaling, failover, and disaster recovery. The entire scheduling system can be customized for highly flexible production-grade deployment.

Multi-Bitrate Support

This project provides built-in multi-bitrate transcoding capabilities, supporting the conversion of Baseline Profile FLV files into multi-resolution HLS streams to adapt to different network environments and mobile devices.

⚠️ Performance Notice

  • The current multi-bitrate module is implemented in pure PHP and performance is limited. It is intended only for small file offline transcoding or functional verification.
  • Due to the computationally intensive nature of H.264 re-encoding, which requires significant processing time, it is strictly prohibited to use this module in production environments for real-time live streaming. For professional adaptive bitrate transcoding, please use mature tools such as FFmpeg.
  • This feature depends on the xiaosongshu/flv2mp4 toolkit, which is installed with this project β€” no additional setup required.

Usage

For detailed configuration, please refer to the encode.php example file. Run the following command to transcode FLV to HLS:

php encode.php
  • πŸ“Œ Version Requirement: This feature requires xiaosongshu/flv2mp4 version >= 1.4.4.
  • πŸ“Œ The xiaosongshu/flv2mp4 toolkit supports re-encoding for FLV/MP4 and FLV to HLS transcoding, as well as watermark overlay. For more usage, please refer to the toolkit documentation.

Use Cases

Scenario Recommended
Local testing / functional verification βœ… Recommended
Small file offline transcoding (< 10MB) βœ… Acceptable
Real-time live stream transcoding ❌ Not recommended
High-concurrency / large-scale production ❌ Strictly prohibited

Note: This module is for learning and evaluation purposes only. Please do not use it in production environments. For high-performance transcoding solutions, consider using FFmpeg or professional transcoding services.

Watermark Tool

You can use the built-in tool to generate text watermarks. For detailed configuration, please refer to watermark.php. Run the following command to generate a watermark file:

php watermark.php

A sample watermark file watermark_80x16.yuv is already prepared for you.

FAQ

Q1: Missing event extension on Windows?

The event extension is not available on Windows β€” the service automatically uses the select I/O model. Just install the sockets extension and it will run normally.

Q2: How to confirm the service started successfully?

Successful startup is indicated by three log lines in the terminal: RTMP 1935, FLV 8501, HTTP static 80.

Q3: Push works but playback is laggy/stuttering?

  1. Push bitrate/resolution is too high β€” reduce bitrate/framerate for testing.
  2. Server CPU is maxed out β€” enable multi-process to use all cores.
  3. High concurrency without FLV gateway β€” many player connections are consuming origin resources.
  4. Insufficient server upstream bandwidth β€” limit concurrent viewers.

Q4: How to stop the service?

Press Ctrl + C in the terminal to send a termination signal, or simply close the terminal window.

Q5: Which third-party push software is supported?

Fully compatible with all standard RTMP clients: OBS Studio, FFmpeg, xSplit, and mobile RTMP SDKs.

License

This project is released under the Apache License 2.0. The software is provided "AS IS", without warranty of any kind. The developer assumes no liability for direct, indirect, or consequential damages arising from the use of this software. For full terms, see the LICENSE file in the project root.

Companion Toolkit

The underlying codec and container conversion capabilities have been extracted into a separate toolkit: xiaosongshu/flv2mp4 It provides FLV/MP4/fMP4/HLS interconversion, standalone push/pull clients, and gateway components, and can be used independently in third-party PHP projects.

Contact