什么是ZLMediaKit?
ZLMediaKit 是一個基于C++11的高性能流媒體服務器框架,支持RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV等多種流媒體協議。它具有以下特點:
-
跨平臺支持(Linux、Windows、macOS)
-
高性能,支持高并發
-
低延遲
-
支持多種協議轉換
-
開源免費(MIT許可證)
安裝ZLMediaKit
Linux/macOS 編譯安裝
1.安裝依賴項:
bash
# Ubuntu/Debian
sudo apt install build-essential cmake git
sudo apt install libssl-dev libsdl-dev libavcodec-dev libavutil-dev libavformat-dev# CentOS
sudo yum install -y gcc-c++ cmake git
sudo yum install -y openssl-devel SDL2-devel ffmpeg-devel# macOS (使用Homebrew)
brew install cmake openssl ffmpeg sdl2
2.克隆代碼庫:
bash
git clone --depth 1 https://github.com/ZLMediaKit/ZLMediaKit.git
cd ZLMediaKit
git submodule update --init
3.編譯:
bash
mkdir build
cd build
cmake ..
make -j4
Windows 編譯安裝
-
安裝Visual Studio 2017或更高版本
-
安裝CMake
-
使用CMake生成Visual Studio項目文件
-
用Visual Studio打開并編譯
基本使用
啟動服務器
bash
# Linux/macOS
cd ZLMediaKit/release/linux/Debug
./MediaServer -d & # 后臺運行# Windows
cd ZLMediaKit/release/windows/Debug
MediaServer.exe
配置文件
文件位置
-
默認路徑:與?
MediaServer
?可執行文件同目錄 -
指定路徑:啟動時通過?
-c
?參數指定,如?./MediaServer -c /path/to/config.ini
配置文件結構
[api] 部分 - HTTP API 配置
ini
[api]
apiDebug=1 ; 是否啟用API調試模式(1啟用)
secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc ; API調用密鑰
defaultSnap=./www/logo.png ; 截圖默認圖片
[ffmpeg] 部分 - FFmpeg 相關配置
ini
[ffmpeg]
bin=/usr/bin/ffmpeg ; ffmpeg路徑
cmd=%s -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
snap=%s -i %s -y -f mjpeg -frames:v 1 %s
log=/var/log/ffmpeg.log ; ffmpeg日志文件路徑
[general] 部分 - 通用配置
ini
[general]
enableVhost=0 ; 是否啟用虛擬主機(1啟用)
flowThreshold=1024 ; 流量統計閾值(KB)
maxStreamWaitMS=15000 ; 等待流注冊超時時間(毫秒)
streamNoneReaderDelayMS=20000 ; 無觀眾時流關閉延遲(毫秒)
addMuteAudio=1 ; 是否添加靜音音頻(當源只有視頻時)
resetWhenRePlay=1 ; 斷流后是否重新開始播放(1是)
publishToHls=1 ; 是否發布hls(1是)
publishToMP4=0 ; 是否發布mp4(1是)
[hls] 部分 - HLS 配置
ini
[hls]
fileBufSize=65536 ; HLS文件緩存大小
filePath=./www ; HLS文件保存路徑
segDur=2 ; 分片時長(秒)
segNum=3 ; 保留分片數
segRetain=5 ; 分片保留時長(秒)
broadcastRecordTs=0 ; 是否廣播錄制ts(1是)
deleteDelaySec=10 ; 刪除延遲(秒)
[http] 部分 - HTTP 協議配置
ini
[http]
allowCrossDomains=1 ; 是否允許跨域(1允許)
charSet=utf-8 ; HTTP字符集
dirMenu=1 ; 是否開啟目錄瀏覽(1開啟)
keepAliveSecond=15 ; keep-alive超時(秒)
maxReqSize=4096 ; 最大請求頭大小(KB)
port=80 ; HTTP服務器端口
rootPath=./www ; HTTP根目錄
sslport=443 ; HTTPS服務器端口
[multicast] 部分 - 組播配置
ini
[multicast]
addrMax=239.255.255.255 ; 組播地址最大值
addrMin=239.0.0.0 ; 組播地址最小值
udpTTL=64 ; 組播TTL值
[record] 部分 - 錄制配置
ini
[record]
appName=record ; 錄制應用名
fileBufSize=65536 ; 文件緩存大小
filePath=./www ; 錄制文件保存路徑
sampleMS=500 ; 錄制取樣間隔(毫秒)
fastStart=0 ; 是否快速啟動(1是)
fileRepeat=0 ; 是否循環錄制(1是)
[rtmp] 部分 - RTMP 協議配置
ini
[rtmp]
handshakeSecond=15 ; 握手超時(秒)
keepAliveSecond=15 ; keep-alive超時(秒)
modifyStamp=1 ; 是否調整時間戳(1是)
port=1935 ; RTMP服務器端口
sslport=1936 ; RTMPS服務器端口
[rtp] 部分 - RTP 配置
ini
[rtp]
audioMtuSize=600 ; 音頻MTU大小
videoMtuSize=1400 ; 視頻MTU大小
rtpMaxSize=10 ; RTP最大緩存包數
[rtsp] 部分 - RTSP 協議配置
ini
[rtsp]
authBasic=0 ; 是否啟用基本認證(1啟用)
handshakeSecond=15 ; 握手超時(秒)
keepAliveSecond=15 ; keep-alive超時(秒)
port=554 ; RTSP服務器端口
sslport=322 ; RTSPS服務器端口
directProxy=1 ; 是否直接代理(1是)
[shell] 部分 - Shell 配置
ini
[shell]
maxReqSize=1024 ; 最大請求大小
port=9000 ; shell端口
[thread] 部分 - 線程池配置
ini
[thread]
thread_num=8 ; 線程池大小
高級配置
日志配置
ini
[log]
level=3 ; 日志級別(1-5, 1=verbose, 5=error)
logPath=./logs ; 日志目錄
logDays=7 ; 日志保留天數
TCP/UDP 配置
ini
[tcp]
fast_open=1 ; 是否啟用TCP快速打開(1啟用)
sendBuf=4194304 ; 發送緩沖區大小(字節)
recvBuf=1048576 ; 接收緩沖區大小(字節)[udp]
sendBuf=1048576 ; 發送緩沖區大小(字節)
recvBuf=4194304 ; 接收緩沖區大小(字節)
性能調優配置
ini
[performance]
closeDelay=500 ; 關閉延遲(毫秒)
虛擬主機配置示例
ini
[vhost___defaultVhost__]
hls.segNum=5
hls.segDur=5
常用API
基礎信息類API
1. 獲取服務器配置
API:?/index/api/getServerConfig
比如:http://127.0.0.1/index/api/getServerConfig
方法: GET
參數: 無
響應示例:
json
{"code": 0,"data": {"api.apiDebug": "1","api.secret": "035c73f7-bb6b-4889-a715-d9eb2d1925cc","ffmpeg.bin": "/usr/bin/ffmpeg","general.enableVhost": "0",// 更多配置項...}
}
2. 獲取服務器版本信息
API:?/index/api/version
方法: GET
參數: 無
響應示例:
json
{"code": 0,"data": {"buildTime": "2023-05-20 15:30:45","branchName": "master","commitHash": "a1b2c3d4","version": "10.0"}
}
流管理類API
3. 獲取流列表
API:?/index/api/getMediaList
方法: GET
參數:
-
schema
?(可選): 協議類型,如rtsp/rtmp等 -
vhost
?(可選): 虛擬主機名 -
app
?(可選): 應用名
響應示例:
json
{"code": 0,"data": [{"app": "live","stream": "test","readerCount": 3,"totalReaderCount": 10,"originType": 0,"originTypeStr": "rtmp_push","createStamp": 1684567890,"aliveSecond": 3600}]
}
4. 檢查流是否在線
API:?/index/api/isMediaOnline
方法: GET
參數:
-
schema
: 協議類型,如rtsp/rtmp等 -
vhost
: 虛擬主機名 -
app
: 應用名 -
stream
: 流ID
響應示例:
json
{"code": 0,"online": true
}
5. 關閉流
API:?/index/api/close_stream
方法: GET
參數:
-
schema
: 協議類型 -
vhost
: 虛擬主機名 -
app
: 應用名 -
stream
: 流ID -
force
?(可選): 是否強制關閉(1/0)
響應示例:
json
{"code": 0,"msg": "success"
}
錄制控制類API
6. 開始錄制
API:?/index/api/startRecord
方法: GET
參數:
-
type
: 0=hls, 1=mp4 -
vhost
: 虛擬主機名 -
app
: 應用名 -
stream
: 流ID -
customized_path
?(可選): 自定義錄制路徑
響應示例:
json
{"code": 0,"result": true,"msg": "start record success"
}
7. 停止錄制
API:?/index/api/stopRecord
方法: GET
參數:
-
type
: 0=hls, 1=mp4 -
vhost
: 虛擬主機名 -
app
: 應用名 -
stream
: 流ID
響應示例:
json
{"code": 0,"result": true,"msg": "stop record success"
}
8. 獲取錄制狀態
API:?/index/api/isRecording
方法: GET
參數:
-
type
: 0=hls, 1=mp4 -
vhost
: 虛擬主機名 -
app
: 應用名 -
stream
: 流ID
響應示例:
json
{"code": 0,"status": true
}
代理與轉協議API
9. 添加FFmpeg代理
API:?/index/api/addFFmpegSource
方法: GET/POST
參數:
-
src_url
: 源流URL -
dst_url
: 目標流URL -
timeout_ms
: 超時時間(毫秒) -
enable_hls
: 是否啟用HLS(1/0) -
enable_mp4
: 是否啟用MP4錄制(1/0)
響應示例:
json
{"code": 0,"msg": "success","key": "ffmpeg_key_123456"
}
10. 刪除FFmpeg代理
API:?/index/api/delFFmpegSource
方法: GET
參數:
-
key
: addFFmpegSource返回的key
響應示例:
json
{"code": 0,"msg": "success"
}
系統控制類API
11. 熱加載配置文件
API:?/index/api/reloadConfig
方法: GET
參數: 無
響應示例:
json
{"code": 0,"msg": "reload config success"
}
12. 關閉服務器
API:?/index/api/closeServer
方法: GET
參數:
-
secret
: API密鑰(必須與config.ini中的secret匹配)
響應示例:
json
{"code": 0,"msg": "server will close soon"
}
統計信息類API
13. 獲取服務器負載情況
API:?/index/api/getStatistic
方法: GET
參數: 無
響應示例:
json
{"code": 0,"data": {"online": {"streams": 5,"players": 23,"pushers": 3},"bytes": {"send": 1024000,"recv": 512000}}
}
14. 獲取線程負載情況
API:?/index/api/getThreadsLoad
方法: GET
參數: 無
響應示例:
json
{"code": 0,"data": [{"id": 0,"load": 45,"task": 1234}]
}
安全認證
所有API調用(除了version和getServerConfig)都需要添加secret參數或在HTTP頭中添加Authorization:
bash
# 方法1:URL參數
http://127.0.0.1/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc# 方法2:HTTP頭
curl -H "Authorization: 035c73f7-bb6b-4889-a715-d9eb2d1925cc" \http://127.0.0.1/index/api/getMediaList
啟動拉流代理(從遠程拉流到 ZLMediaKit)
這是最常用的 "打開流推送" 方式,即讓 ZLMediaKit 作為客戶端主動拉取遠程流,然后轉發給本地客戶端。
15. 開啟拉流代理
API 接口
text
http://[ZLMediaKit_IP]:[HTTP端口]/index/api/addStreamProxy
請求參數
參數名 | 必選 | 說明 |
---|---|---|
secret | 是 | API 密鑰(如果配置了?api.secret ) |
vhost | 否 | 虛擬主機,默認?__defaultVhost__ |
app | 是 | 本地應用名(如?live ) |
stream | 是 | 本地流 ID(如?test ) |
url | 是 | 遠程流地址(如?rtmp://example.com/live/stream ) |
enable_hls | 否 | 是否生成 HLS(默認?false ) |
enable_mp4 | 否 | 是否錄制 MP4(默認?false ) |
rtp_type | 否 | 拉流協議類型(rtmp /rtsp /hls /http ,默認自動判斷) |
示例請求
bash
curl "http://127.0.0.1:80/index/api/addStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=live&stream=test&url=rtmp://example.com/live/origin_stream"
成功響應
json
{"code": 0,"msg": "success","data": {"key": "__defaultVhost__/live/test"}
}
16. 停止拉流代理
關閉已拉取的流。
API 接口
text
http://[ZLMediaKit_IP]:[HTTP端口]/index/api/delStreamProxy
請求參數
參數名 | 必選 | 說明 |
---|---|---|
secret | 是 | API 密鑰 |
key | 是 | 流的 key(從?addStreamProxy ?返回) |
示例請求
bash
curl "http://127.0.0.1:80/index/api/delStreamProxy?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&key=__defaultVhost__/live/test"
17. 主動推流到 ZLMediaKit
如果希望外部設備(如 FFmpeg、OBS)推流到 ZLMediaKit,可直接使用推流地址,無需調用 API。
推流地址格式
-
RTMP 推流
text
rtmp://[ZLMediaKit_IP]:1935/[app]/[stream]
示例:
bash
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://127.0.0.1/live/test
-
RTSP 推流
text
rtsp://[ZLMediaKit_IP]:554/[app]/[stream]
18. 查詢流狀態
檢查流是否已成功打開。
API 接口
text
http://[ZLMediaKit_IP]:[HTTP端口]/index/api/getMediaInfo
請求參數
參數名 | 必選 | 說明 |
---|---|---|
secret | 是 | API 密鑰 |
app | 是 | 應用名(如?live ) |
stream | 是 | 流 ID(如?test ) |
示例請求
bash
curl "http://127.0.0.1:80/index/api/getMediaInfo?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&app=live&stream=test"
成功響應(流存在時)
json
{"code": 0,"online": true,"readerCount": 2 // 當前觀看人數
}
注意事項
-
所有時間參數單位為毫秒,除非特別說明
-
返回的code為0表示成功,非0表示失敗
-
生產環境建議使用HTTPS協議訪問API
-
頻繁調用的API建議添加適當的緩存機制
-
關鍵操作API(如關閉服務器)需要謹慎調用
-
確保端口開放:RTMP 默認?
1935
,HTTP API 默認?80
。 -
API 密鑰:如果配置了?
api.secret
(在?config.ini
?中),必須在請求中攜帶。 -
拉流重試:如果遠程流斷開,ZLMediaKit 默認會嘗試重連。
-
流唯一性:
app
?+?stream
?唯一標識一路流。
推流與播放
推流方式
1. 使用 FFmpeg 推流
基本推流命令:
bash
rtmp
rtmp://[ZLMediaKit_IP]:1935/[app]/[stream]
比如:
ffmpeg -re -i input.mp4 -c:v libx264 -preset ultrafast -tune zerolatency -c:a aac -f flv rtmp://服務器IP/live/流ID
rtsp rtsp://[ZLMediaKit_IP]:554/[app]/[stream]
常用參數說明:
-
-re
:按照原始幀率推送 -
-i
:輸入文件 -
-c:v
:視頻編碼器(libx264, h264等) -
-preset ultrafast
:最快編碼預設 -
-tune zerolatency
:零延遲調優 -
-c:a
:音頻編碼器 -
-f flv
:輸出格式為FLV
示例場景:
-
推送本地文件:
bash
ffmpeg -re -i test.mp4 -c:v libx264 -c:a aac -f flv rtmp://127.0.0.1/live/test
-
推送攝像頭(Linux):
bash
ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset ultrafast -f flv rtmp://127.0.0.1/live/cam
-
推送屏幕(Windows):
bash
ffmpeg -f gdigrab -i desktop -c:v libx264 -preset ultrafast -f flv rtmp://127.0.0.1/live/screen
2. 使用 OBS 推流
-
打開OBS設置 → 推流
-
服務選擇"自定義"
-
服務器填寫:
rtmp://服務器IP/live
-
流密鑰填寫任意流ID(如:test123)
-
點擊"確定"后開始推流
3. 使用 SDK 推流
ZLMediaKit支持多種協議的推流,包括RTMP、RTSP、RTP等。開發者可以使用以下SDK進行推流:
-
libZLToolKit(C++)
-
librtmp(C)
-
各語言封裝的RTMP庫(如Python的
pylibrtmp
)
播放方式
1. RTMP 播放
播放地址格式:
text
rtmp://服務器IP/live/流ID
播放工具:
-
VLC:媒體 → 打開網絡串流 → 輸入RTMP地址
-
FFplay:
bash
ffplay rtmp://127.0.0.1/live/test
-
網頁播放(需Flash):使用JWPlayer等支持RTMP的網頁播放器
2. HTTP-FLV 播放
播放地址格式:
text
http://服務器IP/live/流ID.flv
優勢:
-
基于HTTP,穿透性好
-
延遲低(2-3秒)
-
支持網頁端直接播放
播放工具:
-
VLC
-
FFplay:
bash
ffplay http://127.0.0.1/live/test.flv
-
網頁播放(推薦flv.js):
html
<script src="https://cdn.jsdelivr.net/npm/flv.js@latest/dist/flv.min.js"></script> <video id="videoElement" controls></video> <script>if (flvjs.isSupported()) {var videoElement = document.getElementById('videoElement');var flvPlayer = flvjs.createPlayer({type: 'flv',url: 'http://127.0.0.1/live/test.flv'});flvPlayer.attachMediaElement(videoElement);flvPlayer.load();flvPlayer.play();} </script>
3. HLS 播放
播放地址格式:
text
http://服務器IP/live/流ID/hls.m3u8
特點:
-
高兼容性(所有瀏覽器原生支持)
-
高延遲(通常10-30秒)
-
適合點播和移動端
播放工具:
-
直接瀏覽器打開:
html
<video src="http://127.0.0.1/live/test/hls.m3u8" controls></video>
-
VLC/FFplay等播放器
4. WebRTC 播放(需啟用WebRTC支持)
播放地址格式:
text
http://服務器IP/live/流ID.live.ts
特點:
-
超低延遲(<1秒)
-
需要瀏覽器支持WebRTC
網頁播放示例:
html
<video id="video" autoplay controls></video>
<script>const video = document.getElementById('video');const pc = new RTCPeerConnection();pc.addTransceiver('video', { direction: 'recvonly' });pc.addTransceiver('audio', { direction: 'recvonly' });pc.ontrack = function(event) {if (event.track.kind === 'video') {video.srcObject = event.streams[0];}};fetch('http://127.0.0.1:8080/index/api/webrtc', {method: 'POST',body: JSON.stringify({type: 'play',app: 'live',stream: 'test',sdp: ''})}).then(res => res.json()).then(data => {pc.setRemoteDescription(new RTCSessionDescription(data.sdp));pc.createAnswer().then(answer => {pc.setLocalDescription(answer);});});
</script>
推流與播放狀態管理
1. 檢查流是否在線
bash
curl "http://127.0.0.1/index/api/isMediaOnline?app=live&stream=test"
2. 獲取流信息
bash
curl "http://127.0.0.1/index/api/getMediaInfo?app=live&stream=test"
3. 斷開指定推流
bash
curl "http://127.0.0.1/index/api/kick_session?type=0&id=客戶端ID"
延遲優化建議
-
推流端優化:
-
使用
-tune zerolatency
參數 -
降低GOP長度(
-g 30
) -
減少B幀數量(
-bf 0
)
-
-
服務器端優化:
ini
[rtmp] modifyStamp=1[hls] segDur=1 segNum=3
-
播放端優化:
-
使用HTTP-FLV或WebRTC協議
-
減少播放器緩沖時間
-
常見問題解決
1. 推流失敗
-
檢查服務器端口是否開放(默認1935)
-
檢查防火墻設置
-
查看ZLMediaKit日志
2. 播放卡頓
-
檢查網絡帶寬
-
降低推流碼率
-
檢查服務器負載
3. 高延遲
-
避免使用HLS協議
-
調整GOP大小
-
使用低延遲協議(WebRTC或HTTP-FLV)
常見問題
-
如何提高性能?
-
調整配置文件中的線程數
-
啟用TCP_NODELAY
-
使用硬件加速編解碼
-
-
如何實現鑒權?
-
配置文件中設置
[api]
部分的secret
-
實現
on_rtsp_realm
和on_rtsp_auth
回調
-
-
如何支持WebRTC?
-
編譯時開啟
ENABLE_WEBRTC
選項 -
配置STUN/TURN服務器
-
進階學習
-
閱讀官方文檔:https://github.com/ZLMediaKit/ZLMediaKit/wiki