xiaosongshu / flv2mp4
Pure PHP native media processing library, realize FLV/MP4/HLS mutual conversion , H.264 re-encoding and opus/mp3/aac/wav 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: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- v1.6.5
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.9
- v1.5.8
- v1.5.7
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.9
- v1.4.8
- v1.4.7
- v1.4.6
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.9
- v1.3.8
- v1.3.7
- v1.3.6
- v1.3.5
- v1.3.4
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.9
- v1.2.8
- v1.2.7
- v1.2.6
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- dev-fast2
- dev-fast_recode
- dev-opus
- dev-best_decode
- dev-good_encode
- dev-fix_encode
- dev-new_p
- dev-fix_p
This package is auto-updated.
Last update: 2026-09-15 10:19:50 UTC
README
Introduction
A lightweight pure PHP 8.1+ media processing toolkit with zero external dependencies (no FFmpeg required).
Supports FLV, FMP4, MP4, HLS mutual conversion, live streaming gateway, pushing, pulling, rebroadcasting, as well as H.264 decoding + scaling + re-encoding (Baseline Profile) and Full-format Interconversion of AAC/MP3/Opus/WAV.
📋 Table of Contents
- Introduction
- Core Features
- Requirements
- Installation
- Quick Start
- Advanced Features
- Testing & Playback
- Use Cases
- H.264 Re-encoding
- Encoding/Decoding for AAC-MP3-OPUS-WAV
- Technical Notes
- License & Disclaimer
- Contact
🎯 Core Features
| Feature | Direction | Description |
|---|---|---|
| Container conversion | FLV ↔ MP4 / FMP4 | Generate standard MP4 or fragmented fMP4 (MSE compatible) |
| HLS slicing | FLV → HLS | Generate M3U8 + TS segments, compatible with hls.js, VLC, etc. |
| HLS restoration | HLS → FLV | Merge HLS segments back into a single FLV file |
| MP4 ↔ FLV | MP4 → FLV / FMP4 → FLV | Multi-container interconversion |
| Live gateway | FLV gateway | High-performance multi-level forwarding, supports high concurrency |
| Static file server | HTTP file gateway | Lightweight file server with directory browsing support |
| Pushing client | FLV / MP4 → RTMP/HTTP-FLV/WS-FLV | Push static files as a pseudo-live stream |
| Pulling client | RTMP/HTTP-FLV/WS-FLV → FLV | Pull live stream and save as local FLV |
| Rebroadcasting | Multi-protocol input → Multi-protocol output | One pull, multiple forwards |
| H.264 re-encoding | Decode → Scale → Encode | Baseline Profile, provides core support for multi-bitrate HLS |
| OPUS→AAC | opus→pcm→aac | Convert WebRTC Opus audio to AAC-LC |
| AAC→MP3 | aac→pcm→mp3 | Convert AAC-LC audio to MP3 |
| opus/aac/mp3/wav format conversion | Source audio → PCM → target format audio | Supports mutual conversion among Opus/AAC/MP3/WAV audio formats |
Environment Requirements
| Dependency | Description |
|---|---|
| PHP | ≥ 8.1 (CLI mode only) |
sockets ext |
Optional, provides low-level Socket communication. Only required for live streaming and H.264 re-encoding scenarios. |
gd ext |
Optional, used to generate watermarks from PNG/JPG images. If not installed, it automatically falls back to the built-in bitmap font mode. |
- 💡 Only supported in PHP CLI mode. Not supported under Nginx/FPM or web server environments.
- 💡 No FFmpeg, no third-party binaries required — fully implemented in pure PHP.
- 💡 Container remuxing (FLV/MP4/HLS conversion) only changes the container format and is very fast.
- ⚠️ H.264 re-encoding requires
proc_opento be enabled. (This module uses multi-process distributed computing and spawns child processes to process frames in parallel.) - ⚠️ Opus real-time transcoding (live streaming only) requires
proc_opento be enabled. (In real-time scenarios such as WebRTC to RTMP, it launches a standalone background Worker process for audio transcoding. Static file Opus transcoding does not require this function.) - ⚠️ H.264 re-encoding is a CPU-intensive task. Performance depends on server configuration. It is not recommended for live real-time transcoding. Enabling JIT acceleration is highly recommended.
🚀 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 → fragmented fMP4 (merged) \Xiaosongshu\Flv2mp4\Client::runFlv2Fmp4Mixed($file, __DIR__ . '/output_merge'); // 2. FLV → fragmented fMP4 (separate audio/video tracks) \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 merged and separate formats) \Xiaosongshu\Flv2mp4\Client::runFmp42Flv(__DIR__ . '/output_merge/index.m3u8', __DIR__ . '/output.flv'); // 8. MP4 → HLS \Xiaosongshu\Flv2mp4\Client::runMp42Hls(__DIR__ . "/demo.mp4", __DIR__ . "/mp4_hls"); // 9. HLS → MP4 \Xiaosongshu\Flv2mp4\Client::runHls2Mp4( __DIR__ .'/mp4_hls/demo/index.m3u8', __DIR__.'/hls_2_mp4.mp4'); // 10. MP4 → fMP4 \Xiaosongshu\Flv2mp4\Client::runMp42Fmp4(__DIR__.'/demo.mp4', __DIR__.'/mp4_2_fmp4'); // 11. fMP4 → MP4 \Xiaosongshu\Flv2mp4\Client::runFmp42Mp4(__DIR__.'/mp4_2_fmp4/index.m3u8',__DIR__.'/1234567.mp4');
🌐 Advanced Features
Opus 2 AAC
WebRtcFlvRelay receives WebRTC RTP data, wraps H.264 video into FLV, transcodes Opus audio to AAC‑LC via a pure PHP Worker, and pushes it to a WebSocket‑FLV service for recording or forwarding to RTMP.
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiaosongshu\Flv2mp4\Flv\WebRtcFlvRelay; use Xiaosongshu\Flv2mp4\Opus\OpusWorkerClient; $clientId = 1; $streamId = 'stream_001'; $opusWorkerPort = 8330; $pushUrl = "ws://127.0.0.1:8501/live/{$streamId}"; $relay = new WebRtcFlvRelay( $clientId, $streamId, $pushUrl, null, null, $opusWorkerPort ); $relay->connect(); // Call these in your WebRTC server's RTP callback: // $relay->pushRtp($plainRtp, 'video'); // $relay->pushRtp($plainRtp, 'audio'); // Close relay when done; shut down automatically started Workers on process exit. $relay->finish(); OpusWorkerClient::shutdownOwnedWorkers();
A complete example is available at examples/webrtc.php. Common configuration:
// Each project instance must use a different Worker port. $opusWorkerPort = 8330; // Supports RTMP, HTTP‑FLV, and WebSocket‑FLV push URLs. // The example uses WebSocket‑FLV and replaces placeholder with streamId. $wsFlvPushUrl = 'ws://127.0.0.1:8501/live/{streamId}';
Run the example:
php webrtc.php
Notes:
- The relay automatically starts
bin/opus-worker.phpif no Worker is listening on the port – no manual startup needed. - Worker listens only on
127.0.0.1, default port8330. - Auto‑start passes the host project's real
vendor/autoload.phpvia--autoload, working with both local development and Composer‑installed setups. - Default output: 48kHz, mono, 64kbps AAC‑LC.
- One Worker process can manage multiple independent connections, but real‑time transcoding is CPU‑heavy; plan for one live stream per instance.
- Different project instances on the same machine must use different
$opusWorkerPort. - On
Ctrl+Cor process exit, callOpusWorkerClient::shutdownOwnedWorkers()– the example already handles this. - PHP must allow
proc_openfor automatic Worker creation. - The Worker queue has bounded back‑pressure; do not simply enlarge the queue to solve performance issues, as it may increase latency and cause A/V desync.
- WebRTC service requires the
xiaosongshu/webrtcpackage.
FLV Live Gateway
Supports multi‑level proxy deployment for high‑concurrency live stream forwarding. Create flvGateway.php:
<?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();
Run:
php flvGateway.php
Static File Gateway
Lightweight HTTP file server with directory browsing toggle. Create fileGateway.php:
<?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();
Run:
php fileGateway.php
Pushing Client
Supports HTTP‑FLV, WS‑FLV, RTMP, with speed control and auto‑reconnect. Create pusher.php:
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();
Run:
php pusher.php
Pulling Client
Pulls a live stream and saves it as a local FLV file. Create puller.php:
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();
Run:
php puller.php
Rebroadcasting (Forwarding)
Pulls one stream and forwards it to multiple destinations (mixed protocols supported). Create forward.php:
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();
Run:
php forward.php
🧪 Testing & Playback
| Output format | Recommended player | Sample 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 (push test) | Web push test | push.html |
🎯 Use Cases
- Live recording: Save RTMP/FLV streams as fMP4 / HLS in real time.
- Video playback: On‑demand playback of recorded streams.
- Stream forwarding: Multi‑level gateways for load balancing and edge acceleration.
- Offline batch processing: Bulk FLV / MP4 conversion.
- Pseudo‑live streaming: Push on‑demand files as live streams.
- Cross‑platform rebroadcasting: One pull, multiple pushes to different platforms.
- Multi‑bitrate HLS: Pure PHP H.264 re‑encoding to generate adaptive‑bitrate HLS.
🔥 H.264 Decoding + Scaling + Re-encoding
Supports Baseline Profile H.264 decoding, scaling, and re‑encoding, enabling the following capabilities:
| Use case | Description |
|---|---|
| Multi‑bitrate HLS | Convert a single FLV into multiple resolution HLS streams (adaptive bitrate) |
| FLV re‑encoding | Change resolution/bitrate and output as FLV |
| MP4 re‑encoding | Change resolution/bitrate and output as MP4 |
| Format conversion | Re‑encode during FLV ↔ MP4 conversion (not just remuxing) |
| Watermark overlay | Decode YUV → overlay PNG/text watermark → re‑encode output |
| Image enhancement | Apply filters (sharpen, denoise) after decoding → re‑encode |
| Resolution adaptation | Downsample high‑resolution video to multiple output resolutions |
| Bitrate control | Transcode high‑bitrate videos to target bitrate |
This is a complete H.264 pixel processing pipeline (decode → process → encode), implemented entirely in PHP without FFmpeg.
FLV2HLS
Example for multi‑bitrate HLS generation:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $profiles = [ '240p' => [ 'width' => 426, 'height' => 240, 'bitrate' => 300000, // 300 Kbps video 'fps' => 24, 'audioBitrate' => 48000, // 48 Kbps 'qp' => 30, 'watermark'=>true, 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv", ] ]; // Enable multi-process acceleration for high-quality re-encoding; not needed for low bitrate. $generator = new \Xiaosongshu\Flv2mp4\Recode\PurePhpHlsGenerator($profiles, __DIR__ . '/hls/output', true); $generator->processFlv(__DIR__ . '/input.flv'); echo "Master playlist: hls/output/master.m3u8\n"; echo "All done!\n";
FLV2FLV
Re‑encode a FLV file with new bitrate/resolution:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $config = [ 'width' => 320, 'height' => 180, 'bitrate' => 150000, 'fps' => 15, 'qp' => 30, 'watermark'=>true, 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv", ]; // Enable multi-process acceleration for high-quality re-encoding; not needed for low bitrate. $recoder = new \Xiaosongshu\Flv2mp4\Recode\FlvRecoder($config, true); $recoder->setMaxFrames(50); $recoder->processFlv(__DIR__ . '/input.flv', __DIR__.'/output.flv'); echo "FLV re‑encoding done.\n";
MP42MP4
Re‑encode a MP4 file:
<?php require_once __DIR__ . '/vendor/autoload.php'; ini_set('memory_limit', '2048M'); $config = [ 'width' => 320, 'height' => 180, 'bitrate' => 150000, 'fps' => 15, 'qp' => 30, 'watermark'=>true, 'watermark_file'=> __DIR__."/src/Static/watermark_80x16.yuv", ]; // Enable multi-process acceleration for high-quality re-encoding; not needed for low bitrate. $recoder = new \Xiaosongshu\Flv2mp4\Recode\Mp4Recoder($config, true); $recoder->setMaxFrames(50); $recoder->processMp4(__DIR__ . '/input.mp4', __DIR__ . '/output.mp4'); echo "MP4 re‑encoding done.\n";
Notes for watermarking:
- Watermark files must be in YUV format, and the filename must include its dimensions (e.g.,
watermark_{width}x{height}.yuv). - The tool parses width and height from the filename automatically (e.g.,
watermark_80x16.yuv→ width 80, height 16). - The re‑encoding module exposes a YUV pixel‑level interface, which can be used to implement custom features like subtitles, picture‑in‑picture, video stitching, etc.
- For detailed H.264 usage, see src/Codec/README.md.
Supported Re‑encoding Features
- I‑frame decode & encode (100% exact, INF dB)
- P‑frame decode & encode (Baseline Profile)
- Intra prediction: 4×4 (9 modes) + 16×16 (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 decode → re‑encode)
- Bitrate control (via QP parameter)
- B‑frame support (planned, requires Main Profile with bidirectional prediction)
- CABAC entropy coding (planned, Main Profile)
⚠️ Performance note: The H.264 re‑encoding module is pure PHP and is intended for short‑duration videos (≤ 10 seconds) for offline processing or functional verification. For long videos or high‑resolution transcoding, professional tools like FFmpeg are recommended.
Watermark Generator
Provides PHP functions to generate YUV watermark files. Uses GD extension if available, otherwise falls back to built‑in bitmap font.
generateFromText()– generates text watermark YUV. Uses GD if available; otherwise falls back to bitmap font (ASCII characters only).generateFromImage()– generates watermark YUV from PNG/JPG images (requires GD extension).
Generate text watermark
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiaosongshu\Flv2mp4\Codec\WatermarkUtil; echo "=== Testing WatermarkUtil ===\n\n"; echo "1. Generate text watermark (xiaosongshu, 80x16)...\n"; $outputFile1 = __DIR__ . '/test_wm_text.yuv'; $start = microtime(true); $result = WatermarkUtil::generateFromText( 'xiaosongshu', $outputFile1, 80, 16, [ 'fontSize' => 5, // 1–5, built‑in font; ASCII only '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! 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 from image
Requires GD extension.
<?php require_once __DIR__ . '/vendor/autoload.php'; use Xiaosongshu\Flv2mp4\Codec\WatermarkUtil; echo "=== Testing WatermarkUtil ===\n\n"; echo "1. Generate 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! 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"; }
Performance Test Report
Test Environment
| Item | Windows Environment | Linux Environment (Docker) |
|---|---|---|
| Operating System | Windows | Linux (Docker) |
| CPU | 16 cores (physical) | 14 cores (physical) |
| Memory | 15.8 GB (available) | 4 GB (available) |
| Worker processes | 8 ME sub‑processes | 8 ME sub‑processes |
| PHP version | 8.4.3 (CLI, JIT enabled) | 8.1.24 (CLI, OPcache disabled) |
| OPcache | opcache.enable_cli=on, opcache.jit=on, opcache.jit_buffer_size=100M |
Not enabled |
| Test clip | test.flv, 3.02 s, 720×742, 30 fps |
Same as left |
| Output specs | output.flv, 360×360, 10 fps |
Same as left |
| Encoding settings | H.264 Constrained Baseline, AAC 128 kbps | Same as left |
Cross‑Platform Performance Comparison
| Output Format | Windows Time | Linux (Docker) Time | Performance Gain |
|---|---|---|---|
| FLV Re‑encoding | 28 s | 23 s | ↓ 17.9% |
| MP4 Re‑encoding | 29 s | 24 s | ↓ 17.2% |
| HLS (mpegts + m3u8) | 37 s | 31 s | ↓ 16.2% |
Linux environment (without OPcache) is still about 5–6 seconds faster than Windows (with JIT enabled).
Encoding/Decoding for AAC-MP3-OPUS-WAV
# aac-lc → mp3 \Xiaosongshu\Flv2mp4\Client::runAac2Mp3( __DIR__ . '/input.aac',__DIR__ . '/aac2mp3.mp3'); # aac-lc → wav \Xiaosongshu\Flv2mp4\Client::runAac2Wav(__DIR__ . '/input.aac',__DIR__ . '/aac2wav.wav'); # wav → aac-lc \Xiaosongshu\Flv2mp4\Client::runWav2Aac(__DIR__ . '/input.wav',__DIR__ . '/wav2aac.aac'); # opus → wav \Xiaosongshu\Flv2mp4\Client::runOpus2Wav(__DIR__ . '/input.opus',__DIR__ . '/opus2wav.wav'); # mp3 → wav \Xiaosongshu\Flv2mp4\Client::runMp32Wav(__DIR__ . '/input.mp3',__DIR__ . '/mp32wav.wav'); # wav → mp3 \Xiaosongshu\Flv2mp4\Client::runWav2Mp3(__DIR__ . '/input.wav',__DIR__ . '/wav2mp3.mp3'); # opus → mp3 \Xiaosongshu\Flv2mp4\Client::runOpus2Mp3(__DIR__ . '/input.opus',__DIR__ . '/opus2mp3.mp3'); # opus → aac-lc \Xiaosongshu\Flv2mp4\Client::runOpus2Aac(__DIR__ . '/input.opus',__DIR__ . '/opus2aac.aac'); # mp3 → aac-lc \Xiaosongshu\Flv2mp4\Client::runMp32Aac(__DIR__ . '/input.mp3',__DIR__ . '/mp32aac.aac'); # mp3 → opus \Xiaosongshu\Flv2mp4\Client::runMp32Opus(__DIR__ . '/input.mp3', __DIR__ . '/mp32opus.opus'); # wav → opus \Xiaosongshu\Flv2mp4\Client::runWav2Opus(__DIR__ . '/input.wav', __DIR__ . '/wav2opus.opus'); # aac-lc → opus \Xiaosongshu\Flv2mp4\Client::runAac2Opus(__DIR__ . '/input.aac', __DIR__ . '/aac2opus.opus');
🔧 Technical Notes
- 100% pure PHP 8.1+, no FFmpeg dependency.
- Originally built to serve xiaosongshu/rtmp_server.
- Recommended static analysis: PHPStan Level 8.
- H.264 re‑encoding uses distributed multi‑process architecture; disable distributed mode if running on a single‑core machine.
Open Source License & Disclaimer
- Open Source License: This project is released under the Apache License 2.0, which permits free use, modification, and distribution (including for commercial purposes). The code is provided "AS IS", without any express or implied warranties. The author shall not be held liable for any damages arising from the use of this software.
- Patent Risk Notice: This project contains pure PHP implementations of patent-protected audio/video codecs, including H.264, AAC-LC, and MP3. The above open source license grants only a copyright license and does not include any patent license.
- Usage Restrictions & Transfer of Liability: The above codec implementations are intended solely for learning, research, testing, and personal non-commercial use. If you use them for any commercial product distribution or commercial operation, you must obtain the appropriate patent licenses from the relevant patent holders (e.g., Via Licensing, MPEG LA, Fraunhofer IIS) at your own expense and assume all patent infringement risks. The author of this project shall not be liable for any patent infringement liabilities arising therefrom.
- Final Interpretation: By using this project, you are deemed to have read, understood, and agreed to all terms of this disclaimer.
📧 Contact
- Email: 2723659854@qq.com
- GitHub: 2723659854