草庐IT

WVP+ZLMediaKit+MediaServerUI实现摄像头GB28181推流播放录制

轻风博客 2023-03-28 原文

本文主要介绍使用 WVP+ZLMediaKit+MediaServerUI 实现通过 GB28181 进行海康、大华、宇视等品牌的 IPCNVR 、DVR 接入,完成摄像头监控播放,控制,录制。

准备工作

1.服务运行环境,Linux / OS X / Windows 均可,但推荐 Linux

2.海康云台摄像头一个

3.运行 sip 服务 WVP https://github.com/swwheihei/wvp-GB28181

4.运行流媒体服务 ZLMediaKit https://github.com/xiongziliang/ZLMediaKit

5.运行前端展示项目 MediaServerUI https://gitee.com/kkkkk5G/MediaServerUI/tree/gb28181/

以上三个项目其实都有文档可供查看,因为踩了一些坑,所以写了本文,文章可能会写得比较细一点,建议结合它们的文档一起看。

运行 WVP

安装 Redis

WVP 项目中将设备信息等存放在 Redis 中,所以需要安装 Redis,安装教程请自行搜索。

配置运行 SIP

首先修改 WVP 项目配置文件:

spring:
    application:
        name: iot-vmp-vmanager
        # 影子数据存储方式,支持redis、jdbc
        database: redis
        # 通信方式,支持kafka、http
        communicate: http
    redis: 
        # Redis服务器IP
        host: 127.0.0.1
        #端口号
        port: 6379
        datebase: 0
        #访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
        password: 123123
        #超时时间
        timeout: 10000
    datasource: 
        name: eiot
        url: jdbc:mysql://host.docker.internal:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
        username: root
        password: 123456
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
sip:
        # SIP 所在服务IP,就是本机IP
    ip: 192.168.1.102
    port: 5060
    # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
    # 后两位为行业编码,定义参照附录D.3
    # 3701020049标识山东济南历下区 信息行业接入
    domain: 3701020049
    id: 37010200492000000002
    # 默认设备认证密码,后续扩展使用设备单独密码
    password: 123456
media:
        # 流媒体服务的IP,内网测试可填内网IP,公网填公网服务器IP并放开端口
    ip: 177.11.11.111
    port: 10000

然后登录海康摄像头管理页面,修改配置:

平台接入选择 28181;传输协议可自选,公网建议选择TCP;协议版本选择 GB/T28181-2016(目前WVP只支持这个协议,2011后面会适配)

SIP服务器ID 和 SIP服务器域密码 要和 WVP 项目中配置的一致。

SIP服务器地址 填写 WVP 项目的地址,内网填写内网IP地址,云服务器填写公网IP,端口写配置文件中配置的端口。

因为摄像头平台接入配置好后,摄像头会请求 SIP 服务,所以这个一定要配置好。

配置完成后就可以运行项目了!如果 SIP 服务启动成功后,会看到这个日志 "Sip Server 启动成功":

如果摄像头连接到 SIP 服务,项目会有这样的日志,显示 200 OK(公网服务器记得放开sip端口):

建立好连接后,就可以控制查询摄像头了。

GET /api/devices 查询所有设备的信息

[
    {
        "deviceId":"37010200492000000001",
        "name":"IP DOME",
        "manufacturer":"Hikvision",
        "model":"DS-2DC4223IW-D/GLT",
        "firmware":"V5.6.15",
        "transport":"TCP",
        "host":{
            "ip":"192.168.1.101",
            "port":1609,
            "address":"192.168.1.101:1609"
        },
        "online":1,
        "channelMap":{
            "34020000001320000001":{
                "channelId":"34020000001320000001",
                "name":"IPdome",
                "manufacture":"Hikvision",
                "model":"IP Camera",
                "owner":"Owner",
                "civilCode":"37010123123",
                "block":null,
                "address":"Address",
                "parental":0,
                "parentId":null,
                "safetyWay":0,
                "registerWay":1,
                "certNum":null,
                "certifiable":0,
                "errCode":0,
                "endTime":null,
                "secrecy":"0",
                "ipAddress":null,
                "port":0,
                "password":null,
                "status":1,
                "longitude":0,
                "latitude":0
            }
        }
    }
]

POST /api/ptz/{deviceId}/{channelId} 云台控制指定设备通道

http://127.0.0.1:8080/api/ptz/34020000001320000001/34020000001320000001?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=1

zoomSpeed 的数字不能太大,不然运行不了,无效。

WVP 项目所有接口:https://github.com/swwheihei/wvp-GB28181/wiki/API-%E6%8E%A5%E5%8F%A3

运行流媒体服务 ZLMediaKit

获取代码

#国内用户推荐从同步镜像网站gitee下载 
git clone --depth 1 https://gitee.com/xiahcu/ZLMediaKit
cd ZLMediaKit
#千万不要忘记执行这句命令
git submodule update --init

构建项目

项目开发者贴心的提供了三个shell脚本在项目根目录:

  • build_docker_images.sh 构建为docker镜像
  • build_for_linux.sh linux下构建项目
  • build_for_mac.sh mac下构建项目

打开以后可以看到是使用CMake来编译的,我们可以直接选择运行shell脚本,Windows的话就看文档跟着一步步来吧?。

构建好后打开 release/xx/Debug 目录,可以看到有 config.ini 是项目的配置文件:https://github.com/xiongziliang/ZLMediaKit/blob/master/conf/config.ini

其中需要特别注意的有两个地方:

一是 [http] 的 port,因为 ZLMediaKit 项目也有很多 API 接口,都需要通过这个接口来访问,包括生成的播放的URL,都是这个端口,如遇到端口被你的其它服务占用,可自行配置。

