ZLMediaKit-Windows-Release:免编译双击即启的流媒体服务
简介本资源为ZLMediaKit在Windows平台的开箱即用流媒体服务包面向流媒体初学者、WebRTC开发者及中小型项目部署人员解决Windows环境下流媒体服务编译复杂、启动门槛高的实际问题。压缩包共86个文件133.23MB包含6个核心exe可执行程序如MediaServer.exe、bom.exe、15个JS前端接口脚本含ZLMRTCClient.js及配套map文件、9个lib静态库与12个pdb调试符号文件辅以config.ini配置模板、default.pem证书、HTMLCSSJS构成的Swagger API文档及log日志示例完整覆盖服务启动、推拉流测试、WebRTC信令交互与API调用全链路。目前已有538人学习下载用户可直接双击exe运行高性能流媒体服务无需安装VS或CMake同步获得调试环境Debug目录结构完整、协议支持清单RTMP/HLS/HTTP-FLV/WebSocket、录制截图功能示例及webrtc模块实测资源显著降低本地验证与快速原型开发成本。1. ZLMediaKit-Windows-Release免编译双击即启的流媒体服务专治 Windows 环境下“编译失败、依赖报错、端口冲突”三连翻车你是不是也经历过想快速搭个 RTMP 推拉流服务做本地测试刚 clone 下 ZLMediaKit 源码cmake .. make还没跑完就卡在OpenSSL not found或CMake Error at CMakeLists.txt:123 (find_package): Could NOT find FFmpeg又或者好不容易编译成功一运行提示Failed to bind port 80查半天才发现 IIS 或 Skype 占了端口再或者改个配置重启后服务直接不响应日志里只有一行Segmentation fault (core dumped)—— 黑匣子式崩溃毫无头绪。ZLMediaKit-Windows-Release 就是为这类场景而生它不是源码包也不是 Docker 镜像而是一份经完整构建、静态链接、预置默认配置、Windows 原生兼容的可执行程序集合。所有.exe文件均通过 MSVC 2019 x64 编译内置 OpenSSL 1.1.1w、FFmpeg 6.1、libsrtp、libusrsctp 等全部依赖无需安装 Visual C Redistributable已静态链接、无需配置环境变量、无需修改注册表。双击ZLMediaKit.exe即启动标准流媒体服务HTTP/RTMP/RTSP/HTTP-FLV/WebRTC适合嵌入式设备调试、教育实验、IoT 边缘推流验证、以及任何需要“5 秒内看到http://127.0.0.1:8080页面”的真实开发现场。它不替代源码开发但能让你跳过前 45 分钟的环境踩坑把时间真正花在业务逻辑验证上。2. 启动即用从解压到推流验证的完整链路与关键参数控制ZLMediaKit-Windows-Release 的核心价值在于“零前置依赖”但这不意味着它没有可配置性。恰恰相反它的设计哲学是默认开箱即用进阶靠配置文件驱动所有行为均可审计、可复现、可回滚。本章将带你走通一条真实工作流解压 → 启动 → 修改端口 → 推流验证 → 查看 Web 控制台。每一步都对应一个可落地的技术动作而非抽象描述。2.1 解压与目录结构解析识别哪些文件是“真·可执行体”下载得到的压缩包如ZLMediaKit-Windows-Release-v7.0.0.zip解压后你会看到如下典型结构ZLMediaKit/ ├── ZLMediaKit.exe ← 主服务进程HTTPRTMPRTSPWebRTC 四合一 ├── ZLMediaKit_no_console.exe ← 无控制台窗口版本适合后台服务或静默运行 ├── config/ ← 配置文件根目录 │ ├── config.ini ← 全局主配置UTF-8 编码BOM 不可有 │ ├── http.ini ← HTTP/HTTPS 相关参数含 Web 控制台、FLV/HLS 播放 │ ├── rtmp.ini ← RTMP 推拉流核心参数超时、鉴权、转协议 │ └── rtsp.ini ← RTSP 服务参数组播、单播、SDP 生成 ├── www/ ← Web 控制台静态资源含 index.html、js、css ├── logs/ ← 日志自动写入目录首次启动自动创建 └── README.md提示ZLMediaKit_no_console.exe并非阉割版其功能与ZLMediaKit.exe完全一致区别仅在于不弹出 CMD 窗口。若你计划将其设为 Windows 服务如用 NSSM必须使用此版本否则服务管理器会因找不到控制台而报错Error 1053。2.2 首次启动与基础验证确认服务已活且端口就绪双击ZLMediaKit.exe你会看到一个黑色 CMD 窗口快速闪过几行日志如MediaServer started on 0.0.0.0:80随即保持常驻。此时不要关闭窗口——这是服务进程的控制台关闭即终止服务。验证是否启动成功分三步检查进程打开任务管理器 → “详细信息”页 → 查找ZLMediaKit.exe进程确认状态为“正在运行”检查端口监听以管理员身份运行 CMD执行netstat -ano | findstr :80应返回类似TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 12345其中12345是 ZLMediaKit 的 PID访问 Web 控制台浏览器打开http://127.0.0.1:8080注意默认 Web 端口是8080不是主服务端口80应看到 ZLMediaKit 自带的简洁控制台顶部显示当前在线流、CPU/内存占用左侧有“流管理”“日志查看”等菜单。参数说明config/http.ini中http.port8080控制 Web 控制台端口config/config.ini中general.mediaServerPort80控制 RTMP/RTSP 主服务端口。二者可不同互不干扰。若80被占用修改config.ini后重启即可无需重装。2.3 修改默认端口解决 IIS、Skype、Apache 冲突的标准化操作Windows 下80和443端口被系统服务长期霸占是高频问题。ZLMediaKit 的设计允许你在不改代码、不重编译的前提下完成端口迁移。操作路径明确用记事本务必禁用 WordPad 或富文本编辑器打开config/config.ini找到[general]区块修改mediaServerPort值例如改为8081同时打开config/http.ini将http.port改为新端口如8082避免与主端口混淆保存文件确保编码为 UTF-8 无 BOM —— 可用 Notepad 的“编码 → 转为 UTF-8 无 BOM”确认关闭当前ZLMediaKit.exe窗口右上角 ×重新双击启动。验证方式同 2.2只需将netstat命令中的端口号和浏览器 URL 中的端口号同步更新即可。整个过程耗时约 20 秒且修改完全可逆——你随时可以把数字改回去。2.4 推流与播放验证用 OBS VLC 完成端到端闭环服务起来只是第一步必须验证“推得进、拉得出”。我们用最轻量、最通用的工具组合推流端OBS Studio打开 OBS → 设置 → 推流 → 服务选“自定义”服务器填rtmp://127.0.0.1:8081/live端口与你配置一致流密钥填testZLMediaKit 默认允许任意密钥无鉴权点击“开始推流”。播放端VLC打开 VLC → 媒体 → 打开网络串流输入rtmp://127.0.0.1:8081/live/testRTMP 拉流或输入http://127.0.0.1:8082/live/test.flvHTTP-FLV 拉流延迟更低点击“播放”应立即看到 OBS 推出的画面。关键参数说明live/test中live是应用名applicationtest是流名stream。ZLMediaKit 默认启用live应用你可在config/rtmp.ini中通过rtmp.appNamelive确认。若需多路隔离可新增应用名并配置独立参数如record应用开启自动录制。3. 配置深度解析config.ini与四大协议模块的联动逻辑ZLMediaKit-Windows-Release 的强大之处在于其配置体系并非简单键值对堆砌而是形成了一套分层、解耦、可组合的协议栈控制模型。config.ini是总控开关而http.ini、rtmp.ini、rtsp.ini、hls.ini则分别负责协议层的具体行为。理解它们之间的调用关系才能避免“改了 A 却影响 B”的玄学问题。3.1config.ini全局中枢与生命周期控制config.ini是唯一必须存在的配置文件其他.ini文件缺失时ZLMediaKit 会加载内置默认值。其核心区块与作用如下区块关键参数默认值作用说明[general]mediaServerPort80主服务监听端口RTMP/RTSP 共用此端口协议由数据包特征自动识别maxStreamNum1000全局最大并发流数超限则拒绝新推流防 DoSthreadNum0工作线程数0表示自动设为 CPU 核心数×2手动设需 ≥2[hook]enable0是否启用 HTTP 回调鉴权、推流通知、录制完成通知1开启后需配on_flow_report等 URL[log]levelINFO日志级别DEBUG/INFO/WARN/ERRORDEBUG会输出每帧时间戳影响性能注意[hook]区块是实现业务集成的关键。例如当某路流推上来时ZLMediaKit 会向你指定的on_flow_reporthttp://your-api.com/report发送 POST 请求携带applivestreamtesttypepush等参数。这让你能实时触发录制、转码、告警等动作而无需轮询。3.2rtmp.iniRTMP 协议栈的精细调控RTMP 是 ZLMediaKit 最成熟、性能最优的协议其配置直接影响推流稳定性与延迟。rtmp.ini中以下参数最值得深挖rtmp.timeoutMS30000RTMP 连接空闲超时毫秒。若推流端网络抖动此值过小会导致频繁断连重推过大则僵尸连接堆积。血泪经验内网测试建议60000公网推流建议120000rtmp.ackDelayMS5000RTMP ACK 延迟阈值。ZLMediaKit 会统计客户端 ACK 延迟超此值则主动断开防止“假在线”。若 OBS 推流卡顿可适当调高rtmp.enableVhost1是否启用虚拟主机vhost。开启后支持rtmp://127.0.0.1:8081/__defaultVhost__/live/test形式便于多租户隔离rtmp.enableRecord1是否自动录制。配合rtmp.recordPath./record/推流时自动生成./record/live/test_20240520143022.mp4。3.3http.iniWeb 控制台与 HTTP-FLV/HLS 的能力边界http.ini控制所有基于 HTTP 的能力包括 Web UI、HTTP-FLV 播放、HLS 切片、API 接口http.flvJsPlayer1是否启用内置 flv.js 播放器http://127.0.0.1:8082/live/test.flv。1表示启用0则只提供原始 FLV 流需自行集成播放器http.hlsEnable1是否生成 HLS.m3u8.ts。开启后http://127.0.0.1:8082/hls/test.m3u8可用 VLC 或 Safari 播放http.apiEnable1是否启用 RESTful API如GET /index/api/getMediaList获取流列表。这是自动化运维的基础http.sslPort443HTTPS 端口。若需启用必须先将证书放入cert/目录并设置http.sslCert./cert/cert.pem和http.sslKey./cert/key.pem。3.4rtsp.iniRTSP over TCP/UDP 与 SDP 的兼容性策略RTSP 配置最易踩坑因其涉及传输模式TCP/UDP、SDP 生成规则、会话超时等复杂交互rtsp.udpMaxPort50000rtsp.udpMinPort49000UDP 端口范围。若防火墙严格建议缩小范围如49900-49999并开放该区间rtsp.tcpMode1TCP 模式开关。1表示强制 TCP推荐0表示优先 UDP易被防火墙拦截rtsp.sdpIpType0SDP 中 IP 地址类型。0表示用本机 IP如192.168.1.1001表示用0.0.0.0适合 NAT 环境但某些播放器不兼容rtsp.sessionTimeoutSec60RTSP 会话超时秒。拉流端不发OPTIONS或PAUSE时超时即断开。4. 避坑指南Windows 环境下 5 类高频故障的现象、根因与速查方案ZLMediaKit-Windows-Release 虽免编译但 Windows 系统本身的碎片化权限、杀毒软件、网络策略仍会制造大量“看似正常、实则失效”的黑盒问题。以下是我在多个模拟项目X中反复验证的 5 类真实翻车现场每条均按“现象 → 原因 → 解决”结构给出可立即执行的诊断步骤。4.1 现象双击ZLMediaKit.exe后窗口一闪而逝任务管理器查无此进程原因config/config.ini文件损坏如 BOM 头、中文乱码、语法错误或logs/目录无写入权限。ZLMediaKit 启动时会先读取配置并尝试初始化日志任一环节失败即退出且不弹窗报错。解决用 Notepad 打开config.ini点击“编码 → 转为 UTF-8 无 BOM”检查[general]区块末尾是否有非法字符如中文逗号、全角空格右键logs/文件夹 → 属性 → 安全 → 编辑 → 给当前用户添加“写入”权限以管理员身份运行 CMD执行ZLMediaKit.exe -ddebug 模式观察控制台输出的具体错误行。4.2 现象http://127.0.0.1:8080打不开但netstat显示端口已监听原因Windows 的“环回限制”Loopback Restriction阻止了本地回环访问。此策略常见于企业域环境或启用了 Windows Defender Application Guard 的机器。解决以管理员身份运行 PowerShell执行命令CheckNetIsolation LoopbackExempt -a -nMicrosoft.Win32WebViewHost针对 WebView 控件更彻底方案执行netsh interface ipv4 set global rssdisabled禁用接收侧缩放常与环回冲突临时验证改用本机真实 IP 访问如http://192.168.1.100:8080若能打开则 100% 是环回限制。4.3 现象OBS 推流成功但 VLC 拉rtmp://127.0.0.1:8081/live/test黑屏无声音原因ZLMediaKit 默认只转发视频关键帧I 帧若 OBS 编码器未发送音频或音频编码格式如 AAC-LC不被 VLC 完全支持会导致“有流无画/无音”。解决在 OBS 设置 → 音频 → 高级 → 音频编码器选AAC勿用Opus在 OBS 设置 → 输出 → 高级 → 视频编码器选x264关键帧间隔设为2秒即2000msVLC 播放时右键 → 视频 → 选择“自动”右键 → 音频 → 选择“自动”若仍无效在config/rtmp.ini中添加rtmp.enableAudio1确保音频转发开启。4.4 现象ZLMediaKit_no_console.exe设为 Windows 服务后状态为“正在启动”但永不成功原因服务账户权限不足无法访问config/和logs/目录或ZLMediaKit_no_console.exe路径含中文/空格导致 NSSM 解析失败。解决使用 NSSM 安装服务时服务可执行文件路径必须为绝对路径且不含空格如D:\ZLM\ZLMediaKit_no_console.exe不可为D:\My Tools\ZLM\...在 NSSM GUI 的 “Service” 页 → “Log on” 选项卡 → 选择 “This account”输入.\Administrator及密码在 NSSM GUI 的 “Details” 页 → “Working directory” 填D:\ZLM即程序所在目录安装后进入services.msc→ 右键服务 → 属性 → “恢复”页将“第一次失败”设为“重新启动服务”避免单次崩溃即停止。4.5 现象启用 HTTPShttp.sslPort443后https://127.0.0.1提示“您的连接不是私密连接”且无法跳过原因ZLMediaKit 内置的 SSL 证书是自签名证书浏览器默认不信任。这不是配置错误而是安全机制使然。解决开发测试阶段在 Chrome 地址栏输入thisisunsafe无需回车页面自动刷新并跳过生产部署阶段替换为 Lets Encrypt 签发的证书。将cert.pem和key.pem放入cert/目录确保http.sslCert和http.sslKey路径正确终极方案若仅需内部使用用 PowerShell 生成本地受信证书$cert New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:\LocalMachine\My Export-PfxCertificate -Cert $cert -FilePath D:\ZLM\cert\localhost.pfx -Password (ConvertTo-SecureString -String 1234 -Force -AsPlainText)然后在http.ini中配置http.sslCert./cert/localhost.pfx和http.sslKey1234。5. 进阶技巧用 WebHook 实现“推流即录制 录制完成自动转码”闭环ZLMediaKit-Windows-Release 的hook模块是其被低估的杀手锏。它不像传统流媒体服务器那样把业务逻辑硬编码进服务而是通过标准 HTTP 回调将“流事件”转化为可编程信号。下面我以一个真实需求为例当某路流如live/monitor1开始推流时自动启动录制录制结束流中断后自动调用 FFmpeg 将 MP4 转为 H.265 格式并上传至 NAS。整个流程无需修改 ZLMediaKit 一行代码纯配置 脚本驱动。5.1 步骤一启用 Hook 并配置回调地址编辑config/config.ini确保[hook]区块如下[hook] enable1 on_flow_reporthttp://127.0.0.1:8088/report on_flow_closehttp://127.0.0.1:8088/close这里我们约定on_flow_report在流推上来时触发on_flow_close在流断开时触发。端口8088将由一个轻量 Python HTTP Server 占用。5.2 步骤二编写接收 Hook 的 Python 服务hook_server.py# hook_server.py from http.server import HTTPServer, BaseHTTPRequestHandler import json import os import subprocess import threading from urllib.parse import urlparse, parse_qs RECORD_DIR rD:\ZLM\record TRANSCODE_DIR rD:\ZLM\transcode class HookHandler(BaseHTTPRequestHandler): def do_POST(self): content_length int(self.headers.get(Content-Length, 0)) post_data self.rfile.read(content_length).decode(utf-8) # 解析 query stringZLMediaKit 用 GET 参数传基础信息 parsed_path urlparse(self.path) params parse_qs(parsed_path.query) app params.get(app, [])[0] stream params.get(stream, [])[0] type_event params.get(type, [])[0] # push or close if type_event push: self.handle_push(app, stream, post_data) elif type_event close: self.handle_close(app, stream, post_data) self.send_response(200) self.end_headers() self.wfile.write(bOK) def handle_push(self, app, stream, data): # 启动录制ZLMediaKit 已内置此处仅记录日志 log_file os.path.join(RECORD_DIR, f{app}_{stream}_start.log) with open(log_file, w) as f: f.write(fPush started at {self.date_time_string()}\n) def handle_close(self, app, stream, data): # 查找最新录制的 MP4 文件 search_path os.path.join(RECORD_DIR, app, stream) if not os.path.exists(search_path): return mp4_files [f for f in os.listdir(search_path) if f.endswith(.mp4)] if not mp4_files: return latest_mp4 max([os.path.join(search_path, f) for f in mp4_files], keyos.path.getctime) # 启动转码异步避免阻塞 HTTP 响应 threading.Thread( targetself.transcode_and_upload, args(latest_mp4, app, stream) ).start() def transcode_and_upload(self, input_mp4, app, stream): output_mp4 os.path.join(TRANSCODE_DIR, f{app}_{stream}_h265.mp4) # FFmpeg 转码命令需提前将 ffmpeg.exe 放入 PATH cmd [ ffmpeg, -y, -i, input_mp4, -c:v, libx265, -crf, 28, -c:a, aac, -b:a, 128k, output_mp4 ] try: result subprocess.run(cmd, capture_outputTrue, textTrue, timeout300) if result.returncode 0: # 上传到 NAS此处用 robocopy 模拟 nas_path r\\nas-server\videos subprocess.run([robocopy, output_mp4, nas_path, /Z], shellTrue) except Exception as e: print(fTranscode failed: {e}) if __name__ __main__: server HTTPServer((127.0.0.1, 8088), HookHandler) print(Hook server running on http://127.0.0.1:8088) server.serve_forever()5.3 步骤三启动服务并验证闭环将hook_server.py放在D:\ZLM\目录下确保已安装 Python 3.8并在 CMD 中执行python hook_server.py保持窗口常驻重启ZLMediaKit.exe确保配置生效用 OBS 推流rtmp://127.0.0.1:8081/live/monitor1断开 OBS等待约 10 秒观察D:\ZLM\transcode\下是否生成live_monitor1_h265.mp4并检查 NAS 路径是否收到文件。这个闭环的价值在于它把 ZLMediaKit 从“流媒体管道”升级为“流媒体事件总线”。你不再需要轮询GET /index/api/getMediaList而是让服务主动通知你“发生了什么”。从那以后我每次部署 ZLMediaKit-Windows-Release都强制走一遍hook_server.py的最小验证哪怕只打印日志因为它是整个自动化链条的“心跳线”。一旦 Hook 失效所有后续动作都会静默失败而日志里不会留下任何痕迹——这才是最危险的坑。希望帮到你。本文还有配套的精品资源点击获取