找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1593

积分

0

好友

205

主题
发表于 2026-2-15 20:36:40 | 查看: 26| 回复: 0

将 ZLMediaKit 这一高性能的流媒体服务器以动态库形式内嵌到 Java 应用中,可以实现单一进程内的高度集成,避免了独立部署进程带来的复杂性和资源开销。本文将详细介绍在 Windows 和 Linux 系统上实现此目标的通用步骤。

前提:编译 ZLMediaKit 为动态库

首先,需要将 ZLMediaKit 编译为可供链接的动态库(Linux 下为 .so 文件,Windows 下为 .dll 文件),而不是独立的可执行程序。

  1. 获取源码
    克隆 ZLMediaKit 的官方仓库:

    github.com/ZLMediaKit/ZLMediaKit
  2. 编译配置与构建
    以 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
  3. 获取动态库
    编译完成后,在 build 目录下可以找到核心动态库文件:

    • Linux: libZLMediaKit.so
    • Windows: ZLMediaKit.dll

步骤一:将动态库集成到 Java 项目

将编译好的动态库文件放入你的 Java 项目资源目录,确保其能被打包进最终的 JAR 文件。

  1. 组织项目结构
    src/main/resources/ 目录下创建 lib 文件夹,并将对应平台的动态库放入。

    src/main/resources/
    ├── lib/
    │   ├── libZLMediaKit.so (Linux)
    │   └── ZLMediaKit.dll (Windows)
    └── ...
  2. 配置 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 来调用动态库的启动和停止函数。

  1. 引入 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>
  2. 定义 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();
    }
  3. 编写主类:解压库文件并启动服务
    编写主类,在程序启动时将 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

将 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

版权声明:本文由 云栈社区 整理发布,版权归原作者所有。




上一篇:基于STM32的LD3320语音识别开发:硬件连接与驱动代码详解
下一篇:Immich + Docker 快速搭建:私有化 Google Photos 替代方案部署指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 11:47 , Processed in 0.622250 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表