将 ZLMediaKit 这一高性能的流媒体服务器以动态库形式内嵌到 Java 应用中,可以实现单一进程内的高度集成,避免了独立部署进程带来的复杂性和资源开销。本文将详细介绍在 Windows 和 Linux 系统上实现此目标的通用步骤。
首先,需要将 ZLMediaKit 编译为可供链接的动态库(Linux 下为 .so 文件,Windows 下为 .dll 文件),而不是独立的可执行程序。
-
获取源码
克隆 ZLMediaKit 的官方仓库:
github.com/ZLMediaKit/ZLMediaKit
-
编译配置与构建
以 Linux 系统为例,Windows 可使用 Visual Studio 进行类似操作。关键编译选项是 -DBUILD_SHARED_LIBS=ON。
# 安装必要的编译依赖
sudo apt install cmake g++ libssl-dev libsdl-dev libavutil-dev libavformat-dev
# 创建构建目录并编译
mkdir build && cd build
cmake -DBUILD_SHARED_LIBS=ON -DENABLE_ALL_IN_ONE=ON ..
make -j4
-
获取动态库
编译完成后,在 build 目录下可以找到核心动态库文件:
- Linux:
libZLMediaKit.so
- Windows:
ZLMediaKit.dll
步骤一:将动态库集成到 Java 项目
将编译好的动态库文件放入你的 Java 项目资源目录,确保其能被打包进最终的 JAR 文件。
-
组织项目结构
在 src/main/resources/ 目录下创建 lib 文件夹,并将对应平台的动态库放入。
src/main/resources/
├── lib/
│ ├── libZLMediaKit.so (Linux)
│ └── ZLMediaKit.dll (Windows)
└── ...
-
配置 Maven 打包(POM.xml 示例)
需要配置 Maven 的资源拷贝和打包插件,确保 lib 目录下的动态库被打包进 JAR 文件。
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>lib/**/*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<!-- 打包为可执行JAR(包含所有依赖) -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.xxx.ZlmEmbeddedMain</mainClass> <!-- 替换为你的主类 -->
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
步骤二:通过 JNA 调用动态库启动服务
ZLMediaKit 的 Java SDK zlm4j 主要提供客户端 API,不直接包含启动内嵌服务端的功能。因此,我们需要通过 Java 的 JNI 或更简便的 JNA 来调用动态库的启动和停止函数。
-
引入 JNA 依赖
在 pom.xml 中添加 JNA 依赖。
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
-
定义 JNA 接口映射 C++ 函数
创建一个接口,用于映射 ZLMediaKit 动态库中暴露的启动和停止函数。具体的函数签名需要与你编译的动态库头文件保持一致。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
// 映射 ZLMediaKit 动态库的核心接口
public interface ZLMediaKitLib extends Library {
// 加载动态库(自动适配 Windows/Linux)
ZLMediaKitLib INSTANCE = Native.load(
Platform.isWindows() ? "ZLMediaKit" : "libZLMediaKit",
ZLMediaKitLib.class
);
// ZLMediaKit 启动函数(需与 C++ 接口一致)
int startMediaServer(String configPath);
// ZLMediaKit 停止函数
void stopMediaServer();
}
-
编写主类:解压库文件并启动服务
编写主类,在程序启动时将 JAR 包内的动态库解压到临时目录,然后加载并调用启动函数。
import com.sun.jna.Platform;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
public class ZlmEmbeddedMain {
public static void main(String[] args) throws Exception {
// 步骤1:从 JAR 中解压 ZLMediaKit 动态库到临时目录
String libName = Platform.isWindows() ? "ZLMediaKit.dll" : "libZLMediaKit.so";
String tempLibPath = System.getProperty("java.io.tmpdir") + File.separator + libName;
try (InputStream is = ZlmEmbeddedMain.class.getResourceAsStream("/lib/" + libName);
FileOutputStream fos = new FileOutputStream(tempLibPath)) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
// 步骤2:加载动态库并启动 ZLMediaKit 服务端
System.load(tempLibPath); // 加载解压后的动态库
String zlmConfigPath = "config.ini"; // ZLMediaKit 配置文件路径
int startResult = ZLMediaKitLib.INSTANCE.startMediaServer(zlmConfigPath);
if (startResult == 0) {
System.out.println("内嵌 ZLMediaKit 服务器启动成功!");
} else {
throw new RuntimeException("ZLMediaKit 启动失败,错误码:" + startResult);
}
// 步骤3:结合 zlm4j SDK 调用内嵌的 ZLMediaKit(连接 127.0.0.1 即可)
// ... 此处复用你原有的 zlm4j 业务代码 ...
// 程序退出时停止 ZLMediaKit
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
ZLMediaKitLib.INSTANCE.stopMediaServer();
System.out.println("内嵌 ZLMediaKit 服务器已停止");
}));
}
}
将 ZLMediaKit 的配置文件 config.ini 同样打包到 JAR 的 resources 目录,并在主类启动时指定其路径。对于内嵌模式,建议修改以下关键配置:
[General]
# 内嵌模式下,建议使用非默认端口,避免与系统其他服务冲突
apiPort=8081
rtmpPort=1936
rtspPort=555
httpPort=8082
# 禁用后台守护进程模式,以内嵌方式运行
daemon=0
同样,需要在主类中实现将此配置文件从 JAR 内解压到临时目录的逻辑,并将解压后的路径传递给 startMediaServer 函数。
通过以上四个步骤,你就能将一个完整的 ZLMediaKit 流媒体服务器核心内嵌到你的 Java 应用程序中,实现从流媒体协议处理到业务逻辑的单一进程闭环,极大简化了部署和 配置和部署 复杂度。
参考资料
[1] 实现「Java 内嵌 ZLMediaKit」的步骤(Windows/Linux 通用), 微信公众号:mp.weixin.qq.com/s/dxn_km-qAywD1n7ghNrXQw
版权声明:本文由 云栈社区 整理发布,版权归原作者所有。
|