二是 [rtp_proxy] 的 port,是我们上面 SIP 项目配置的 media.port

配置好了就可以运行项目了。

运行项目

Linux 下启动:

cd ZLMediaKit/release/linux/Debug
#通过-h可以了解启动参数
./MediaServer -h
#以守护进程模式启动
./MediaServer -d &

使用守护进程模式启动后,可以通过 ps -axj 来查看进程

运行成功后会打印出如下日志:

我们可以做下推流测试,非必须操作,不需要可直接跳到下一节“项目推流”,具体操作可以查看文档:https://github.com/xiongziliang/ZLMediaKit/wiki/ZLMediaKit%E6%8E%A8%E6%B5%81%E6%B5%8B%E8%AF%95

下载一个视频文件 big_buck_bunny.mp4 放在当前目录上,使用rtp方式推流试试,在文件所在目录输入命令(没安装ffmpeg的话需要先安装下):

ffmpeg -re -i "big_buck_bunny.mp4" -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000

运行后,查看 ZLMediaKit 项目会有类似这样的日志:

使用可以播放流的播放器(如:PotPlayer,IINA)打开 http://服务器IP/rtp/xxxxx.flv 就能播放了。

如 http://服务器IP/rtp/061484E1.flv

项目推流

SIP 服务和流媒体服务以及就绪了,我们就可以推流了。

拿到 /api/devices 查到的 deviceId 和 channelId,然后调用 SIP 服务的播放接口

GET /api/play/37010200492000000001/34020000001320000001 预览指定设备通道的音视频

成功调用后会返回ssrc:

{"ssrc":"0102008033"}

ssrc 转换为16进制后为 061484E1

我们查看流媒体服务的日志,就能看到如下:

注:公网服务器如果没有收到推流日志,记得开放端口并检查 wvp 项目的 media 配置是否正确。

那我们怎么拿到播放地址呢?其实文档已经有了:https://github.com/xiongziliang/ZLMediaKit/wiki/%E6%92%AD%E6%94%BEurl%E8%A7%84%E5%88%99

如果我的公网IP是177.11.11.111,转换过来就是:

rtsp://177.11.11.111:554/rtp/061484E1?token=abcdefg&field=value

rtmp://177.11.11.111/rtp/061484E1

http://177.11.11.111/rtp/061484E1.flv

http://177.11.11.111/rtp/061484E1/hls.m3u8

此外 ZLMediaKit 还提供了录制,截图,动态添加拉流代理等功能,很棒,大家感兴趣可以看API文档。

运行MediaServerUI

拉下项目代码:https://gitee.com/kkkkk5G/MediaServerUI/tree/gb28181/

项目启动后,SIP 服务调用 play 接口,流媒体服务受到消息,在项目的“视频广场”中就能看到我们的视频了。

这个项目需要注意的也是配置,本项目是和流媒体服务关联的,调用的接口也是流媒体 ZLMediaKit 的 API。

打开项目根目录下的 global.js

const serverip="172.16.63.208"
const host = 'http://' + serverip + '/index/api';
const secret = '035c73f7-bb6b-4889-a715-d9eb2d1925cc';
const baseMediaUrl='ws://' + serverip + '/';
function genApiUrl(method){
    return host+method+"?secret="+secret;
}
export default{
    serverip,
    host,
    secret,
    genApiUrl,
    baseMediaUrl
}

serverip是流媒体服务的IP,如果 ZLMediaKit 的配置文件中 [http] 配置项的端口改成了其它的,也记得在这里加上端口号(不同服务器请配置放开端口哦)。

secret 需要和流媒体服务配置的一样。

baseMediaUrl 是你拉流的url,你可以改成其它的,如 rtsp,rtmp,http。

整个视频请求的流程图

其中流媒体模块指 ZLMediaServer ,接口模块与信令模块指 WVP,视频设备指 IPC、NVR

后记

最后感谢大佬们这么棒的开源项目,谢谢!

 

作者|小米笔记

有关WVP+ZLMediaKit+MediaServerUI实现摄像头GB28181推流播放录制的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  3. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  4. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  5. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  6. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

  7. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

  8. ruby-on-rails - 如何将大于 5GB 的文件上传到 Amazon S3? - 2

    我目前正在使用带有Carrierwavegem的Rails3.2将文件上传到AmazonS3。现在我需要能够处理用户提交的大于5GB的文件,同时仍然使用Carrierwavegem。Carrierwave或Fog是否有任何其他gem或分支可以处理5GB以上的文件上传到S3?编辑:我不想重写一个完整的Rails上传解决方案,所以像这样的链接没有帮助:https://gist.github.com/908875. 最佳答案 我想出了如何做到这一点,并且现在可以正常工作了。在正确的config/environment文件中,添加以下内容以

  9. ruby - 实现k最近邻需要哪些数据? - 2

    我目前有一个reddit克隆类型的网站。我正在尝试根据我的用户之前喜欢的帖子推荐帖子。看起来K最近邻或k均值是执行此操作的最佳方法。我似乎无法理解如何实际实现它。我看过一些数学公式(例如k表示维基百科页面),但它们对我来说并没有真正意义。有人可以推荐一些伪代码,或者可以查看的地方,以便我更好地了解如何执行此操作吗? 最佳答案 K最近邻(又名KNN)是一种分类算法。基本上,您采用包含N个项目的训练组并对它们进行分类。如何对它们进行分类完全取决于您的数据,以及您认为该数据的重要分类特征是什么。在您的示例中,这可能是帖子类别、谁发布了该项

  10. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

随机推荐