ZLMediaKit是一款开源的轻量级流媒体服务器框架,由国内开发者开发维护。它采用C++11编写,支持RTSP、RTMP、HLS、HTTP-FLV等多种流媒体协议,能够实现低延迟的直播推拉流服务。我在实际部署中发现,其单机性能可轻松支撑500路以上的720P直播流转发,资源占用却不到同类产品的60%。
这个框架最大的特点在于其模块化设计——将流媒体处理流程拆解为独立的协议转换、流管理、事件通知等组件。就像搭积木一样,你可以根据业务需求自由组合这些模块。比如我们团队就曾基于ZLMediaKit的核心流处理引擎,仅用两周时间就定制出了一套支持私有协议的安防监控系统。
ZLMediaKit的协议支持能力堪称全面:
实测在跨协议转推场景下(如RTMP进→HLS出),同一路流的不同协议输出时间差可控制在200ms内。这得益于其内部的统一时间戳同步机制——所有输入流都会被转换为统一的PTS时间基准。
框架在性能方面做了多处针对性优化:
在我们的压力测试中,一台8核16G的云服务器可以稳定承载:
推荐使用Ubuntu 20.04 LTS作为生产环境:
bash复制# 安装依赖
sudo apt install -y gcc g++ cmake openssl libssl-dev
# 克隆源码
git clone --depth 1 https://github.com/ZLMediaKit/ZLMediaKit.git
cd ZLMediaKit
# 编译(启用调试日志)
mkdir build && cd build
cmake .. -DENABLE_DEBUG=ON
make -j$(nproc)
编译完成后会生成三个关键二进制文件:
MediaServer:主服务程序ffmpeg:定制版转码工具test_client:测试客户端config.ini中的核心参数:
ini复制[api]
secret=your_api_key # 用于RESTful API鉴权
[rtmp]
port=1935
timeout_sec=15 # 推流超时时间
[hls]
seg_num=5 # 保留的分片数
seg_duration=2 # 每个分片时长(秒)
重要提示:生产环境务必修改默认API密钥,我们曾遭遇过因使用默认密钥导致的未授权访问事件。
ZLMediaKit提供了完善的插件机制。以开发一个推流鉴权插件为例:
WebApiPlugin基类cpp复制class AuthPlugin : public WebApiPlugin {
public:
virtual bool onConnect(const Parser& parser) {
string token = parser.getUrlArgs()["token"];
return verifyToken(token); // 实现自己的验证逻辑
}
};
cpp复制Registry::registerPlugin(make_shared<AuthPlugin>());
对于超大规模应用,我们设计了一套集群方案:
通过ffmpeg的-re参数实现源站到边缘节点的级联推流:
bash复制ffmpeg -re -i rtmp://center/live/stream -c copy -f flv rtmp://edge1/live/stream
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 推流成功但无法播放 | HLS分片未生成 | 检查hls.save_path目录权限 |
| 高并发下内存暴涨 | 内存池配置过小 | 调整[memory]段的pool_size |
| RTMP握手失败 | 防火墙拦截 | 开放1935端口TCP/UDP |
ini复制[shell]
sock_buf_size=204800 # 调大Socket缓冲区
bash复制./MediaServer -l warn
ini复制[thread]
pool_size=16
某在线教育平台采用ZLMediaKit实现:
[rtmp]段的gop_cache减少首屏时间-preset ultrafast参数降低编码延迟在智慧工地项目中,我们将其改造为:
通过内置的HTTP API获取状态:
bash复制curl http://127.0.0.1:8080/api/statistic
返回示例:
json复制{
"code": 0,
"data": {
"connections": 142,
"streams": 35,
"cpu_usage": 23.7
}
}
编写exporter采集关键指标:
go复制func collectStreamMetrics() {
resp, _ := http.Get(apiUrl)
var data StatData
json.Unmarshal(resp.Body, &data)
streamGauge.Set(float64(data.Streams))
}
配合Grafana展示的监控看板应包括:
ini复制[shell]
max_connections=5000
nginx复制limit_conn_zone $binary_remote_addr zone=conn:10m;
limit_req_zone $binary_remote_addr zone=req:10m rate=30r/s;
ini复制[rtmp]
ssl_on=1
ssl_cert=/path/to/cert.pem
bash复制./MediaServer -s /path/to/cert.pem -k /path/to/key.pem
核心模块分布:
src/RTMP:RTMP协议实现src/RTP:RTP封包处理src/Http:HTTP服务框架src/Player:播放器逻辑建议从MediaServer.cpp的main()函数开始跟踪启动流程。
添加新协议的通用步骤:
Socket类实现网络层MediaSource接口处理媒体流Registry我们曾用这种方式增加了SRT协议支持,实测延迟比RTMP降低40%。
Android端推荐使用IjkPlayer:
java复制IjkMediaPlayer.loadLibrariesOnce(null);
IjkMediaPlayer ijkPlayer = new IjkMediaPlayer();
ijkPlayer.setDataSource("http://server/live/stream.flv");
Web端建议使用flv.js:
javascript复制import FLVJS from 'flv.js';
const player = FLVJS.createPlayer({
type: 'flv',
url: 'http://server/live/stream.flv'
});
player.attachMediaElement(videoElement);
与其他主流方案的基准测试数据(相同硬件环境):
| 方案 | 100路720P CPU占用 | 启动时间 | 内存占用 |
|---|---|---|---|
| ZLMediaKit | 38% | 1.2s | 420MB |
| SRS | 52% | 2.8s | 680MB |
| Nginx-RTMP | 47% | 0.8s | 560MB |
测试条件:Intel Xeon E5-2680v4 @ 2.4GHz, 16GB RAM, Ubuntu 20.04
通过重写malloc实现内存监控:
cpp复制void* my_malloc(size_t size) {
stat.mem_usage += size;
return original_malloc(size);
}
使用AWK统计错误日志:
bash复制awk '/ERROR/{err[$5]++} END{for(i in err) print i,err[i]}' logs/error.log
bash复制# 增加文件描述符限制
echo "fs.file-max = 1000000" >> /etc/sysctl.conf
# 调整TCP缓冲区
sysctl -w net.ipv4.tcp_mem='786432 2097152 3145728'
建议定期进行以下演练:
我们设计的自动化演练脚本包含:
传统三次握手流程:
ZLMediaKit的改进:
动态分片算法:
math复制seg_duration = max(2, min(6, network_rtt * 2))
根据网络状况自动调整分片时长。
社区近期重点方向:
建议关注项目的roadmap.md文件,我们团队已提交了SRT相关的改进提案。