mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
完善readme
This commit is contained in:
parent
725e75cd23
commit
3f9f9c4d81
344
README.md
344
README.md
@ -1,63 +1,90 @@
|
|||||||
![logo](https://raw.githubusercontent.com/zlmediakit/ZLMediaKit/master/logo.png)
|
![logo](https://raw.githubusercontent.com/zlmediakit/ZLMediaKit/master/logo.png)
|
||||||
|
|
||||||
# A lightweight ,high performance and stable stream server and client framework based on C++11.
|
[english readme](https://github.com/xiongziliang/ZLMediaKit/blob/master/README_en.md)
|
||||||
|
|
||||||
|
# 一个基于C++11的高性能运营级流媒体服务框架
|
||||||
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
||||||
|
|
||||||
[中文](https://github.com/xiongziliang/ZLMediaKit/blob/master/README_CN.md)
|
|
||||||
|
|
||||||
## Why ZLMediaKit?
|
## 国内用户请使用gitee镜像下载
|
||||||
- Developed based on C++ 11, the code is stable and reliable, avoiding the use of raw pointers, cross-platform porting is simple and convenient, and the code is clear and concise.
|
```
|
||||||
- Support rich streaming media protocols(`RTSP/RTMP/HLS/HTTP-FLV/Websocket-flv`),and support Inter-protocol conversion.
|
git clone --depth 1 https://gitee.com/xiahcu/ZLMediaKit
|
||||||
- Multiplexing asynchronous network IO based on epoll and multi thread,extreme performance.
|
cd ZLMediaKit
|
||||||
- Well performance and stable test,can be used commercially.
|
git submodule update --init
|
||||||
- Support linux, macos, ios, android, Windows Platforms.
|
```
|
||||||
- Very low latency(lower then one second), video opened immediately.
|
## 项目特点
|
||||||
|
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
||||||
|
- 打包多种流媒体协议(RTSP/RTMP/HLS/HTTP-FLV/Websocket-FLV),支持协议间的互相转换,提供一站式的服务。
|
||||||
|
- 使用epoll+线程池+异步网络IO模式开发,并发性能优越。
|
||||||
|
- 已实现主流的的H264/H265+AAC流媒体方案,代码精简,脉络清晰,适合学习。
|
||||||
|
- 编码格式与框架代码解耦,方便自由简洁的添加支持其他编码格式。
|
||||||
|
- 代码经过大量的稳定性、性能测试,可满足商用服务器项目。
|
||||||
|
- 支持linux、macos、ios、android、windows平台。
|
||||||
|
- 支持画面秒开(GOP缓存)、极低延时([500毫秒内,最低可达100毫秒](https://github.com/zlmediakit/ZLMediaKit/wiki/%E5%BB%B6%E6%97%B6%E6%B5%8B%E8%AF%95))。
|
||||||
|
- [ZLMediaKit高并发实现原理](https://github.com/xiongziliang/ZLMediaKit/wiki/ZLMediaKit%E9%AB%98%E5%B9%B6%E5%8F%91%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86)。
|
||||||
|
- 提供完善的标准C API,可以作SDK用,或供其他语言调用。
|
||||||
|
- 提供完整的MediaServer服务器,可以免开发直接部署为商用服务器。
|
||||||
|
|
||||||
## Features
|
## 项目定位
|
||||||
|
- 移动嵌入式跨平台流媒体解决方案。
|
||||||
|
- 商用级流媒体服务器。
|
||||||
|
- 网络编程二次开发SDK。
|
||||||
|
|
||||||
|
|
||||||
|
## 功能清单
|
||||||
- RTSP
|
- RTSP
|
||||||
- RTSP[S] server,support rtsp push.
|
- RTSP 服务器,支持RTMP/MP4转RTSP。
|
||||||
- RTSP player and pusher.
|
- RTSPS 服务器,支持亚马逊echo show这样的设备
|
||||||
- RTP Transport : `rtp over udp` `rtp over tcp` `rtp over http` `rtp udp multicast` .
|
- RTSP 播放器,支持RTSP代理,支持生成静音音频
|
||||||
- Basic/Digest/Url Authentication.
|
- RTSP 推流客户端与服务器
|
||||||
- H265/H264/AAC codec.
|
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
|
||||||
- Recorded as mp4.
|
- 服务器/客户端完整支持Basic/Digest方式的登录鉴权,全异步可配置化的鉴权接口。
|
||||||
- Vod of mp4.
|
- 支持H265编码
|
||||||
|
- 服务器支持RTSP推流(包括`rtp over udp` `rtp over tcp`方式)
|
||||||
|
- 支持任意编码格式的rtsp推流,只是除H264/H265+AAC外无法转协议
|
||||||
|
|
||||||
- RTMP
|
- RTMP
|
||||||
- RTMP server,support player and pusher.
|
- RTMP 播放服务器,支持RTSP/MP4转RTMP。
|
||||||
- RTMP player and pusher.
|
- RTMP 发布服务器,支持录制发布流。
|
||||||
- Support HTTP-FLV player.
|
- RTMP 播放器,支持RTMP代理,支持生成静音音频
|
||||||
- H264/AAC codec.
|
- RTMP 推流客户端。
|
||||||
- Recorded as flv or mp4.
|
- 支持http-flv直播。
|
||||||
- Vod of mp4.
|
- 支持https-flv直播。
|
||||||
|
- 支持任意编码格式的rtmp推流,只是除H264/H265+AAC外无法转协议
|
||||||
|
|
||||||
- HLS
|
- HLS
|
||||||
- RTSP RTMP can be converted into HLS,built-in HTTP server.
|
- 支持HLS文件生成,自带HTTP文件服务器。
|
||||||
- Play authentication based on cookie.
|
- 支持播放鉴权,鉴权结果可以缓存为cookie
|
||||||
|
|
||||||
- HTTP[S]
|
- HTTP[S]
|
||||||
- HTTP server,suppor directory meun、RESTful http api.
|
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
|
||||||
- HTTP client,downloader,uploader,and http api requester.
|
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`,`文件上传器`。
|
||||||
- Cookie supported.
|
- 完整HTTP API服务器,可以作为web后台开发框架。
|
||||||
- WebSocket Server and Client.
|
- 支持跨域访问。
|
||||||
- File access authentication.
|
- 支持http客户端、服务器cookie
|
||||||
|
- 支持WebSocket服务器和客户端
|
||||||
|
- 支持http文件访问鉴权
|
||||||
|
|
||||||
- Others
|
- 其他
|
||||||
- Support stream proxy by ffmpeg.
|
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
|
||||||
- RESTful http api and http hook event api.
|
- 支持简单的telnet调试。
|
||||||
- Config file hot loading.
|
- 支持H264的解析,支持B帧的POC计算排序。
|
||||||
- Vhost supported.
|
- 支持配置文件热加载
|
||||||
- Auto close stream when nobody played.
|
- 支持流量统计、推流播放鉴权等事件
|
||||||
- Play and push authentication.
|
- 支持rtsp/rtmp/http虚拟主机
|
||||||
- Pull stream on Demand.
|
- 支持flv、mp4文件录制
|
||||||
|
- 支持rtps/rtmp协议的mp4点播,支持seek
|
||||||
|
- 支持按需拉流,无人观看自动关断拉流
|
||||||
|
- 支持先拉流后推流,提高及时推流画面打开率
|
||||||
|
- 支持rtsp/rtmp/http-flv/hls播放鉴权(url参数方式)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- Protocol conversion:
|
## 其他功能细节表
|
||||||
|
|
||||||
| protocol/codec | H264 | H265 | AAC | other |
|
- 转协议:
|
||||||
|
|
||||||
|
| 功能/编码格式 | H264 | H265 | AAC | other |
|
||||||
| :------------------------------: | :--: | :--: | :--: | :---: |
|
| :------------------------------: | :--: | :--: | :--: | :---: |
|
||||||
| RTSP[S] --> RTMP/HTTP[S]-FLV/FLV | Y | N | Y | N |
|
| RTSP[S] --> RTMP/HTTP[S]-FLV/FLV | Y | N | Y | N |
|
||||||
| RTMP --> RTSP[S] | Y | N | Y | N |
|
| RTMP --> RTSP[S] | Y | N | Y | N |
|
||||||
@ -68,18 +95,18 @@
|
|||||||
| MP4 --> RTSP[S] | Y | N | Y | N |
|
| MP4 --> RTSP[S] | Y | N | Y | N |
|
||||||
| MP4 --> RTMP | Y | N | Y | N |
|
| MP4 --> RTMP | Y | N | Y | N |
|
||||||
|
|
||||||
- Stream generation:
|
- 流生成:
|
||||||
|
|
||||||
| feature/codec | H264 | H265 | AAC | other |
|
| 功能/编码格式 | H264 | H265 | AAC | other |
|
||||||
| :-----------: | :--: | :--: | :--: | :---: |
|
| :------------------------------: | :--: | :--: | :--: | :---: |
|
||||||
| RTSP[S] push | Y | Y | Y | Y |
|
| RTSP[S]推流 | Y | Y | Y | Y |
|
||||||
| RTSP proxy | Y | Y | Y | Y |
|
| RTSP拉流代理 | Y | Y | Y | Y |
|
||||||
| RTMP push | Y | Y | Y | Y |
|
| RTMP推流 | Y | Y | Y | Y |
|
||||||
| RTMP proxy | Y | Y | Y | Y |
|
| RTMP拉流代理 | Y | Y | Y | Y |
|
||||||
|
|
||||||
- RTP transport:
|
- RTP传输方式:
|
||||||
|
|
||||||
| feature/transport | tcp | udp | http | udp_multicast |
|
| 功能/RTP传输方式 | tcp | udp | http | udp_multicast |
|
||||||
| :-----------------: | :--: | :--: | :--: | :-----------: |
|
| :-----------------: | :--: | :--: | :--: | :-----------: |
|
||||||
| RTSP[S] Play Server | Y | Y | Y | Y |
|
| RTSP[S] Play Server | Y | Y | Y | Y |
|
||||||
| RTSP[S] Push Server | Y | Y | N | N |
|
| RTSP[S] Push Server | Y | Y | N | N |
|
||||||
@ -87,18 +114,18 @@
|
|||||||
| RTSP Pusher | Y | Y | N | N |
|
| RTSP Pusher | Y | Y | N | N |
|
||||||
|
|
||||||
|
|
||||||
- Server supported:
|
- 支持的服务器类型列表
|
||||||
|
|
||||||
| Server | Y/N |
|
| 服务类型 | Y/N |
|
||||||
| :-----------------: | :--: |
|
| :-----------------: | :--: |
|
||||||
| RTSP[S] Play Server | Y |
|
| RTSP[S] Play Server | Y |
|
||||||
| RTSP[S] Push Server | Y |
|
| RTSP[S] Push Server | Y |
|
||||||
| RTMP | Y |
|
| RTMP | Y |
|
||||||
| HTTP[S]/WebSocket[S] | Y |
|
| HTTP[S]/WebSocket[S] | Y |
|
||||||
|
|
||||||
- Client supported:
|
- 支持的客户端类型
|
||||||
|
|
||||||
| Client | Y/N |
|
| 客户端类型 | Y/N |
|
||||||
| :---------: | :--: |
|
| :---------: | :--: |
|
||||||
| RTSP Player | Y |
|
| RTSP Player | Y |
|
||||||
| RTSP Pusher | Y |
|
| RTSP Pusher | Y |
|
||||||
@ -107,130 +134,112 @@
|
|||||||
| HTTP[S] | Y |
|
| HTTP[S] | Y |
|
||||||
| WebSocket[S] | Y |
|
| WebSocket[S] | Y |
|
||||||
|
|
||||||
|
## 后续任务
|
||||||
|
- 完善支持H265
|
||||||
|
|
||||||
|
## 编译要求
|
||||||
|
- 编译器支持C++11,GCC4.8/Clang3.3/VC2015或以上
|
||||||
|
- cmake3.2或以上
|
||||||
|
|
||||||
## System Requirements
|
## 编译前必看!!!
|
||||||
|
|
||||||
- Compiler support c++11,GCC4.8/Clang3.3/VC2015 or above.
|
- **必须使用git下载完整的代码,不要使用下载zip包的方式下载源码,否则子模块代码默认不下载!你可以像以下这样操作:**
|
||||||
- cmake3.1 or above.
|
|
||||||
- All Linux , both 32 and 64 bits
|
|
||||||
- Apple OSX(Darwin), both 32 and 64bits.
|
|
||||||
- All hardware with x86/x86_64/arm/mips cpu.
|
|
||||||
- Windows.
|
|
||||||
|
|
||||||
## How to build
|
|
||||||
|
|
||||||
It is recommended to compile on Ubuntu or MacOS,compiling on windows is cumbersome, and some features are not compiled by default.
|
|
||||||
|
|
||||||
### Before build
|
|
||||||
- **You must use git to clone the complete code. Do not download the source code by downloading zip package. Otherwise, the sub-module code will not be downloaded by default.You can do it like this:**
|
|
||||||
```
|
```
|
||||||
git clone https://github.com/zlmediakit/ZLMediaKit.git
|
git clone https://github.com/zlmediakit/ZLMediaKit.git
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build on linux
|
## 编译(Linux)
|
||||||
|
- 我的编译环境
|
||||||
- My environment
|
- Ubuntu16.04 64 bit + gcc5.4
|
||||||
- Ubuntu16.04 64 bit and gcc5.4
|
|
||||||
- cmake 3.5.1
|
- cmake 3.5.1
|
||||||
- Guidance
|
- 编译
|
||||||
|
|
||||||
```
|
```
|
||||||
# If it is on centos6.x, you need to install the newer version of GCC and cmake first,
|
//如果是centos6.x,需要先安装较新版本的gcc以及cmake,然后打开脚本build_for_linux.sh手动编译
|
||||||
# and then compile manually according to the script "build_for_linux.sh".
|
//如果是ubuntu这样的比较新的系统版本可以直接操作第4步
|
||||||
# If it is on a newer version of a system such as Ubuntu or Debain,
|
|
||||||
# step 4 can be manipulated directly.
|
|
||||||
|
|
||||||
# 1、Install GCC5.2 (this step can be skipped if the GCC version is higher than 4.7)
|
1、安装GCC5.2(如果gcc版本高于4.7可以跳过此步骤)
|
||||||
sudo yum install centos-release-scl -y
|
sudo yum install centos-release-scl -y
|
||||||
sudo yum install devtoolset-4-toolchain -y
|
sudo yum install devtoolset-4-toolchain -y
|
||||||
scl enable devtoolset-4 bash
|
scl enable devtoolset-4 bash
|
||||||
|
|
||||||
# 2、Install cmake (this step can be skipped if the cmake version is higher than 3.1)
|
2、安装cmake
|
||||||
tar -xvf cmake-3.10.0-rc4.tar.gz #you need download cmake source file manually
|
#需要安装新版本cmake,当然你也可以通过yum或者apt-get方式安装(前提是版本够新)
|
||||||
|
tar -xvf cmake-3.10.0-rc4.tar.gz
|
||||||
cd cmake-3.10.0-rc4
|
cd cmake-3.10.0-rc4
|
||||||
./configure
|
./configure
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
# 3、Switch to high version GCC
|
3、切换高版本gcc
|
||||||
scl enable devtoolset-4 bash
|
scl enable devtoolset-4 bash
|
||||||
|
|
||||||
# 4、build
|
4、编译
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
./build_for_linux.sh
|
./build_for_linux.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build on macOS
|
## 编译(macOS)
|
||||||
|
- 我的编译环境
|
||||||
- My environment
|
|
||||||
- macOS Sierra(10.12.1) + xcode8.3.1
|
- macOS Sierra(10.12.1) + xcode8.3.1
|
||||||
- Homebrew 1.1.3
|
- Homebrew 1.1.3
|
||||||
- cmake 3.8.0
|
- cmake 3.8.0
|
||||||
- Guidance
|
- 编译
|
||||||
|
|
||||||
```
|
```
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
./build_for_mac.sh
|
./build_for_mac.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build on iOS
|
## 编译(iOS)
|
||||||
|
- 编译环境:`请参考macOS的编译指导。`
|
||||||
|
- 编译
|
||||||
|
|
||||||
This build method is no longer recommended.It is recommended that make Xcode project by yourself.
|
```
|
||||||
|
cd ZLMediaKit
|
||||||
- My environment
|
./build_for_ios.sh
|
||||||
|
```
|
||||||
Same with Build on macOS
|
- 你也可以生成Xcode工程再编译,[了解更多](https://github.com/leetal/ios-cmake):
|
||||||
|
|
||||||
|
|
||||||
- You can generate Xcode projects and recompile them , [learn more](https://github.com/leetal/ios-cmake):
|
|
||||||
|
|
||||||
```
|
```
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
# Generate Xcode project, project file is in build directory
|
# 生成Xcode工程,工程文件在build目录下
|
||||||
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
|
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 编译(Android)
|
||||||
|
- 我的编译环境
|
||||||
|
|
||||||
### Build on Android
|
|
||||||
|
|
||||||
Now you can open android sudio project in `Android` folder,this is a `aar library` and damo project.
|
|
||||||
|
|
||||||
- My environment
|
|
||||||
- macOS Sierra(10.12.1) + xcode8.3.1
|
- macOS Sierra(10.12.1) + xcode8.3.1
|
||||||
- Homebrew 1.1.3
|
- Homebrew 1.1.3
|
||||||
- cmake 3.8.0
|
- cmake 3.8.0
|
||||||
- [android-ndk-r14b](https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip)
|
- [android-ndk-r14b](https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip)
|
||||||
- Guidance
|
- 编译
|
||||||
|
|
||||||
```
|
```
|
||||||
cd ZLMediaKit
|
cd ZLMediaKit
|
||||||
export ANDROID_NDK_ROOT=/path/to/ndk
|
export ANDROID_NDK_ROOT=/path/to/ndk
|
||||||
./build_for_android.sh
|
./build_for_android.sh
|
||||||
```
|
```
|
||||||
### Build on Windows
|
## 编译(Windows)
|
||||||
|
- 我的编译环境
|
||||||
- My environment
|
|
||||||
- windows 10
|
- windows 10
|
||||||
- visual studio 2017
|
- visual studio 2017
|
||||||
- [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
|
- [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
|
||||||
|
|
||||||
- Guidance
|
- 编译
|
||||||
```
|
```
|
||||||
1 Enter the ZLMediaKit directory and execute git submodule update -- init downloads the code for ZLToolKit
|
1 进入ZLMediaKit目录执行 git submodule update --init 以下载ZLToolKit的代码
|
||||||
2 Open the project with cmake-gui and generate the vs project file.
|
2 使用cmake-gui打开工程并生成vs工程文件.
|
||||||
3 Find the project file (ZLMediaKit.sln), double-click to open it with vs2017.
|
3 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
|
||||||
4 Choose to compile Release version. Find the target file and run the test case.
|
4 选择编译Release 版本.
|
||||||
|
5 找到目标文件并运行测试用例.
|
||||||
```
|
```
|
||||||
## Usage
|
## 使用方法
|
||||||
|
- 作为服务器:
|
||||||
- As server:
|
|
||||||
```cpp
|
```cpp
|
||||||
TcpServer::Ptr rtspSrv(new TcpServer());
|
TcpServer::Ptr rtspSrv(new TcpServer());
|
||||||
TcpServer::Ptr rtmpSrv(new TcpServer());
|
TcpServer::Ptr rtmpSrv(new TcpServer());
|
||||||
@ -243,7 +252,7 @@ git submodule update --init
|
|||||||
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
|
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
|
||||||
```
|
```
|
||||||
|
|
||||||
- As player:
|
- 作为播放器:
|
||||||
```cpp
|
```cpp
|
||||||
MediaPlayer::Ptr player(new MediaPlayer());
|
MediaPlayer::Ptr player(new MediaPlayer());
|
||||||
weak_ptr<MediaPlayer> weakPlayer = player;
|
weak_ptr<MediaPlayer> weakPlayer = player;
|
||||||
@ -256,11 +265,11 @@ git submodule update --init
|
|||||||
|
|
||||||
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
||||||
if (!viedoTrack) {
|
if (!viedoTrack) {
|
||||||
WarnL << "none video Track!";
|
WarnL << "没有视频Track!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([](const Frame::Ptr &frame) {
|
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([](const Frame::Ptr &frame) {
|
||||||
//please decode video here
|
//此处解码并播放
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -268,11 +277,11 @@ git submodule update --init
|
|||||||
ErrorL << "OnShutdown:" << ex.what();
|
ErrorL << "OnShutdown:" << ex.what();
|
||||||
});
|
});
|
||||||
|
|
||||||
//rtp transport over tcp
|
//支持rtmp、rtsp
|
||||||
(*player)[Client::kRtpType] = Rtsp::RTP_TCP;
|
(*player)[Client::kRtpType] = Rtsp::RTP_TCP;
|
||||||
player->play("rtsp://admin:jzan123456@192.168.0.122/");
|
player->play("rtsp://admin:jzan123456@192.168.0.122/");
|
||||||
```
|
```
|
||||||
- As proxy server:
|
- 作为代理服务器:
|
||||||
```cpp
|
```cpp
|
||||||
//support rtmp and rtsp url
|
//support rtmp and rtsp url
|
||||||
//just support H264+AAC
|
//just support H264+AAC
|
||||||
@ -281,77 +290,94 @@ git submodule update --init
|
|||||||
map<string , PlayerProxy::Ptr> proxyMap;
|
map<string , PlayerProxy::Ptr> proxyMap;
|
||||||
int i=0;
|
int i=0;
|
||||||
for(auto url : urlList){
|
for(auto url : urlList){
|
||||||
|
//PlayerProxy构造函数前两个参数分别为应用名(app),流id(streamId)
|
||||||
|
//比如说应用为live,流id为0,那么直播地址为:
|
||||||
|
//http://127.0.0.1/live/0/hls.m3u8
|
||||||
|
//rtsp://127.0.0.1/live/0
|
||||||
|
//rtmp://127.0.0.1/live/0
|
||||||
|
//录像地址为:
|
||||||
|
//http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
||||||
|
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
||||||
|
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
||||||
PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i++).data()));
|
PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i++).data()));
|
||||||
player->play(url);
|
player->play(url);
|
||||||
proxyMap.emplace(string(url),player);
|
proxyMap.emplace(string(url),player);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- As puser:
|
- 作为推流客户端器:
|
||||||
```cpp
|
```cpp
|
||||||
PlayerProxy::Ptr player(new PlayerProxy("app","stream"));
|
PlayerProxy::Ptr player(new PlayerProxy("app","stream"));
|
||||||
|
//拉一个流,生成一个RtmpMediaSource,源的名称是"app/stream"
|
||||||
|
//你也可以以其他方式生成RtmpMediaSource,比如说MP4文件(请研读MediaReader代码)
|
||||||
player->play("rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
player->play("rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
||||||
|
|
||||||
RtmpPusher::Ptr pusher;
|
RtmpPusher::Ptr pusher;
|
||||||
|
//监听RtmpMediaSource注册事件,在PlayerProxy播放成功后触发。
|
||||||
NoticeCenter::Instance().addListener(nullptr,Config::Broadcast::kBroadcastRtmpSrcRegisted,
|
NoticeCenter::Instance().addListener(nullptr,Config::Broadcast::kBroadcastRtmpSrcRegisted,
|
||||||
[&pusher](BroadcastRtmpSrcRegistedArgs){
|
[&pusher](BroadcastRtmpSrcRegistedArgs){
|
||||||
|
//媒体源"app/stream"已经注册,这时方可新建一个RtmpPusher对象并绑定该媒体源
|
||||||
const_cast<RtmpPusher::Ptr &>(pusher).reset(new RtmpPusher(app,stream));
|
const_cast<RtmpPusher::Ptr &>(pusher).reset(new RtmpPusher(app,stream));
|
||||||
|
|
||||||
|
//推流地址,请改成你自己的服务器。
|
||||||
|
//这个范例地址(也是基于mediakit)是可用的,但是带宽只有1mb,访问可能很卡顿。
|
||||||
pusher->publish("rtmp://jizan.iok.la/live/test");
|
pusher->publish("rtmp://jizan.iok.la/live/test");
|
||||||
});
|
});
|
||||||
|
|
||||||
```
|
```
|
||||||
## Docker Image
|
## QA
|
||||||
You can pull a pre-built docker image from Docker Hub and run with
|
- 怎么测试服务器性能?
|
||||||
```bash
|
|
||||||
docker run -id -p 1935:1935 -p 8080:80 gemfield/zlmediakit
|
|
||||||
```
|
|
||||||
|
|
||||||
Dockerfile is also supplied to build images on Ubuntu 16.04
|
ZLMediaKit提供了测试性能的示例,代码在tests/test_benchmark.cpp。
|
||||||
```bash
|
|
||||||
cd docker
|
|
||||||
docker build -t zlmediakit .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Mirrors
|
这里是测试报告:[benchmark.md](https://github.com/xiongziliang/ZLMediaKit/blob/master/benchmark.md)
|
||||||
|
|
||||||
|
- github下载太慢了,有其他下载方式吗?
|
||||||
|
|
||||||
|
你可以在通过开源中国获取最新的代码,地址为:
|
||||||
|
|
||||||
[ZLToolKit](http://git.oschina.net/xiahcu/ZLToolKit)
|
[ZLToolKit](http://git.oschina.net/xiahcu/ZLToolKit)
|
||||||
|
|
||||||
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
|
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
|
||||||
|
|
||||||
|
|
||||||
## Licence
|
- 在windows下编译很多错误?
|
||||||
|
|
||||||
```
|
由于本项目主体代码在macOS/linux下开发,部分源码采用的是无bom头的UTF-8编码;由于windows对于utf-8支持不甚友好,所以如果发现编译错误请先尝试添 加bom头再编译。
|
||||||
MIT License
|
也可以通过参考这篇博客解决:
|
||||||
|
[vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题](https://blog.csdn.net/10km/article/details/80203286)
|
||||||
|
|
||||||
Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
## 参考案例
|
||||||
Copyright (c) 2019 Gemfield <gemfield@civilnet.cn>
|
- [IOS摄像头实时录制,生成rtsp/rtmp/hls/http-flv](https://gitee.com/xiahcu/IOSMedia)
|
||||||
Copyright (c) 2018 huohuo <913481084@qq.com>
|
- [IOS rtmp/rtsp播放器,视频推流器](https://gitee.com/xiahcu/IOSPlayer)
|
||||||
|
- [支持linux、windows、mac的rtmp/rtsp播放器](https://github.com/xiongziliang/ZLMediaPlayer)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
上述工程可能在最新的代码的情况下编译不过,请手动修改
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
## 授权协议
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
```
|
本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。
|
||||||
|
但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除;
|
||||||
|
由于使用本项目而产生的商业纠纷或侵权行为一概与本项项目及开发者无关,请自行承担法律风险。
|
||||||
|
|
||||||
|
## 联系方式
|
||||||
|
- 邮箱:<771730766@qq.com>(本项目相关或流媒体相关问题请走issue流程,否则恕不邮件答复)
|
||||||
|
- QQ群:542509000
|
||||||
|
|
||||||
|
## 怎么提问?
|
||||||
|
如果要对项目有相关疑问,建议您这么做:
|
||||||
|
- 1、仔细看下readme、wiki,如果有必要可以查看下issue.
|
||||||
|
- 2、如果您的问题还没解决,可以提issue.
|
||||||
|
- 3、有些问题,如果不具备参考性的,无需在issue提的,可以在qq群提.
|
||||||
|
- 4、QQ私聊一般不接受无偿技术咨询和支持(谈谈人生理想还是可以的😂),毕竟精力有限,谢谢理解.
|
||||||
|
|
||||||
|
## 捐赠
|
||||||
|
欢迎捐赠以便更好的推动项目的发展,谢谢您的支持!
|
||||||
|
|
||||||
|
[支付宝](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3919.JPG)
|
||||||
|
|
||||||
|
[微信](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3920.JPG)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
- Email:<771730766@qq.com>
|
|
||||||
- QQ chat group:542509000
|
|
||||||
|
|
||||||
|
|
||||||
|
380
README_CN.md
380
README_CN.md
@ -1,380 +0,0 @@
|
|||||||
![logo](https://raw.githubusercontent.com/zlmediakit/ZLMediaKit/master/logo.png)
|
|
||||||
# 一个基于C++11的高性能运营级流媒体服务框架
|
|
||||||
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
|
||||||
|
|
||||||
|
|
||||||
## 国内用户请使用gitee镜像下载
|
|
||||||
```
|
|
||||||
git clone --depth 1 https://gitee.com/xiahcu/ZLMediaKit
|
|
||||||
cd ZLMediaKit
|
|
||||||
git submodule update --init
|
|
||||||
```
|
|
||||||
## 项目特点
|
|
||||||
- 基于C++11开发,避免使用裸指针,代码稳定可靠;同时跨平台移植简单方便,代码清晰简洁。
|
|
||||||
- 打包多种流媒体协议(RTSP/RTMP/HLS/HTTP-FLV/Websocket-FLV),支持协议间的互相转换,提供一站式的服务。
|
|
||||||
- 使用epoll+线程池+异步网络IO模式开发,并发性能优越。
|
|
||||||
- 已实现主流的的H264/H265+AAC流媒体方案,代码精简,脉络清晰,适合学习。
|
|
||||||
- 编码格式与框架代码解耦,方便自由简洁的添加支持其他编码格式。
|
|
||||||
- 代码经过大量的稳定性、性能测试,可满足商用服务器项目。
|
|
||||||
- 支持linux、macos、ios、android、windows平台。
|
|
||||||
- 支持画面秒开(GOP缓存)、极低延时([500毫秒内,最低可达100毫秒](https://github.com/zlmediakit/ZLMediaKit/wiki/%E5%BB%B6%E6%97%B6%E6%B5%8B%E8%AF%95))。
|
|
||||||
- [ZLMediaKit高并发实现原理](https://github.com/xiongziliang/ZLMediaKit/wiki/ZLMediaKit%E9%AB%98%E5%B9%B6%E5%8F%91%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86)。
|
|
||||||
- 提供完善的标准C API,可以作SDK用,或供其他语言调用。
|
|
||||||
- 提供完整的MediaServer服务器,可以免开发直接部署为商用服务器。
|
|
||||||
|
|
||||||
## 项目定位
|
|
||||||
- 移动嵌入式跨平台流媒体解决方案。
|
|
||||||
- 商用级流媒体服务器。
|
|
||||||
- 网络编程二次开发SDK。
|
|
||||||
|
|
||||||
|
|
||||||
## 功能清单
|
|
||||||
- RTSP
|
|
||||||
- RTSP 服务器,支持RTMP/MP4转RTSP。
|
|
||||||
- RTSPS 服务器,支持亚马逊echo show这样的设备
|
|
||||||
- RTSP 播放器,支持RTSP代理,支持生成静音音频
|
|
||||||
- RTSP 推流客户端与服务器
|
|
||||||
- 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式 。
|
|
||||||
- 服务器/客户端完整支持Basic/Digest方式的登录鉴权,全异步可配置化的鉴权接口。
|
|
||||||
- 支持H265编码
|
|
||||||
- 服务器支持RTSP推流(包括`rtp over udp` `rtp over tcp`方式)
|
|
||||||
- 支持任意编码格式的rtsp推流,只是除H264/H265+AAC外无法转协议
|
|
||||||
|
|
||||||
- RTMP
|
|
||||||
- RTMP 播放服务器,支持RTSP/MP4转RTMP。
|
|
||||||
- RTMP 发布服务器,支持录制发布流。
|
|
||||||
- RTMP 播放器,支持RTMP代理,支持生成静音音频
|
|
||||||
- RTMP 推流客户端。
|
|
||||||
- 支持http-flv直播。
|
|
||||||
- 支持https-flv直播。
|
|
||||||
- 支持任意编码格式的rtmp推流,只是除H264/H265+AAC外无法转协议
|
|
||||||
|
|
||||||
- HLS
|
|
||||||
- 支持HLS文件生成,自带HTTP文件服务器。
|
|
||||||
- 支持播放鉴权,鉴权结果可以缓存为cookie
|
|
||||||
|
|
||||||
- HTTP[S]
|
|
||||||
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`。
|
|
||||||
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`,`文件上传器`。
|
|
||||||
- 完整HTTP API服务器,可以作为web后台开发框架。
|
|
||||||
- 支持跨域访问。
|
|
||||||
- 支持http客户端、服务器cookie
|
|
||||||
- 支持WebSocket服务器和客户端
|
|
||||||
- 支持http文件访问鉴权
|
|
||||||
|
|
||||||
- 其他
|
|
||||||
- 支持输入YUV+PCM自动生成RTSP/RTMP/HLS/MP4.
|
|
||||||
- 支持简单的telnet调试。
|
|
||||||
- 支持H264的解析,支持B帧的POC计算排序。
|
|
||||||
- 支持配置文件热加载
|
|
||||||
- 支持流量统计、推流播放鉴权等事件
|
|
||||||
- 支持rtsp/rtmp/http虚拟主机
|
|
||||||
- 支持flv、mp4文件录制
|
|
||||||
- 支持rtps/rtmp协议的mp4点播,支持seek
|
|
||||||
- 支持按需拉流,无人观看自动关断拉流
|
|
||||||
- 支持先拉流后推流,提高及时推流画面打开率
|
|
||||||
- 支持rtsp/rtmp/http-flv/hls播放鉴权(url参数方式)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 其他功能细节表
|
|
||||||
|
|
||||||
- 转协议:
|
|
||||||
|
|
||||||
| 功能/编码格式 | H264 | H265 | AAC | other |
|
|
||||||
| :------------------------------: | :--: | :--: | :--: | :---: |
|
|
||||||
| RTSP[S] --> RTMP/HTTP[S]-FLV/FLV | Y | N | Y | N |
|
|
||||||
| RTMP --> RTSP[S] | Y | N | Y | N |
|
|
||||||
| RTSP[S] --> HLS | Y | Y | Y | N |
|
|
||||||
| RTMP --> HLS | Y | N | Y | N |
|
|
||||||
| RTSP[S] --> MP4 | Y | Y | Y | N |
|
|
||||||
| RTMP --> MP4 | Y | N | Y | N |
|
|
||||||
| MP4 --> RTSP[S] | Y | N | Y | N |
|
|
||||||
| MP4 --> RTMP | Y | N | Y | N |
|
|
||||||
|
|
||||||
- 流生成:
|
|
||||||
|
|
||||||
| 功能/编码格式 | H264 | H265 | AAC | other |
|
|
||||||
| :------------------------------: | :--: | :--: | :--: | :---: |
|
|
||||||
| RTSP[S]推流 | Y | Y | Y | Y |
|
|
||||||
| RTSP拉流代理 | Y | Y | Y | Y |
|
|
||||||
| RTMP推流 | Y | Y | Y | Y |
|
|
||||||
| RTMP拉流代理 | Y | Y | Y | Y |
|
|
||||||
|
|
||||||
- RTP传输方式:
|
|
||||||
|
|
||||||
| 功能/RTP传输方式 | tcp | udp | http | udp_multicast |
|
|
||||||
| :-----------------: | :--: | :--: | :--: | :-----------: |
|
|
||||||
| RTSP[S] Play Server | Y | Y | Y | Y |
|
|
||||||
| RTSP[S] Push Server | Y | Y | N | N |
|
|
||||||
| RTSP Player | Y | Y | N | Y |
|
|
||||||
| RTSP Pusher | Y | Y | N | N |
|
|
||||||
|
|
||||||
|
|
||||||
- 支持的服务器类型列表
|
|
||||||
|
|
||||||
| 服务类型 | Y/N |
|
|
||||||
| :-----------------: | :--: |
|
|
||||||
| RTSP[S] Play Server | Y |
|
|
||||||
| RTSP[S] Push Server | Y |
|
|
||||||
| RTMP | Y |
|
|
||||||
| HTTP[S]/WebSocket[S] | Y |
|
|
||||||
|
|
||||||
- 支持的客户端类型
|
|
||||||
|
|
||||||
| 客户端类型 | Y/N |
|
|
||||||
| :---------: | :--: |
|
|
||||||
| RTSP Player | Y |
|
|
||||||
| RTSP Pusher | Y |
|
|
||||||
| RTMP Player | Y |
|
|
||||||
| RTMP Pusher | Y |
|
|
||||||
| HTTP[S] | Y |
|
|
||||||
| WebSocket[S] | Y |
|
|
||||||
|
|
||||||
## 后续任务
|
|
||||||
- 完善支持H265
|
|
||||||
|
|
||||||
## 编译要求
|
|
||||||
- 编译器支持C++11,GCC4.8/Clang3.3/VC2015或以上
|
|
||||||
- cmake3.2或以上
|
|
||||||
|
|
||||||
## 编译前必看!!!
|
|
||||||
|
|
||||||
- **必须使用git下载完整的代码,不要使用下载zip包的方式下载源码,否则子模块代码默认不下载!你可以像以下这样操作:**
|
|
||||||
```
|
|
||||||
git clone https://github.com/zlmediakit/ZLMediaKit.git
|
|
||||||
cd ZLMediaKit
|
|
||||||
git submodule update --init
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译(Linux)
|
|
||||||
- 我的编译环境
|
|
||||||
- Ubuntu16.04 64 bit + gcc5.4
|
|
||||||
- cmake 3.5.1
|
|
||||||
- 编译
|
|
||||||
|
|
||||||
```
|
|
||||||
//如果是centos6.x,需要先安装较新版本的gcc以及cmake,然后打开脚本build_for_linux.sh手动编译
|
|
||||||
//如果是ubuntu这样的比较新的系统版本可以直接操作第4步
|
|
||||||
|
|
||||||
1、安装GCC5.2(如果gcc版本高于4.7可以跳过此步骤)
|
|
||||||
sudo yum install centos-release-scl -y
|
|
||||||
sudo yum install devtoolset-4-toolchain -y
|
|
||||||
scl enable devtoolset-4 bash
|
|
||||||
|
|
||||||
2、安装cmake
|
|
||||||
#需要安装新版本cmake,当然你也可以通过yum或者apt-get方式安装(前提是版本够新)
|
|
||||||
tar -xvf cmake-3.10.0-rc4.tar.gz
|
|
||||||
cd cmake-3.10.0-rc4
|
|
||||||
./configure
|
|
||||||
make -j4
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
3、切换高版本gcc
|
|
||||||
scl enable devtoolset-4 bash
|
|
||||||
|
|
||||||
4、编译
|
|
||||||
cd ZLMediaKit
|
|
||||||
./build_for_linux.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译(macOS)
|
|
||||||
- 我的编译环境
|
|
||||||
- macOS Sierra(10.12.1) + xcode8.3.1
|
|
||||||
- Homebrew 1.1.3
|
|
||||||
- cmake 3.8.0
|
|
||||||
- 编译
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ZLMediaKit
|
|
||||||
./build_for_mac.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译(iOS)
|
|
||||||
- 编译环境:`请参考macOS的编译指导。`
|
|
||||||
- 编译
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ZLMediaKit
|
|
||||||
./build_for_ios.sh
|
|
||||||
```
|
|
||||||
- 你也可以生成Xcode工程再编译,[了解更多](https://github.com/leetal/ios-cmake):
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ZLMediaKit
|
|
||||||
mkdir -p build
|
|
||||||
cd build
|
|
||||||
# 生成Xcode工程,工程文件在build目录下
|
|
||||||
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
|
|
||||||
```
|
|
||||||
|
|
||||||
## 编译(Android)
|
|
||||||
- 我的编译环境
|
|
||||||
- macOS Sierra(10.12.1) + xcode8.3.1
|
|
||||||
- Homebrew 1.1.3
|
|
||||||
- cmake 3.8.0
|
|
||||||
- [android-ndk-r14b](https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip)
|
|
||||||
- 编译
|
|
||||||
|
|
||||||
```
|
|
||||||
cd ZLMediaKit
|
|
||||||
export ANDROID_NDK_ROOT=/path/to/ndk
|
|
||||||
./build_for_android.sh
|
|
||||||
```
|
|
||||||
## 编译(Windows)
|
|
||||||
- 我的编译环境
|
|
||||||
- windows 10
|
|
||||||
- visual studio 2017
|
|
||||||
- [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
|
|
||||||
|
|
||||||
- 编译
|
|
||||||
```
|
|
||||||
1 进入ZLMediaKit目录执行 git submodule update --init 以下载ZLToolKit的代码
|
|
||||||
2 使用cmake-gui打开工程并生成vs工程文件.
|
|
||||||
3 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
|
|
||||||
4 选择编译Release 版本.
|
|
||||||
5 找到目标文件并运行测试用例.
|
|
||||||
```
|
|
||||||
## 使用方法
|
|
||||||
- 作为服务器:
|
|
||||||
```cpp
|
|
||||||
TcpServer::Ptr rtspSrv(new TcpServer());
|
|
||||||
TcpServer::Ptr rtmpSrv(new TcpServer());
|
|
||||||
TcpServer::Ptr httpSrv(new TcpServer());
|
|
||||||
TcpServer::Ptr httpsSrv(new TcpServer());
|
|
||||||
|
|
||||||
rtspSrv->start<RtspSession>(mINI::Instance()[Config::Rtsp::kPort]);
|
|
||||||
rtmpSrv->start<RtmpSession>(mINI::Instance()[Config::Rtmp::kPort]);
|
|
||||||
httpSrv->start<HttpSession>(mINI::Instance()[Config::Http::kPort]);
|
|
||||||
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
|
|
||||||
```
|
|
||||||
|
|
||||||
- 作为播放器:
|
|
||||||
```cpp
|
|
||||||
MediaPlayer::Ptr player(new MediaPlayer());
|
|
||||||
weak_ptr<MediaPlayer> weakPlayer = player;
|
|
||||||
player->setOnPlayResult([weakPlayer](const SockException &ex) {
|
|
||||||
InfoL << "OnPlayResult:" << ex.what();
|
|
||||||
auto strongPlayer = weakPlayer.lock();
|
|
||||||
if (ex || !strongPlayer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
|
||||||
if (!viedoTrack) {
|
|
||||||
WarnL << "没有视频Track!";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([](const Frame::Ptr &frame) {
|
|
||||||
//此处解码并播放
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
player->setOnShutdown([](const SockException &ex) {
|
|
||||||
ErrorL << "OnShutdown:" << ex.what();
|
|
||||||
});
|
|
||||||
|
|
||||||
//支持rtmp、rtsp
|
|
||||||
(*player)[Client::kRtpType] = Rtsp::RTP_TCP;
|
|
||||||
player->play("rtsp://admin:jzan123456@192.168.0.122/");
|
|
||||||
```
|
|
||||||
- 作为代理服务器:
|
|
||||||
```cpp
|
|
||||||
//support rtmp and rtsp url
|
|
||||||
//just support H264+AAC
|
|
||||||
auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks",
|
|
||||||
"rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"};
|
|
||||||
map<string , PlayerProxy::Ptr> proxyMap;
|
|
||||||
int i=0;
|
|
||||||
for(auto url : urlList){
|
|
||||||
//PlayerProxy构造函数前两个参数分别为应用名(app),流id(streamId)
|
|
||||||
//比如说应用为live,流id为0,那么直播地址为:
|
|
||||||
//http://127.0.0.1/live/0/hls.m3u8
|
|
||||||
//rtsp://127.0.0.1/live/0
|
|
||||||
//rtmp://127.0.0.1/live/0
|
|
||||||
//录像地址为:
|
|
||||||
//http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
|
||||||
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
|
||||||
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
|
|
||||||
PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i++).data()));
|
|
||||||
player->play(url);
|
|
||||||
proxyMap.emplace(string(url),player);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- 作为推流客户端器:
|
|
||||||
```cpp
|
|
||||||
PlayerProxy::Ptr player(new PlayerProxy("app","stream"));
|
|
||||||
//拉一个流,生成一个RtmpMediaSource,源的名称是"app/stream"
|
|
||||||
//你也可以以其他方式生成RtmpMediaSource,比如说MP4文件(请研读MediaReader代码)
|
|
||||||
player->play("rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
|
||||||
|
|
||||||
RtmpPusher::Ptr pusher;
|
|
||||||
//监听RtmpMediaSource注册事件,在PlayerProxy播放成功后触发。
|
|
||||||
NoticeCenter::Instance().addListener(nullptr,Config::Broadcast::kBroadcastRtmpSrcRegisted,
|
|
||||||
[&pusher](BroadcastRtmpSrcRegistedArgs){
|
|
||||||
//媒体源"app/stream"已经注册,这时方可新建一个RtmpPusher对象并绑定该媒体源
|
|
||||||
const_cast<RtmpPusher::Ptr &>(pusher).reset(new RtmpPusher(app,stream));
|
|
||||||
|
|
||||||
//推流地址,请改成你自己的服务器。
|
|
||||||
//这个范例地址(也是基于mediakit)是可用的,但是带宽只有1mb,访问可能很卡顿。
|
|
||||||
pusher->publish("rtmp://jizan.iok.la/live/test");
|
|
||||||
});
|
|
||||||
|
|
||||||
```
|
|
||||||
## QA
|
|
||||||
- 怎么测试服务器性能?
|
|
||||||
|
|
||||||
ZLMediaKit提供了测试性能的示例,代码在tests/test_benchmark.cpp。
|
|
||||||
|
|
||||||
这里是测试报告:[benchmark.md](https://github.com/xiongziliang/ZLMediaKit/blob/master/benchmark.md)
|
|
||||||
|
|
||||||
- github下载太慢了,有其他下载方式吗?
|
|
||||||
|
|
||||||
你可以在通过开源中国获取最新的代码,地址为:
|
|
||||||
|
|
||||||
[ZLToolKit](http://git.oschina.net/xiahcu/ZLToolKit)
|
|
||||||
|
|
||||||
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
|
|
||||||
|
|
||||||
|
|
||||||
- 在windows下编译很多错误?
|
|
||||||
|
|
||||||
由于本项目主体代码在macOS/linux下开发,部分源码采用的是无bom头的UTF-8编码;由于windows对于utf-8支持不甚友好,所以如果发现编译错误请先尝试添 加bom头再编译。
|
|
||||||
也可以通过参考这篇博客解决:
|
|
||||||
[vs2015:/utf-8选项解决UTF-8 without BOM 源码中文输出乱码问题](https://blog.csdn.net/10km/article/details/80203286)
|
|
||||||
|
|
||||||
## 参考案例
|
|
||||||
- [IOS摄像头实时录制,生成rtsp/rtmp/hls/http-flv](https://gitee.com/xiahcu/IOSMedia)
|
|
||||||
- [IOS rtmp/rtsp播放器,视频推流器](https://gitee.com/xiahcu/IOSPlayer)
|
|
||||||
- [支持linux、windows、mac的rtmp/rtsp播放器](https://github.com/xiongziliang/ZLMediaPlayer)
|
|
||||||
|
|
||||||
上述工程可能在最新的代码的情况下编译不过,请手动修改
|
|
||||||
|
|
||||||
|
|
||||||
## 授权协议
|
|
||||||
|
|
||||||
本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。
|
|
||||||
但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除;
|
|
||||||
由于使用本项目而产生的商业纠纷或侵权行为一概与本项项目及开发者无关,请自行承担法律风险。
|
|
||||||
|
|
||||||
## 联系方式
|
|
||||||
- 邮箱:<771730766@qq.com>(本项目相关或流媒体相关问题请走issue流程,否则恕不邮件答复)
|
|
||||||
- QQ群:542509000
|
|
||||||
|
|
||||||
## 怎么提问?
|
|
||||||
如果要对项目有相关疑问,建议您这么做:
|
|
||||||
- 1、仔细看下readme、wiki,如果有必要可以查看下issue.
|
|
||||||
- 2、如果您的问题还没解决,可以提issue.
|
|
||||||
- 3、有些问题,如果不具备参考性的,无需在issue提的,可以在qq群提.
|
|
||||||
- 4、QQ私聊一般不接受无偿技术咨询和支持(谈谈人生理想还是可以的😂),毕竟精力有限,谢谢理解.
|
|
||||||
|
|
||||||
## 捐赠
|
|
||||||
欢迎捐赠以便更好的推动项目的发展,谢谢您的支持!
|
|
||||||
|
|
||||||
[支付宝](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3919.JPG)
|
|
||||||
|
|
||||||
[微信](https://raw.githubusercontent.com/xiongziliang/other/master/IMG_3920.JPG)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
356
README_en.md
Normal file
356
README_en.md
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
![logo](https://raw.githubusercontent.com/zlmediakit/ZLMediaKit/master/logo.png)
|
||||||
|
|
||||||
|
# A lightweight ,high performance and stable stream server and client framework based on C++11.
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/xiongziliang/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xiongziliang/ZLMediaKit)
|
||||||
|
|
||||||
|
|
||||||
|
## Why ZLMediaKit?
|
||||||
|
- Developed based on C++ 11, the code is stable and reliable, avoiding the use of raw pointers, cross-platform porting is simple and convenient, and the code is clear and concise.
|
||||||
|
- Support rich streaming media protocols(`RTSP/RTMP/HLS/HTTP-FLV/Websocket-flv`),and support Inter-protocol conversion.
|
||||||
|
- Multiplexing asynchronous network IO based on epoll and multi thread,extreme performance.
|
||||||
|
- Well performance and stable test,can be used commercially.
|
||||||
|
- Support linux, macos, ios, android, Windows Platforms.
|
||||||
|
- Very low latency(lower then one second), video opened immediately.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- RTSP
|
||||||
|
- RTSP[S] server,support rtsp push.
|
||||||
|
- RTSP player and pusher.
|
||||||
|
- RTP Transport : `rtp over udp` `rtp over tcp` `rtp over http` `rtp udp multicast` .
|
||||||
|
- Basic/Digest/Url Authentication.
|
||||||
|
- H265/H264/AAC codec.
|
||||||
|
- Recorded as mp4.
|
||||||
|
- Vod of mp4.
|
||||||
|
|
||||||
|
- RTMP
|
||||||
|
- RTMP server,support player and pusher.
|
||||||
|
- RTMP player and pusher.
|
||||||
|
- Support HTTP-FLV player.
|
||||||
|
- H264/AAC codec.
|
||||||
|
- Recorded as flv or mp4.
|
||||||
|
- Vod of mp4.
|
||||||
|
|
||||||
|
- HLS
|
||||||
|
- RTSP RTMP can be converted into HLS,built-in HTTP server.
|
||||||
|
- Play authentication based on cookie.
|
||||||
|
|
||||||
|
- HTTP[S]
|
||||||
|
- HTTP server,suppor directory meun、RESTful http api.
|
||||||
|
- HTTP client,downloader,uploader,and http api requester.
|
||||||
|
- Cookie supported.
|
||||||
|
- WebSocket Server and Client.
|
||||||
|
- File access authentication.
|
||||||
|
|
||||||
|
- Others
|
||||||
|
- Support stream proxy by ffmpeg.
|
||||||
|
- RESTful http api and http hook event api.
|
||||||
|
- Config file hot loading.
|
||||||
|
- Vhost supported.
|
||||||
|
- Auto close stream when nobody played.
|
||||||
|
- Play and push authentication.
|
||||||
|
- Pull stream on Demand.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Protocol conversion:
|
||||||
|
|
||||||
|
| protocol/codec | H264 | H265 | AAC | other |
|
||||||
|
| :------------------------------: | :--: | :--: | :--: | :---: |
|
||||||
|
| RTSP[S] --> RTMP/HTTP[S]-FLV/FLV | Y | N | Y | N |
|
||||||
|
| RTMP --> RTSP[S] | Y | N | Y | N |
|
||||||
|
| RTSP[S] --> HLS | Y | Y | Y | N |
|
||||||
|
| RTMP --> HLS | Y | N | Y | N |
|
||||||
|
| RTSP[S] --> MP4 | Y | Y | Y | N |
|
||||||
|
| RTMP --> MP4 | Y | N | Y | N |
|
||||||
|
| MP4 --> RTSP[S] | Y | N | Y | N |
|
||||||
|
| MP4 --> RTMP | Y | N | Y | N |
|
||||||
|
|
||||||
|
- Stream generation:
|
||||||
|
|
||||||
|
| feature/codec | H264 | H265 | AAC | other |
|
||||||
|
| :-----------: | :--: | :--: | :--: | :---: |
|
||||||
|
| RTSP[S] push | Y | Y | Y | Y |
|
||||||
|
| RTSP proxy | Y | Y | Y | Y |
|
||||||
|
| RTMP push | Y | Y | Y | Y |
|
||||||
|
| RTMP proxy | Y | Y | Y | Y |
|
||||||
|
|
||||||
|
- RTP transport:
|
||||||
|
|
||||||
|
| feature/transport | tcp | udp | http | udp_multicast |
|
||||||
|
| :-----------------: | :--: | :--: | :--: | :-----------: |
|
||||||
|
| RTSP[S] Play Server | Y | Y | Y | Y |
|
||||||
|
| RTSP[S] Push Server | Y | Y | N | N |
|
||||||
|
| RTSP Player | Y | Y | N | Y |
|
||||||
|
| RTSP Pusher | Y | Y | N | N |
|
||||||
|
|
||||||
|
|
||||||
|
- Server supported:
|
||||||
|
|
||||||
|
| Server | Y/N |
|
||||||
|
| :-----------------: | :--: |
|
||||||
|
| RTSP[S] Play Server | Y |
|
||||||
|
| RTSP[S] Push Server | Y |
|
||||||
|
| RTMP | Y |
|
||||||
|
| HTTP[S]/WebSocket[S] | Y |
|
||||||
|
|
||||||
|
- Client supported:
|
||||||
|
|
||||||
|
| Client | Y/N |
|
||||||
|
| :---------: | :--: |
|
||||||
|
| RTSP Player | Y |
|
||||||
|
| RTSP Pusher | Y |
|
||||||
|
| RTMP Player | Y |
|
||||||
|
| RTMP Pusher | Y |
|
||||||
|
| HTTP[S] | Y |
|
||||||
|
| WebSocket[S] | Y |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## System Requirements
|
||||||
|
|
||||||
|
- Compiler support c++11,GCC4.8/Clang3.3/VC2015 or above.
|
||||||
|
- cmake3.1 or above.
|
||||||
|
- All Linux , both 32 and 64 bits
|
||||||
|
- Apple OSX(Darwin), both 32 and 64bits.
|
||||||
|
- All hardware with x86/x86_64/arm/mips cpu.
|
||||||
|
- Windows.
|
||||||
|
|
||||||
|
## How to build
|
||||||
|
|
||||||
|
It is recommended to compile on Ubuntu or MacOS,compiling on windows is cumbersome, and some features are not compiled by default.
|
||||||
|
|
||||||
|
### Before build
|
||||||
|
- **You must use git to clone the complete code. Do not download the source code by downloading zip package. Otherwise, the sub-module code will not be downloaded by default.You can do it like this:**
|
||||||
|
```
|
||||||
|
git clone https://github.com/zlmediakit/ZLMediaKit.git
|
||||||
|
cd ZLMediaKit
|
||||||
|
git submodule update --init
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build on linux
|
||||||
|
|
||||||
|
- My environment
|
||||||
|
- Ubuntu16.04 64 bit and gcc5.4
|
||||||
|
- cmake 3.5.1
|
||||||
|
- Guidance
|
||||||
|
|
||||||
|
```
|
||||||
|
# If it is on centos6.x, you need to install the newer version of GCC and cmake first,
|
||||||
|
# and then compile manually according to the script "build_for_linux.sh".
|
||||||
|
# If it is on a newer version of a system such as Ubuntu or Debain,
|
||||||
|
# step 4 can be manipulated directly.
|
||||||
|
|
||||||
|
# 1、Install GCC5.2 (this step can be skipped if the GCC version is higher than 4.7)
|
||||||
|
sudo yum install centos-release-scl -y
|
||||||
|
sudo yum install devtoolset-4-toolchain -y
|
||||||
|
scl enable devtoolset-4 bash
|
||||||
|
|
||||||
|
# 2、Install cmake (this step can be skipped if the cmake version is higher than 3.1)
|
||||||
|
tar -xvf cmake-3.10.0-rc4.tar.gz #you need download cmake source file manually
|
||||||
|
cd cmake-3.10.0-rc4
|
||||||
|
./configure
|
||||||
|
make -j4
|
||||||
|
sudo make install
|
||||||
|
|
||||||
|
# 3、Switch to high version GCC
|
||||||
|
scl enable devtoolset-4 bash
|
||||||
|
|
||||||
|
# 4、build
|
||||||
|
cd ZLMediaKit
|
||||||
|
./build_for_linux.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build on macOS
|
||||||
|
|
||||||
|
- My environment
|
||||||
|
- macOS Sierra(10.12.1) + xcode8.3.1
|
||||||
|
- Homebrew 1.1.3
|
||||||
|
- cmake 3.8.0
|
||||||
|
- Guidance
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ZLMediaKit
|
||||||
|
./build_for_mac.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build on iOS
|
||||||
|
|
||||||
|
This build method is no longer recommended.It is recommended that make Xcode project by yourself.
|
||||||
|
|
||||||
|
- My environment
|
||||||
|
|
||||||
|
Same with Build on macOS
|
||||||
|
|
||||||
|
|
||||||
|
- You can generate Xcode projects and recompile them , [learn more](https://github.com/leetal/ios-cmake):
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ZLMediaKit
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
# Generate Xcode project, project file is in build directory
|
||||||
|
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Build on Android
|
||||||
|
|
||||||
|
Now you can open android sudio project in `Android` folder,this is a `aar library` and damo project.
|
||||||
|
|
||||||
|
- My environment
|
||||||
|
- macOS Sierra(10.12.1) + xcode8.3.1
|
||||||
|
- Homebrew 1.1.3
|
||||||
|
- cmake 3.8.0
|
||||||
|
- [android-ndk-r14b](https://dl.google.com/android/repository/android-ndk-r14b-darwin-x86_64.zip)
|
||||||
|
- Guidance
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ZLMediaKit
|
||||||
|
export ANDROID_NDK_ROOT=/path/to/ndk
|
||||||
|
./build_for_android.sh
|
||||||
|
```
|
||||||
|
### Build on Windows
|
||||||
|
|
||||||
|
- My environment
|
||||||
|
- windows 10
|
||||||
|
- visual studio 2017
|
||||||
|
- [cmake-gui](https://cmake.org/files/v3.10/cmake-3.10.0-rc1-win32-x86.msi)
|
||||||
|
|
||||||
|
- Guidance
|
||||||
|
```
|
||||||
|
1 Enter the ZLMediaKit directory and execute git submodule update -- init downloads the code for ZLToolKit
|
||||||
|
2 Open the project with cmake-gui and generate the vs project file.
|
||||||
|
3 Find the project file (ZLMediaKit.sln), double-click to open it with vs2017.
|
||||||
|
4 Choose to compile Release version. Find the target file and run the test case.
|
||||||
|
```
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
- As server:
|
||||||
|
```cpp
|
||||||
|
TcpServer::Ptr rtspSrv(new TcpServer());
|
||||||
|
TcpServer::Ptr rtmpSrv(new TcpServer());
|
||||||
|
TcpServer::Ptr httpSrv(new TcpServer());
|
||||||
|
TcpServer::Ptr httpsSrv(new TcpServer());
|
||||||
|
|
||||||
|
rtspSrv->start<RtspSession>(mINI::Instance()[Config::Rtsp::kPort]);
|
||||||
|
rtmpSrv->start<RtmpSession>(mINI::Instance()[Config::Rtmp::kPort]);
|
||||||
|
httpSrv->start<HttpSession>(mINI::Instance()[Config::Http::kPort]);
|
||||||
|
httpsSrv->start<HttpsSession>(mINI::Instance()[Config::Http::kSSLPort]);
|
||||||
|
```
|
||||||
|
|
||||||
|
- As player:
|
||||||
|
```cpp
|
||||||
|
MediaPlayer::Ptr player(new MediaPlayer());
|
||||||
|
weak_ptr<MediaPlayer> weakPlayer = player;
|
||||||
|
player->setOnPlayResult([weakPlayer](const SockException &ex) {
|
||||||
|
InfoL << "OnPlayResult:" << ex.what();
|
||||||
|
auto strongPlayer = weakPlayer.lock();
|
||||||
|
if (ex || !strongPlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto viedoTrack = strongPlayer->getTrack(TrackVideo);
|
||||||
|
if (!viedoTrack) {
|
||||||
|
WarnL << "none video Track!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
viedoTrack->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([](const Frame::Ptr &frame) {
|
||||||
|
//please decode video here
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
player->setOnShutdown([](const SockException &ex) {
|
||||||
|
ErrorL << "OnShutdown:" << ex.what();
|
||||||
|
});
|
||||||
|
|
||||||
|
//rtp transport over tcp
|
||||||
|
(*player)[Client::kRtpType] = Rtsp::RTP_TCP;
|
||||||
|
player->play("rtsp://admin:jzan123456@192.168.0.122/");
|
||||||
|
```
|
||||||
|
- As proxy server:
|
||||||
|
```cpp
|
||||||
|
//support rtmp and rtsp url
|
||||||
|
//just support H264+AAC
|
||||||
|
auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks",
|
||||||
|
"rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"};
|
||||||
|
map<string , PlayerProxy::Ptr> proxyMap;
|
||||||
|
int i=0;
|
||||||
|
for(auto url : urlList){
|
||||||
|
PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i++).data()));
|
||||||
|
player->play(url);
|
||||||
|
proxyMap.emplace(string(url),player);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- As puser:
|
||||||
|
```cpp
|
||||||
|
PlayerProxy::Ptr player(new PlayerProxy("app","stream"));
|
||||||
|
player->play("rtmp://live.hkstv.hk.lxdns.com/live/hks");
|
||||||
|
|
||||||
|
RtmpPusher::Ptr pusher;
|
||||||
|
NoticeCenter::Instance().addListener(nullptr,Config::Broadcast::kBroadcastRtmpSrcRegisted,
|
||||||
|
[&pusher](BroadcastRtmpSrcRegistedArgs){
|
||||||
|
const_cast<RtmpPusher::Ptr &>(pusher).reset(new RtmpPusher(app,stream));
|
||||||
|
pusher->publish("rtmp://jizan.iok.la/live/test");
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
## Docker Image
|
||||||
|
You can pull a pre-built docker image from Docker Hub and run with
|
||||||
|
```bash
|
||||||
|
docker run -id -p 1935:1935 -p 8080:80 gemfield/zlmediakit
|
||||||
|
```
|
||||||
|
|
||||||
|
Dockerfile is also supplied to build images on Ubuntu 16.04
|
||||||
|
```bash
|
||||||
|
cd docker
|
||||||
|
docker build -t zlmediakit .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Mirrors
|
||||||
|
|
||||||
|
[ZLToolKit](http://git.oschina.net/xiahcu/ZLToolKit)
|
||||||
|
|
||||||
|
[ZLMediaKit](http://git.oschina.net/xiahcu/ZLMediaKit)
|
||||||
|
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
```
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
|
||||||
|
Copyright (c) 2019 Gemfield <gemfield@civilnet.cn>
|
||||||
|
Copyright (c) 2018 huohuo <913481084@qq.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
- Email:<771730766@qq.com>
|
||||||
|
- QQ chat group:542509000
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user