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
Start Server
php server.php
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}
-
{app}: Application name, e.g.,live -
{channel}: Channel name, e.g.,stream - Only English letters and numbers are supported
Streaming Tools
Using OBS Studio
- Download OBS Studio
- Settings → Stream → Custom RTMP Server
- Server URL:
rtmp://127.0.0.1:1935/live - Stream Key:
stream - 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
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 namelive/streamin 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
- Streaming starts → Recording begins automatically
- Streaming ends → Saves as both MP4 and FLV files
-
MP4 file location:
./mp4/{app}/{channel}/{channel}_full.mp4 -
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();
}
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
❓ FAQ
1. Missing Extensions Error on Startup
Cause: PHP CLI mode and FPM mode may have different extension configurations.
Solution:
- Run
php -mto 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: