流媒体服务器安装及其代码文件

简述

wvp-pro 安装部署步骤

  1. 官网下载源码包:WVP-PRO文档,也含有部署教程wvp-GB28181-pro: WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的网络视频平台,负责实现核心信令与设备管理后台部分,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR、DVR接入。支持国标级联,支持rtsp/rtmp等视频流转发到国标平台,支持rtsp/rtmp等推流转发到国标平台。icon-default.png?t=N7T8https://gitee.com/pan648540858/wvp-GB28181-pro.git

  2. 配置文件(环境为内网穿透后的213本地)

    spring:
      # 设置接口超时时间
      mvc:
        async:
          request-timeout: 20000
      thymeleaf:
        cache: false
      # [可选]上传文件大小限制
      servlet:
        multipart:
          max-file-size: 10MB
          max-request-size: 100MB
      # REDIS数据库配置
      redis:
        # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
        host: 192.168.0.213
        # [必须修改] 端口号
        port: 6379
        # [可选] 数据库 DB
        database: 7
        # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
        password: xiaomu2023
        # [可选] 超时时间
        timeout: 10000
        # mysql数据源
      datasource:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.0.213:3307/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
        username: root
        password: xiaomu2023
        hikari:
          connection-timeout: 20000             # 是客户端等待连接池连接的最大毫秒数
          initialSize: 10                       # 连接池初始化连接数
          maximum-pool-size: 200                # 连接池最大连接数
          minimum-idle: 5                       # 连接池最小空闲连接数
          idle-timeout: 300000                  # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
          max-lifetime: 1200000                 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
    #[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
      # [可选] HTTPS配置, 默认不开启
      ssl:
        # [可选] 是否开启HTTPS访问
        enabled: false
        # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
        key-store: classpath:test.monitor.89iot.cn.jks
        # [可选] 证书密码
        key-store-password: gpf64qmw
        # [可选] 证书类型, 默认为jks,根据实际修改
        key-store-type: JKS
    ​
    # 作为28181服务器的配置
    sip:
      # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
      # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
      # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
      # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
      ip: 127.0.0.1
      # [可选] 28181服务监听的端口
      port: 15060
      # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
      # 后两位为行业编码,定义参照附录D.3
      # 3701020049标识山东济南历下区 信息行业接入
      # [可选]
      domain: 4101050000
      # [可选]
      id: 41010500002000000001
      # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
      password: bajiuwulian1006
      # 是否存储alarm信息
      alarm: true
    ​
    #zlm 默认服务器配置
    media:
      id: xiaomu2012
      # [必须修改] zlm服务器的内网IP
      ip: 192.168.0.213
      # [必须修改] zlm服务器的http.port
      http-port: 88
      # [可选] 返回流地址时的ip,置空使用 media.ip
      stream-ip: 192.168.0.213
      # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
      sdp-ip: 192.168.0.213
      # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
      hook-ip: 192.168.0.213
      # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
      http-ssl-port: 8443
      # [可选] zlm服务器的hook.admin_params=secret
      secret: LluEd5evhoTswSZ1qDnafNEFTCFnnWCe
      # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
      rtmp-prot: 1935
      rtsp-prot: 8554
      rtp:
        # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
        enable: true
    ​
        # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
        port-range: 30000,35000 # 端口范围
        # [可选] 国标级联在此范围内选择端口发送媒体流,
        send-port-range: 30000,35000 # 端口范围
      # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
      record-assist-port: 18081
    # [根据业务需求配置]
    user-settings:
      # 点播/录像回放 等待超时时间,单位:毫秒
      play-timeout: 180000
      # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
      auto-apply-play: true
      # 设备/通道状态变化时发送消息
      device-status-notify: true
      # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个
      allowed-origins:
        - http://localhost:18080
        - http://192.168.0.213:18080
    # [可选] 日志配置, 一般不需要改
    logging:
      config: classpath:logback-spring-local.xml
    server:
      port: 18080
  3. 打包至服务器 现wvp-pro包路径为192.168.0.213服务器的/home/wvp-GB28181-pro/target 下

  4. 编写服务器运行脚本start.sh

    创建start.sh文件,使用chomd 777 start.sh 为配置文件赋权

#start.sh 命令
nohup java -jar wvp-pro.jar --spring.config.location=application-dev.yml > log.out 2>&1 &
  1. 启动直接./start.sh即可 注意修改事项: 本人在使用过程中,遇到wvp连接zlm后初始化重启zlm服务器的问题,经过测试发现,不重启只修改配置也不影响,而对于服务器性能较差的开发者来说,在zlm重启的时间内,wvp就已经将其置为掉线,重启之后也无法连接,这时便又需要重启wvp服务,如此反复,因此我直接修改wvp-pro包的代码,以上皆为本人需要,各位请自行考虑是否需要更改:在wvp源码中找到MediaServerServiceImpl下的setZLMConfig进行修改

    /**
         * 对zlm服务器进行基础配置
         * @param mediaServerItem 服务ID
         * @param restart 是否重启zlm
         */
        @Override
        public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) {
            logger.info("[ZLM] 正在设置 :{} -> {}:{}",
                    mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
            String protocol = sslEnabled ? "https" : "http";
            String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
    ​
            Map<String, Object> param = new HashMap<>();
            param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
            if (mediaServerItem.getRtspPort() != 0) {
                param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -t 0.001 %s");
            }
            param.put("hook.enable","0"); // 将此属性置为0,默认为1,不然每次重启后都无法推流,需要鉴权
            param.put("hook.on_flow_report","");
            param.put("hook.on_play",String.format("%s/on_play", hookPrex));
            param.put("hook.on_http_access","");
            param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
            param.put("hook.on_record_ts","");
            param.put("hook.on_rtsp_auth","");
            param.put("hook.on_rtsp_realm","");
            param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex));
            param.put("hook.on_shell_login","");
            param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex));
            param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
            param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
            param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
            param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrex));
            param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrex));
            if (mediaServerItem.getRecordAssistPort() > 0) {
                param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));
            }else {
                param.put("hook.on_record_mp4","");
            }
            param.put("hook.timeoutSec","20");
            param.put("protocol.continue_push_ms", "3000" );
            if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
                param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
            }
    ​
            if (userSetting.getRecordPath() != null) {
                File recordPathFile = new File(userSetting.getRecordPath());
                File mp4SavePathFile = recordPathFile.getParentFile().getAbsoluteFile();
                param.put("protocol.mp4_save_path", mp4SavePathFile.getAbsoluteFile());
                param.put("record.appName", recordPathFile.getName());
            }
    ​
            JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param);
    ​
            if (responseJSON != null && responseJSON.getInteger("code") == 0) {
                if (false) { // 将此restart置为false,永不重启,如需重启自己进入docker修改配置后重启即可
                    logger.info("[ZLM] 设置成功,开始重启以保证配置生效 {} -> {}:{}",
                            mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
                    zlmresTfulUtils.restartServer(mediaServerItem);
                }else {
                    logger.info("[ZLM] 设置成功 {} -> {}:{}",
                            mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
                }
    ​
    ​
            }else {
                logger.info("[ZLM] 设置zlm失败 {} -> {}:{}",
                        mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
            }
    ​
    ​
        }
    ​

zlmediakit 推流服务器

zlm包下载与配置

# 使用docker 拉取zlm最新的镜像
docker pull zlmediakit/zlmediakit:master
​
# 启动命令
docker run -d -p 11935:1935 -p 88:80 -p 8443:443 -p 8544:554 -p 10000:10000 -v /opt/media/bin/www/record/:/opt/media/bin/www/record/ zlmediakit/zlmediakit:master
​
# 进入zml流媒体服务器docker容器
docker exec -it 容器id /bin/bash
# 进入config目录
cd ../config 
# 编辑config,ini文件
vim config.ini
​
[api]
apiDebug=1
defaultSnap=./www/logo.png
secret=LluEd5evhoTswSZ1qDnafNEFTCFnnWCe #记录此行secret值,将其填入wvp-pro的yml配置文件种
snapRoot=./www/snap/
[hook]
alive_interval=10.0
enable=0 #将hook中的该值修改为0 这样推流时不用鉴权,如需鉴权请自行开启
[general]
check_nvidia_dev=1
enableVhost=0
enable_ffmpeg_log=0
flowThreshold=1024
maxStreamWaitMS=15000
mediaServerId=xiaomu2012 #将次mediaServerId修改为你所需的,与wvp-pro中的mediaServerId替换
​
#随后退出容器,重启即可

wvp-pro-assist 录像服务配置

源码地址在gitee随便找的:wvp-pro-assist: wvp的辅助录像程序,也可单独跟zlm一起使用,提供录像控制,录像合并下载接口。         里面一些包含有作者根据自身项目的修改,因此下载后可能部分功能不能使用的bug,本人便遇到过,无法保存录像和无法生成可播放的MP4文件格式两种bug

wvp-pro-assist 配置文件

使用which查看ffmpeg的安装目录,如果没有则需要自行安装 ,将地址填入下方yaml配置文件中

which ffmpeg
which ffprobe
 

配置录像目录,我使用的docker映射,其它redis 数据库等配置自行更改

record: /opt/media/bin/www/record
 

spring:
    # REDIS数据库配置
    redis:
        # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
        host: 127.0.0.1
        # [必须修改] 端口号
        port: 6379
        # [可选] 数据库 DB
        database: 8
        # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
        password:
        # [可选] 超时时间
        timeout: 10000

# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
server:
    port: 18081
    # [可选] HTTPS配置, 默认不开启
    ssl:
        # [可选] 是否开启HTTPS访问
        enabled: false
        # [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
        key-store: classpath:xxx.jks
        # [可选] 证书密码
        key-password: password
        # [可选] 证书类型, 默认为jks,根据实际修改
        key-store-type: JKS

# [根据业务需求配置]
userSettings:
    # [可选 ] zlm配置的录像路径,
    record: /opt/media/bin/www/record
    # [可选 ] 录像保存时长(单位: 天)每天晚12点自动对过期文件执行清理
    recordDay: 7
    # [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理
    # recordTempDay: 7
    # [必选 ] ffmpeg路径 
    ffmpeg: /usr/bin/ffmpeg
    # [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息
    ffprobe: /usr/bin/ffprobe
    # [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50%
    threads: 2

swagger-ui:

# [可选] 日志配置, 一般不需要改
logging:
    file:
        name: logs/wvp.log
        max-history: 30
        max-size: 10MB
        total-size-cap: 300MB
    level:
        root: WARN
        top:
            panll:
                assist: info

无法生成可播放的MP4文件格式bug解决方案:

        每次重启之后才去读取zlm中的录像文件,进行转换,这种肯定不能满足业务需求,也有可能录像辅助wvp-pro-assist中有配置的方法,我并没有过多的去观察,直接创建定时任务,去转换本地中的录像文件,编译为wvp-pro可播放识别的文件类型 更好的优化方法为写一个监听方法,每次录像目录文件内容发送变化在进行文件格式转化,避免重复执行,影响效率。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