<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 2723659854</title>
    <description>The latest articles on DEV Community by 2723659854 (@2723659854).</description>
    <link>https://dev.to/2723659854</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3952685%2Fab75976c-201d-44f7-98c2-4ad2d7f4d224.png</url>
      <title>DEV Community: 2723659854</title>
      <link>https://dev.to/2723659854</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/2723659854"/>
    <language>en</language>
    <item>
      <title>A lightweight RTMP live streaming server built with pure PHP</title>
      <dc:creator>2723659854</dc:creator>
      <pubDate>Mon, 01 Jun 2026 02:02:37 +0000</pubDate>
      <link>https://dev.to/2723659854/a-lightweight-rtmp-live-streaming-server-built-with-pure-php-2gh4</link>
      <guid>https://dev.to/2723659854/a-lightweight-rtmp-live-streaming-server-built-with-pure-php-2gh4</guid>
      <description>&lt;h2&gt;
  
  
  RTMP Server
&lt;/h2&gt;

&lt;p&gt;A lightweight RTMP live streaming server built with pure PHP. No Nginx or other streaming software required.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ Features
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  📋 Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP &amp;gt;= 8.1 (CLI mode)&lt;/li&gt;
&lt;li&gt;PHP extensions enabled:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sockets&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pcntl&lt;/code&gt; (optional for Linux/macOS)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project xiaosongshu/rtmp_server
&lt;span class="nb"&gt;cd &lt;/span&gt;rtmp_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php server.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stop Server
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Ctrl + C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux / macOS&lt;/td&gt;
&lt;td&gt;`ps aux \&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  🔧 Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Port Configuration
&lt;/h3&gt;

&lt;p&gt;Default ports (modifiable in {% raw %}&lt;code&gt;server.php&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1935&lt;/td&gt;
&lt;td&gt;RTMP&lt;/td&gt;
&lt;td&gt;Push/Pull streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8501&lt;/td&gt;
&lt;td&gt;HTTP/WebSocket&lt;/td&gt;
&lt;td&gt;FLV playback (live)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;HLS playback + Web pages + static file replay&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  📡 Pushing Streams
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Push URL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rtmp://127.0.0.1:1935/{app}/{channel}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;{app}&lt;/code&gt;: Application name, e.g., &lt;code&gt;live&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{channel}&lt;/code&gt;: Channel name, e.g., &lt;code&gt;stream&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Only English letters and numbers are supported&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Streaming Tools
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Using OBS Studio
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Download &lt;a href="https://obsproject.com/" rel="noopener noreferrer"&gt;OBS Studio&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Settings → Stream → Custom RTMP Server&lt;/li&gt;
&lt;li&gt;Server URL: &lt;code&gt;rtmp://127.0.0.1:1935/live&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Stream Key: &lt;code&gt;stream&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Start streaming&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Using FFmpeg
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-re&lt;/span&gt; &lt;span class="nt"&gt;-stream_loop&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"video.mp4"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-vcodec&lt;/span&gt; h264 &lt;span class="nt"&gt;-acodec&lt;/span&gt; aac &lt;span class="nt"&gt;-f&lt;/span&gt; flv &lt;span class="se"&gt;\&lt;/span&gt;
  rtmp://127.0.0.1:1935/live/stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parameter Description:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-re&lt;/code&gt;: Read input at native frame rate&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-stream_loop -1&lt;/code&gt;: Loop infinitely&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-i&lt;/code&gt;: Input video file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-vcodec h264&lt;/code&gt;: H.264 video codec&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-acodec aac&lt;/code&gt;: AAC audio codec&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-f flv&lt;/code&gt;: FLV container format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📺 Pulling &amp;amp; Playback Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Live Stream URLs (Real-time Playback)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTMP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rtmp://127.0.0.1:1935/live/stream&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Native RTMP protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP-FLV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:8501/live/stream.flv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Low-latency browser playback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebSocket-FLV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ws://127.0.0.1:8501/live/stream.flv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WebSocket protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/hls/live/stream/index.m3u8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Recommended for mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Built-in Web Player Pages
&lt;/h3&gt;

&lt;p&gt;After starting the server, open the following URLs in your browser (replace with your actual stream path):&lt;/p&gt;

&lt;h4&gt;
  
  
  🔴 Live Streaming Test Pages
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FLV Live Player&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/index.html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTTP-FLV live stream with autoplay (first click required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLS Live Player&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/play.html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HLS live stream, compatible with mobile browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The default stream URL is &lt;code&gt;rtmp://127.0.0.1:1935/live/stream&lt;/code&gt;, which corresponds to stream name &lt;code&gt;live/stream&lt;/code&gt; in the page. Modify the stream address in the page if using a different channel name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  🔵 Static File Playback Pages
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MP4 Playback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/mp4.html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Play recorded MP4 files (auto-generated during streaming)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FLV Playback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/video.html&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Play recorded FLV files (auto-generated during streaming)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Recorded files are saved in &lt;code&gt;./mp4/&lt;/code&gt; and &lt;code&gt;./flv/&lt;/code&gt; directories. Modify the video path in the page to play specific files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  💾 Auto Recording
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Streaming starts&lt;/strong&gt; → Recording begins automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming ends&lt;/strong&gt; → Saves as both MP4 and FLV files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MP4 file location&lt;/strong&gt;: &lt;code&gt;./mp4/{app}/{channel}/{channel}_full.mp4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FLV file location&lt;/strong&gt;: &lt;code&gt;./flv/{app}/{channel}/{random_id}.flv&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  FLV to MP4 Conversion (Manual)
&lt;/h3&gt;

&lt;p&gt;To manually convert a recorded FLV file to MP4 format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;ini_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'memory_limit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'512M'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Path to the FLV file to convert&lt;/span&gt;
&lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"/test.flv"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Output directory for the converted MP4&lt;/span&gt;
&lt;span class="nv"&gt;$outputDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"/output"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;\Xiaosongshu\Flv2mp4\Client&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$outputDir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Conversion successful: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$res&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Conversion failed: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: The server automatically converts live streams to MP4 during streaming, so manual conversion is usually unnecessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  📁 Directory Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ❓ FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Missing Extensions Error on Startup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;: PHP CLI mode and FPM mode may have different extension configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;php -m&lt;/code&gt; to check installed extensions&lt;/li&gt;
&lt;li&gt;Install missing extensions (e.g., &lt;code&gt;sockets&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Using Docker environment avoids this issue&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Port Already in Use
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check port usage: &lt;code&gt;netstat -ano | findstr &amp;lt;port&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify port settings in &lt;code&gt;server.php&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Update port settings in player pages accordingly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Player Page Cannot Connect
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the server is running and the port is not blocked by firewall&lt;/li&gt;
&lt;li&gt;Verify the playback URL in the page matches the actual stream path&lt;/li&gt;
&lt;li&gt;If using a different port, update the port number in the page&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Recording File Overwrite
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;: Streaming with the same path overwrites previous recording files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use different channel names when streaming&lt;/li&gt;
&lt;li&gt;Or implement custom cleanup and backup logic for recording files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📄 License
&lt;/h2&gt;

&lt;p&gt;This project is for learning and communication purposes only. Commercial use is not permitted.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ Disclaimer
&lt;/h2&gt;

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

&lt;h2&gt;
  
  
  📧 Contact
&lt;/h2&gt;

&lt;p&gt;For questions or suggestions, please contact via email:&lt;/p&gt;

&lt;p&gt;📧 &lt;a href="mailto:2723659854@qq.com"&gt;2723659854@qq.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>networking</category>
      <category>php</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Pure PHP hand-built RTMP live streaming server</title>
      <dc:creator>2723659854</dc:creator>
      <pubDate>Tue, 26 May 2026 13:34:13 +0000</pubDate>
      <link>https://dev.to/2723659854/pure-php-hand-built-rtmp-live-streaming-server-1l0e</link>
      <guid>https://dev.to/2723659854/pure-php-hand-built-rtmp-live-streaming-server-1l0e</guid>
      <description>&lt;h1&gt;
  
  
  rtmp_server
&lt;/h1&gt;

&lt;p&gt;A pure PHP-based RTMP live streaming server. Supports RTMP push and pull streaming, FLV streaming (HTTP/WS), HLS streaming, and includes a simple web-based player.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🎥 RTMP push &amp;amp; pull streaming&lt;/li&gt;
&lt;li&gt;📡 HTTP-FLV and WebSocket-FLV pull streaming&lt;/li&gt;
&lt;li&gt;🧩 HLS output (M3U8 + TS segments)&lt;/li&gt;
&lt;li&gt;🖥️ Built-in simple web player (FLV / HLS)&lt;/li&gt;
&lt;li&gt;🐳 Docker development environment (includes FFmpeg and PHP extensions)&lt;/li&gt;
&lt;li&gt;⚡ Pure PHP implementation – no Nginx or other streaming server required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PHP &amp;gt;= 8.1 (CLI mode)&lt;/li&gt;
&lt;li&gt;PHP extensions: &lt;code&gt;sockets&lt;/code&gt; and others (see error messages if missing)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project xiaosongshu/rtmp_server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration &amp;amp; Startup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Option 1: Using phpstudy (recommended for beginners)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Download and install &lt;a href="https://m.xp.cn/" rel="noopener noreferrer"&gt;phpstudy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Switch PHP version to &lt;strong&gt;8.1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Install required extensions via phpstudy's package manager (follow any error prompts)&lt;/li&gt;
&lt;li&gt;Navigate to the project root and start the server&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Option 2: Using Docker (recommended – includes all dependencies)
&lt;/h4&gt;

&lt;p&gt;Run the following command in the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Docker environment includes PHP 8.1, all required extensions, and FFmpeg (for pushing streams, packet inspection, or transcoding).&lt;/p&gt;

&lt;h3&gt;
  
  
  Start the Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php server.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stop the Server
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: &lt;code&gt;Ctrl + C&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux / macOS&lt;/strong&gt;: &lt;code&gt;kill -9 &amp;lt;PID&amp;gt;&lt;/code&gt; (find PID with &lt;code&gt;ps aux | grep server.php&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Port Configuration
&lt;/h2&gt;

&lt;p&gt;Default ports (can be modified in the entry file):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1935&lt;/td&gt;
&lt;td&gt;RTMP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8501&lt;/td&gt;
&lt;td&gt;FLV (HTTP &amp;amp; WebSocket)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;Web (HLS + static pages)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Push Streaming
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Push Stream URL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rtmp://127.0.0.1:1935/a/b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;a&lt;/code&gt; = application name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;b&lt;/code&gt; = stream key / channel name
(customizable; only letters and numbers allowed)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Push Streaming Tools
&lt;/h3&gt;

&lt;h4&gt;
  
  
  OBS Studio
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://obsproject.com/" rel="noopener noreferrer"&gt;obsproject.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tutorial: &lt;a href="https://www.tencentcloud.com/zh/document/product/267/31569" rel="noopener noreferrer"&gt;OBS streaming to custom RTMP server&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  FFmpeg
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-re&lt;/span&gt; &lt;span class="nt"&gt;-stream_loop&lt;/span&gt; 1 &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"movie.mp4"&lt;/span&gt; &lt;span class="nt"&gt;-vcodec&lt;/span&gt; h264 &lt;span class="nt"&gt;-acodec&lt;/span&gt; aac &lt;span class="nt"&gt;-f&lt;/span&gt; flv rtmp://127.0.0.1/a/b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parameter explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-re&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read input at native frame rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-stream_loop 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loop the input file once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-i "movie.mp4"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Input video file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-vcodec h264&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;H.264 video encoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-acodec aac&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AAC audio encoding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-f flv&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;FLV output format (required for RTMP)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Pull Streaming
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Available Pull URLs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTMP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rtmp://127.0.0.1/a/b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP-FLV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:8501/a/b.flv&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebSocket-FLV&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ws://127.0.0.1:8501/a/b.flv&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HLS (M3U8)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://127.0.0.1:80/hls/a/b/index.m3u8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Players
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.videolan.org/" rel="noopener noreferrer"&gt;VLC media player&lt;/a&gt; – Open Network Stream&lt;/li&gt;
&lt;li&gt;Built-in web player:

&lt;ul&gt;
&lt;li&gt;FLV test page: &lt;a href="http://127.0.0.1:80/index.html" rel="noopener noreferrer"&gt;http://127.0.0.1:80/index.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;HLS test page: &lt;a href="http://127.0.0.1:80/play.html" rel="noopener noreferrer"&gt;http://127.0.0.1:80/play.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Missing extensions at runtime&lt;/strong&gt;: This project runs in PHP CLI mode, which differs from traditional FPM mode. Install the required extensions based on any error messages. If using Docker, all extensions are pre-installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port conflicts&lt;/strong&gt;: Check if ports 1935, 8501, or 80 are already in use. You can modify the port configuration in the entry file. If you change the ports, remember to update the built-in player pages accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚠️ Disclaimer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Some code or materials in this project may originate from public sources. If there are any copyright concerns, please contact me for removal.&lt;/li&gt;
&lt;li&gt;This project is fully open source, intended for technical sharing and mutual progress. The author is not responsible for any legal or commercial disputes arising from individual usage.&lt;/li&gt;
&lt;li&gt;Users assume all risks associated with using this project, including but not limited to copyright and compliance issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For any questions or suggestions, feel free to reach out via email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contact
&lt;/h2&gt;

&lt;p&gt;📧 Email: &lt;a href="mailto:2723659854@qq.com"&gt;2723659854@qq.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>networking</category>
      <category>php</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
