A lightweight RTMP live streaming server built with pure PHP

php dev.to

RTMP Server

A lightweight RTMP live streaming server built with pure PHP. No Nginx or other streaming software required.

✨ Features

  • 🎥 RTMP Push/Pull - Standard RTMP protocol support
  • 📡 HTTP-FLV / WebSocket-FLV - Low-latency playback in browsers
  • 🧩 HLS Output - Automatic M3U8 + TS segment generation, mobile-friendly
  • 💾 Auto Recording - Automatic recording during streaming, saves as both MP4 and FLV files
  • 🖥️ Built-in Players - Multiple web playback pages, ready to use out of the box
  • 🐳 Docker Support - One-click development environment, no manual extension configuration
  • Pure PHP Implementation - No need for Nginx, SRS, or other streaming servers

📋 Requirements

  • PHP >= 8.1 (CLI mode)
  • PHP extensions enabled:
    • sockets
    • pcntl (optional for Linux/macOS)

🚀 Quick Start

Installation

composer create-project xiaosongshu/rtmp_server
cd rtmp_server
Enter fullscreen mode Exit fullscreen mode

Start Server

php server.php
Enter fullscreen mode Exit fullscreen mode

Stop Server

System Command
Windows Ctrl + C
Linux / macOS `ps aux \

🔧 Configuration

Port Configuration

Default ports (modifiable in {% raw %}server.php):

Port Protocol Purpose
1935 RTMP Push/Pull streaming
8501 HTTP/WebSocket FLV playback (live)
80 HTTP HLS playback + Web pages + static file replay

📡 Pushing Streams

Push URL

rtmp://127.0.0.1:1935/{app}/{channel}
Enter fullscreen mode Exit fullscreen mode
  • {app}: Application name, e.g., live
  • {channel}: Channel name, e.g., stream
  • Only English letters and numbers are supported

Streaming Tools

Using OBS Studio

  1. Download OBS Studio
  2. Settings → Stream → Custom RTMP Server
  3. Server URL: rtmp://127.0.0.1:1935/live
  4. Stream Key: stream
  5. Start streaming

Using FFmpeg

ffmpeg -re -stream_loop -1 -i "video.mp4" \
  -vcodec h264 -acodec aac -f flv \
  rtmp://127.0.0.1:1935/live/stream
Enter fullscreen mode Exit fullscreen mode

Parameter Description:

  • -re: Read input at native frame rate
  • -stream_loop -1: Loop infinitely
  • -i: Input video file
  • -vcodec h264: H.264 video codec
  • -acodec aac: AAC audio codec
  • -f flv: FLV container format

📺 Pulling & Playback Guide

Live Stream URLs (Real-time Playback)

Protocol URL Description
RTMP rtmp://127.0.0.1:1935/live/stream Native RTMP protocol
HTTP-FLV http://127.0.0.1:8501/live/stream.flv Low-latency browser playback
WebSocket-FLV ws://127.0.0.1:8501/live/stream.flv WebSocket protocol
HLS http://127.0.0.1:80/hls/live/stream/index.m3u8 Recommended for mobile

Built-in Web Player Pages

After starting the server, open the following URLs in your browser (replace with your actual stream path):

🔴 Live Streaming Test Pages

Page URL Description
FLV Live Player http://127.0.0.1:80/index.html HTTP-FLV live stream with autoplay (first click required)
HLS Live Player http://127.0.0.1:80/play.html HLS live stream, compatible with mobile browsers

Note: The default stream URL is rtmp://127.0.0.1:1935/live/stream, which corresponds to stream name live/stream in the page. Modify the stream address in the page if using a different channel name.

🔵 Static File Playback Pages

Page URL Description
MP4 Playback http://127.0.0.1:80/mp4.html Play recorded MP4 files (auto-generated during streaming)
FLV Playback http://127.0.0.1:80/video.html Play recorded FLV files (auto-generated during streaming)

Note: Recorded files are saved in ./mp4/ and ./flv/ directories. Modify the video path in the page to play specific files.

💾 Auto Recording

How It Works

  1. Streaming starts → Recording begins automatically
  2. Streaming ends → Saves as both MP4 and FLV files
  3. MP4 file location: ./mp4/{app}/{channel}/{channel}_full.mp4
  4. FLV file location: ./flv/{app}/{channel}/{random_id}.flv

Notes

  • ✅ Recorded MP4 files use standard fMP4 format, supporting drag-to-seek playback
  • ✅ Recorded FLV files use standard FLV format, playable with VLC and other players
  • ⚠️ Streaming with the same path will overwrite previous recording files
  • ⚠️ The server does not automatically delete recording files; clean up as needed

FLV to MP4 Conversion (Manual)

To manually convert a recorded FLV file to MP4 format:

<?php
require_once __DIR__ . '/vendor/autoload.php';
ini_set('memory_limit', '512M');

// Path to the FLV file to convert
$file = __DIR__ . "/test.flv";

// Output directory for the converted MP4
$outputDir = __DIR__ . "/output";

try {
    $res = \Xiaosongshu\Flv2mp4\Client::run($file, $outputDir);
    echo "Conversion successful: {$res}";
} catch (\Exception $e) {
    echo "Conversion failed: " . $e->getMessage();
}
Enter fullscreen mode Exit fullscreen mode

Tip: The server automatically converts live streams to MP4 during streaming, so manual conversion is usually unnecessary.

📁 Directory Structure

rtmp_server/
├── mp4/               # MP4 recording files
│   └── {app}/{name}/  # Organized by app/channel name
├── flv/               # FLV recording files
│   └── {app}/{name}/  # Organized by app/channel name
├── hls/               # HLS segment files
│   └── {app}/{name}/  # M3U8 + TS segments
├── MediaServer/       # Core server code
├── ../                # Other core service code
├── server.php         # Server entry point
├── index.html         # FLV live player page
├── play.html          # HLS live player page
├── mp4.html           # MP4 playback page
├── video.html         # FLV playback page
└── README.md          # Project documentation
Enter fullscreen mode Exit fullscreen mode

❓ FAQ

1. Missing Extensions Error on Startup

Cause: PHP CLI mode and FPM mode may have different extension configurations.

Solution:

  • Run php -m to check installed extensions
  • Install missing extensions (e.g., sockets)
  • Using Docker environment avoids this issue

2. Port Already in Use

Solution:

  • Check port usage: netstat -ano | findstr <port>
  • Modify port settings in server.php
  • Update port settings in player pages accordingly

3. Player Page Cannot Connect

Solution:

  • Ensure the server is running and the port is not blocked by firewall
  • Verify the playback URL in the page matches the actual stream path
  • If using a different port, update the port number in the page

4. Recording File Overwrite

Symptom: Streaming with the same path overwrites previous recording files.

Solution:

  • Use different channel names when streaming
  • Or implement custom cleanup and backup logic for recording files

📄 License

This project is for learning and communication purposes only. Commercial use is not permitted.

⚠️ Disclaimer

  • Some project code originates from the internet; please contact us if there are copyright issues
  • This project is fully open source and intended for technical exchange
  • Users bear their own legal risks when using this project
  • The author is not responsible for any losses incurred from using this project

📧 Contact

For questions or suggestions, please contact via email:

📧 2723659854@qq.com

Source: dev.to

arrow_back Back to Tutorials