xiaosongshu / flv2mp4
Pure PHP native media processing library, realize FLV/MP4/HLS mutual conversion and H.264 re-encoding. Built-in live stream relay gateway, file server, multi-protocol push client: RTMP, HTTP-FLV, WebSocket-FLV, no FFmpeg external dependencies.
Requires
- php: >=8.1.0
- ext-ctype: *
- ext-curl: *
This package is auto-updated.
Last update: 2026-07-30 07:17:13 UTC
README
π¨π³ δΈζ β’ π¬π§ English
Project Overview
A lightweight media processing toolkit implemented in pure PHP 8.1+, zero external dependencies (no FFmpeg required).
Supports FLV, FMP4, MP4, HLS interconversion, live streaming gateway, pushing, pulling, relaying, and H.264 decoding + scaling + re-encoding (Baseline Profile).
π Table of Contents
- Project Overview
- Core Features
- Requirements
- Installation
- Quick Start
- Advanced Features
- Testing & Playback
- Use Cases
- H.264 Re-encoding Deep Dive
- Technical Notes
- License & Disclaimer
- Contact
π― Core Features
| Feature | Direction | Description |
|---|---|---|
| Container Conversion | FLV β MP4 / FMP4 | Generate standard MP4 or separate fMP4 segments (MSE-compatible) |
| HLS Packaging | FLV β HLS | Generate M3U8 + TS segments, compatible with hls.js, VLC, etc. |
| HLS Reversal | HLS β FLV | Merge HLS segments back into a single FLV file |
| MP4 β FLV | MP4 β FLV / FMP4 β FLV | Multi-container format interconversion |
| Live Gateway | FLV Gateway | High-performance multi-level forwarding with high concurrency support |
| Static File Service | HTTP File Gateway | Lightweight file server with directory listing support |
| Push Client | FLV / MP4 β RTMP/HTTP-FLV/WS-FLV | Push static files as pseudo-live streams |
| Pull Client | RTMP/HTTP-FLV/WS-FLV β FLV | Pull live streams and save as local FLV files |
| Relay Client | Multi-protocol input β Multi-protocol output | One pull, multiple push targets |
| H.264 Re-encoding | Decode β Scale β Encode | Baseline Profile support, core engine for multi-bitrate HLS |
Requirements
| Dependency | Description |
|---|---|
| PHP | β₯ 8.1 (CLI mode only) |
sockets extension |
Required, provides underlying Socket communication |
gd extension |
Optional, used for generating watermarks from PNG/JPG images. If not installed, it will automatically fallback to built-in bitmap font mode. |
π‘ No FFmpeg, no third-party binaries β all pure PHP.
π Installation
composer require xiaosongshu/flv2mp4
π Quick Start
<?php declare(strict_types=1); require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '512M'); $file = __DIR__ . '/test.flv'; // 1. FLV β mixed fMP4 segments \Xiaosongshu\Flv2mp4\Client::runFlv2Fmp4Mixed($file, __DIR__ . '/output_merge'); // 2. FLV β separate fMP4 segments (audio/video independent) \Xiaosongshu\Flv2mp4\Client::runFlv2Fmp4Separate($file, __DIR__ . '/output_separate'); // 3. FLV β HLS \Xiaosongshu\Flv2mp4\Client::runFlv2Hls($file, __DIR__ . '/hls'); // 4. HLS β FLV \Xiaosongshu\Flv2mp4\Client::runHls2Flv(__DIR__ . '/hls/index.m3u8', __DIR__ . '/output.flv'); // 5. MP4 β FLV \Xiaosongshu\Flv2mp4\Client::runMp42Flv(__DIR__ . '/test.mp4', __DIR__ . '/output.flv'); // 6. FLV β MP4 \Xiaosongshu\Flv2mp4\Client::runFlv2Mp4($file, __DIR__ . '/output.mp4'); // 7. fMP4 β FLV (supports both mixed and separate) \Xiaosongshu\Flv2mp4\Client::runFmp42Flv(__DIR__ . '/output_merge/index.m3u8', __DIR__ . '/output.flv');
π Advanced Features
FLV Live Gateway
Supports multi-level proxy deployment for high-concurrency live stream forwarding. Create a new file flvGateway.php with the following content:
<?php require_once __DIR__ . '/vendor/autoload.php'; $gateway = new \Xiaosongshu\Flv2mp4\manage\FlvGateway(8080, 'http://127.0.0.1:8501'); $gateway->debug = true; $gateway->start();
Start the FLV gateway:
php flvGateway.php
Static File Gateway
Lightweight HTTP file server with directory listing toggle. Create a new file fileGateway.php with the following content:
<?php require_once __DIR__ . '/vendor/autoload.php'; $server = new \Xiaosongshu\Flv2mp4\manage\FileGateway( '0.0.0.0',8100,__DIR__,false); $server->debug = true; $server->start();
Start the file gateway:
php fileGateway.php
Push Client
Supports HTTP-FLV, WS-FLV, RTMP protocols with speed control and auto-reconnect. Create a new file pusher.php with the following content:
require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $pusher = new \Xiaosongshu\Flv2mp4\Manage\PusherManage(__DIR__."/test.flv", "http://127.0.0.1:8501/live/stream", 1.0, false); $pusher->start();
Start pushing:
php pusher.php
Pull Client
Pull live streams and save as local FLV files, suitable for recording or debugging. Create a new file puller.php with the following content:
require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $puller = new \Xiaosongshu\Flv2mp4\Manage\PullerManage("ws://127.0.0.1:8501/live/stream.flv", __DIR__."/pull_record.flv", 0, false); $puller->start();
Start the pull client:
php puller.php
Live Relay
Pull one stream and forward to multiple targets simultaneously (supports mixed protocols). Create a new file forward.php with the following content:
require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $forwarder = new \Xiaosongshu\Flv2mp4\Flv\FlvForwardClient("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"], 0, true); $forwarder->start();
Start the relay client:
php forward.php
π§ͺ Testing & Playback
| Output Format | Recommended Player | Reference File |
|---|---|---|
| MP4 | HTML5 <video> |
index.html |
| fMP4 | MSE Player | play_merge.htmlγmse.html |
| HLS (TS) | hls.js / Safari | play.html |
| FLV | flv.js | flv.html |
| FLV | Web push test | push.html |
π― Use Cases
- Live Recording: RTMP/FLV live streams saved as fMP4 / HLS in real-time
- Video Playback: On-demand playback of recorded streams
- Stream Relaying: Multi-level gateways for load balancing and edge acceleration
- Offline Batch Processing: Batch conversion of FLV / MP4 formats
- Pseudo-live Streaming: Push VOD files as live streams
- Cross-platform Relaying: One pull, multiple push destinations
- Multi-bitrate HLS: Pure PHP H.264 re-encoding for adaptive bitrate HLS
π₯ H.264 Decoding + Scaling + Re-encoding
Supports Baseline Profile H.264 decoding, scaling, and re-encoding, providing core capabilities for the following scenarios:
| Use Case | Description |
|---|---|
| Multi-bitrate HLS | Transcode a single FLV into multi-resolution HLS segments (adaptive bitrate) |
| FLV Re-encoding | Modify resolution/bitrate and re-encode to FLV |
| MP4 Re-encoding | Modify resolution/bitrate and re-encode to MP4 |
| Format Conversion | Re-encode during FLV β MP4 conversion (not just remuxing) |
| Watermark Overlay | Decode YUV β overlay PNG/text watermark β re-encode output |
| Quality Enhancement | Apply filters (sharpening, denoising, etc.) after decoding β re-encode |
| Resolution Adaptation | Downsample high-resolution video to multiple output resolutions |
| Bitrate Control | Re-encode high-bitrate video to a specified target bitrate |
Technical Positioning: This is a complete H.264 pixel processing pipeline (Decode β Process β Encode), implemented in pure PHP with no FFmpeg dependency.
FLV β HLS
Below is a FLV to multi-bitrate HLS example:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $profiles = [ // Configure different bitrates separately '240p' => [ 'width' => 426, // or 424, keep 16:9 ratio 'height' => 240, 'bitrate' => 300000, // 300 Kbps (video bitrate) 'fps' => 24, 'audioBitrate' => 48000, // 48 Kbps 'qp' => 30, // Keep 30 for stability 'watermark'=>true, // Whether to add watermark 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv",// Watermark file ] ]; $generator = new \Xiaosongshu\Flv2mp4\Recode\PurePhpHlsGenerator($profiles, __DIR__ . '/hls/output'); $generator->processFlv(__DIR__ . '/input.flv'); echo "Index URL: hls/output/master.m3u8\n"; echo "All processing complete!\n";
FLV β FLV
Re-encode FLV with new bitrate settings:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $config = [ 'width' => 320, // Target width, 0 = keep original resolution 'height' => 180, // Target height, 0 = keep original resolution 'bitrate' => 150000, // Target bitrate (bps), 0 = use QP mode 'fps' => 15, // Target framerate 'qp' => 30, // QP quality parameter (takes effect when bitrate is 0) 'watermark'=>true, // Whether to add watermark 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv",// Watermark file ]; $recoder = new \Xiaosongshu\Flv2mp4\Recode\FlvRecoder($config); $recoder->setMaxFrames(50); // Optional: limit the number of frames to process $recoder->processFlv(__DIR__ . '/input.flv', __DIR__.'/output.flv'); echo "FLV re-encoding complete\n";
MP4 β MP4
Re-encode MP4 file with new bitrate settings:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $config = [ 'width' => 320, // Target width, 0 = keep original resolution 'height' => 180, // Target height, 0 = keep original resolution 'bitrate' => 150000, // Target bitrate (bps), 0 = use QP mode 'fps' => 15, // Target framerate 'qp' => 30, // QP quality parameter (takes effect when bitrate is 0) 'watermark'=>true, // Whether to add watermark 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv",// Watermark file ]; $recoder = new \Xiaosongshu\Flv2mp4\Recode\Mp4Recoder($config); $recoder->setMaxFrames(50); // Optional: limit the number of frames to process $recoder->processMp4(__DIR__ . '/input.mp4', __DIR__ . '/output.mp4'); echo "MP4 re-encoding complete\n";
- When adding a watermark, a YUV format file is required. The filename must include the watermark dimensions (e.g.,
watermark_{width}x{height}.yuv). The tool will automatically parse the width and height from the filename (e.g.,watermark_80x16.yuvβ width 80, height 16). Please ensure the filename format is correct. - The re-encoding module provides a YUV pixel-level operation interface. You can build custom features on top of it, such as adding subtitles, picture-in-picture, video splicing, etc.
- For detailed H.264 usage instructions, please refer to the README.
Supported Re-encoding Features
- I-frame Decoding & Encoding (fully precise, INF dB)
- P-frame Decoding & Encoding (Baseline Profile)
- Intra Prediction: 4x4 (9 modes) + 16x16 (4 modes)
- Inter Prediction: P-frame motion estimation (Diamond Search optimized)
- 1/4-pixel Precision: 6-tap filter interpolation
- CAVLC Entropy Coding (Baseline Profile)
- Resolution Scaling (YUV scaling after decoding β re-encoding)
- Bitrate Control (via QP parameter adjustment)
- B-frame Support (planned, requires extension to Main Profile and bidirectional prediction implementation)
- CABAC Entropy Coding (planned, for Main Profile support)
β οΈ Performance Notice: The current H.264 re-encoding module is implemented in pure PHP and is suitable for short-duration videos (recommended β€ 10 seconds) offline processing or functional verification. For long videos or high-resolution transcoding, it is recommended to use FFmpeg or other professional tools.
Watermark Generation Tool
This project provides PHP functions for generating watermark YUV files. GD extension is preferred, with automatic fallback to bitmap font when GD is unavailable.
generateFromText(): Generate text watermark YUV. GD extension preferred, falls back to bitmap font when GD is unavailable. Built-in bitmap font only supports ASCII characters (English letters, numbers, and English punctuation).generateFromImage(): Generate watermark YUV from an image. Requires GD extension, supports PNG/JPG.
Generate Watermark File from Text
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiaosongshu\Flv2mp4\Codec\WatermarkUtil; echo "=== Testing WatermarkUtil ===\n\n"; // Test 1: Generate text watermark echo "1. Generating text watermark (xiaosongshu, 80x16)...\n"; $outputFile1 = __DIR__ . '/test_wm_text.yuv'; $start = microtime(true); $result = WatermarkUtil::generateFromText( 'xiaosongshu', $outputFile1, 80, 16, [ 'fontSize' => 5, // Built-in font size 1-5. `fontSize` ranges from 1-5 (larger number = larger font). Built-in bitmap font only supports ASCII characters. 'fontColor' => [255, 255, 255], 'bgColor' => [0, 0, 0], ] ); $cost = round(microtime(true) - $start, 3); if ($result && file_exists($outputFile1)) { $size = filesize($outputFile1); $expectedSize = 80 * 16 + (80 * 16 >> 1); echo " Success! File size: {$size} bytes (expected: {$expectedSize}) - Time: {$cost}s\n"; if ($size === $expectedSize) { echo " β File size correct\n"; } else { echo " β File size mismatch\n"; } } else { echo " β Generation failed\n"; }
Generate Watermark File from Image
- Requires PHP GD extension installed.
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiaosongshu\Flv2mp4\Codec\WatermarkUtil; echo "=== Testing WatermarkUtil ===\n\n"; // Test 1: Generate watermark from image echo "1. Generating watermark from image (xiaosongshu, 80x16)...\n"; $outputFile1 = __DIR__ . '/test_wm_copy_80x16.yuv'; $start = microtime(true); $result = WatermarkUtil::generateFromImage( __DIR__."/watermark_80x16.png", $outputFile1, 80, 16, ); $cost = round(microtime(true) - $start, 3); if ($result && file_exists($outputFile1)) { $size = filesize($outputFile1); $expectedSize = 80 * 16 + (80 * 16 >> 1); echo " Success! File size: {$size} bytes (expected: {$expectedSize}) - Time: {$cost}s\n"; if ($size === $expectedSize) { echo " β File size correct\n"; } else { echo " β File size mismatch\n"; } } else { echo " β Generation failed\n"; }
π§ Technical Notes
- Pure PHP 8.1+ implementation, no FFmpeg dependency
- This project was originally created primarily to serve the xiaosongshu/rtmp_server project
- Recommended static analysis with PHPStan Level 8
License & Disclaimer
This project is open-sourced under the Apache License 2.0. You are free to use, modify, and distribute the code, including for commercial purposes.
The code is provided "AS IS", without warranty of any kind, express or implied. The author shall not be liable for any damages arising from the use of this software.
π§ Contact
- π¬ Email: 2723659854@qq.com
- π GitHub: 2723659854