Android编译ZLMediaKit之实现NVR功能问题点记录

news2024/11/19 10:25:56

NVR功能

NVR,全称Network Video Recorder,即网络视频录像机,是网络视频监控系统的存储转发部分,NVR与视频编码器或网络摄像机协同工作,完成视频的录像、存储及转发功能。

一、git clone项目

git clone --recursive https://github.com/ZLMediaKit/ZLMediaKit.git

注意–recursive参数,这里用的是递归克隆,避免关联模块没有下载问题

image.png

二、Android studio编译注意事项

image.png

image.png
看到如上图输出的日志即为编译成功,第一次编译完你会发现页面上啥都没有。那要实现我们的功能需求,我们还需要引入一些自己的逻辑代码。

注意如果你本地没有对应的gradle和cmake版本,第一次导入的加载过程可能有点久。

image.png

三、功能接口用例

从NVR的简介中我们可以了解到,其主要功能不就是录像和存储,完全可以不用这么重的框架也可以实现,例如Camera+MediaRecorder,或者麻烦一点用Camera+MediaCodec自己编码保存即可。那么为什么要用ZLMediaKit呢,其实主要是为了方便后期功能扩展,了解录像机的朋友都知道其不光只有录像,还有rtmp、rtsp推流、rtsp-server、GB28181、onvif等功能,这里主要记录一下我在实现各个功能节点上的问题点;

3.1、录制视频

我这里用的是restful api接口控制的方式来实现,C、C++厉害的朋友可以尝试直接JNI将对应功能接口暴露出来理论上应该也是可以。

image.png
看到接口中的app、stream等参数,没接触过的可能有点懵,这里实际对应的是我们往ZLMediaKit推流的地址。

rtmp://127.0.0.1/live/1234

app对应live、stream对应1234,具体请求开启录制如下(前提是应用在往ZLMediaKit中,当然用拉流代理也是可以)

scopeNet {
    var result = Get<ResBaseBean>("http://127.0.0.1/index/api/startRecord") {
        param("type", "1")
        param("vhost", "__defaultVhost__")
        param("app", "live")
        param("stream", "1234")
        param("max_second", 60 * 1)
        param("customized_path", path)
        param("secret", "035c73f7-bb6b-4889-a715-d9eb2d1925cc")
    }.await().result
    LocalLog.e(TAG, "开始接口录制返回结果 :$result") 
}

新手可能会问ResBaseBean对象、网络请求框架 (Net)都是什么,这里都贴出来避免这样的尴尬(毕竟这事我经常干)

class ResBaseBean (val code:Int, val data: DataBean?, val result: Boolean, val status: Boolean){
    class DataBean(val key: String?, val flag:Boolean ,val originUrl: Boolean) {
    }
}

当然了,有开启录制就一定有关闭录制的方法,顺便一起贴出来

scopeNet {
    var result = Get<ResBaseBean>("http://127.0.0.1/index/api/stopRecord") {
        param("type", "1")
        param("vhost", "__defaultVhost__")
        param("app", "live")
        param("stream", "1234")
        param("secret", "035c73f7-bb6b-4889-a715-d9eb2d1925cc")
    }.await().result
}

3.2、视频推流

视频推流这里有两部分别搞混了,首先是将手机摄像头编码推流到ZLMediaKit(只有这个正常了,录制接口等才能正常使用),其次就是把我们这个流再转推到其他流媒体服务器(如云服务器或者国标平台等需求),方便外网访问。

3.2.1、往ZLMediaKit推流

Android端rtmp、rtsp推流的开源项目多的是,大家可以各取所好,图方便的也可以直接用我封装好的推流库,使用也是比较简单的。

初始化推流库

InitRtmpCamera.getInstance().init(context, null, null, 1920, 1080, 15, 3000, 0)
参数说明
Context上下文
SurfaceView本地预览控制,null为无预览推流
CameraCallBack回调
width
height
fps帧率
bitrate码率
rotation角度

开始推流

InitRtmpCamera.getInstance().startPush("rtmp://127.0.0.1/live/1234")

关闭推流

InitRtmpCamera.getInstance().stopPush()

注意使用推流库前先导入aar包,如果文章点击率不错后面会上传JitPack,方便大家在线引用,这里先贴个下载连接:rtmp-stream-demo;

implementation files('libs/rtmp-stream-v1.3.6.aar')

同时不要忘记申请权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
3.2.2、ZLMediaKit往其他流媒体服务器推流

开始推流

scopeNet {
   val pushKey = Get<ResBaseBean>("http://127.0.0.1/index/api/addStreamPusherProxy") {
            param("vhost", "__defaultVhost__")
            param("schema", "rtmp")
            param("app", "live")
            param("stream", "1234")
            param("dst_url", "这里是你自己的推流地址,如:rtmp://IP/live/test")
            param("secret", "035c73f7-bb6b-4889-a715-d9eb2d1925cc")
        }.await().data?.key   
   LocalLog.e(TAG, "开始推流 pushKey:$pushKey")
}

关闭推流

var result = Get<ResBaseBean>("http://127.0.0.1/index/api/delStreamPusherProxy") {
        param("key", pushKey)
        param("secret", "035c73f7-bb6b-4889-a715-d9eb2d1925cc")
    }.await().result

3.3、GB28181转推国标平台

都是调用接口,这里我就不贴代码了,直接看大佬的接口文档

image.png

3.4、其他功能简介

仔细看一下ZLMediaKit的配置文件会解锁更多新技能,这里就留给大家自行扩展吧,感谢夏楚大佬开源这么好的项目。

#!!!!此配置文件为范例配置文件,意在告诉读者,各个配置项的具体含义和作用,
#!!!!该配置文件在执行cmake时,会拷贝至release/${操作系统类型}/${编译类型}(例如release/linux/Debug) 文件夹。
#!!!!该文件夹(release/${操作系统类型}/${编译类型})同时也是可执行程序生成目标路径,在执行MediaServer进程时,它会默认加载同目录下的config.ini文件作为配置文件,
#!!!!你如果修改此范例配置文件(conf/config.ini),并不会被MediaServer进程加载,因为MediaServer进程默认加载的是release/${操作系统类型}/${编译类型}/config.ini。
#!!!!当然,你每次执行cmake,该文件确实会被拷贝至release/${操作系统类型}/${编译类型}/config.ini,
#!!!!但是一般建议你直接修改release/${操作系统类型}/${编译类型}/config.ini文件,修改此文件一般不起作用,除非你运行MediaServer时使用-c参数指定到此文件。

[api]
#是否调试http api,启用调试后,会打印每次http请求的内容和回复
apiDebug=1
#一些比较敏感的http api在访问时需要提供secret,否则无权限调用
#如果是通过127.0.0.1访问,那么可以不提供secret
secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc
#截图保存路径根目录,截图通过http api(/index/api/getSnap)生成和获取
snapRoot=./www/snap/
#默认截图图片,在启动FFmpeg截图后但是截图还未生成时,可以返回默认的预设图片
defaultSnap=./www/logo.png

[ffmpeg]
#FFmpeg可执行程序路径,支持相对路径/绝对路径
bin=/usr/bin/ffmpeg
#FFmpeg拉流再推流的命令模板,通过该模板可以设置再编码的一些参数
cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
#FFmpeg生成截图的命令,可以通过修改该配置改变截图分辨率或质量
snap=%s -i %s -y -f mjpeg -t 0.001 %s
#FFmpeg日志的路径,如果置空则不生成FFmpeg日志
#可以为相对(相对于本可执行程序目录)或绝对路径
log=./ffmpeg/ffmpeg.log
# 自动重启的时间(秒), 默认为0, 也就是不自动重启. 主要是为了避免长时间ffmpeg拉流导致的不同步现象
restart_sec=0

#转协议相关开关;如果addStreamProxy api和on_publish hook回复未指定转协议参数,则采用这些配置项
[protocol]
#转协议时,是否开启帧级时间戳覆盖
modify_stamp=0
#转协议是否开启音频
enable_audio=1
#添加acc静音音频,在关闭音频时,此开关无效
add_mute_audio=1
#推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
#置0关闭此特性(推流断开会导致立即断开播放器)
#此参数不应大于播放器超时时间;单位毫秒
continue_push_ms=15000

#是否开启转换为hls
enable_hls=1
#是否开启MP4录制
enable_mp4=0
#是否开启转换为rtsp/webrtc
enable_rtsp=1
#是否开启转换为rtmp/flv
enable_rtmp=1
#是否开启转换为http-ts/ws-ts
enable_ts=1
#是否开启转换为http-fmp4/ws-fmp4
enable_fmp4=1

#是否将mp4录制当做观看者
mp4_as_player=0
#mp4切片大小,单位秒
mp4_max_second=3600
#mp4录制保存路径
mp4_save_path=./www

#hls录制保存路径
hls_save_path=./www

###### 以下是按需转协议的开关,在测试ZLMediaKit的接收推流性能时,请把下面开关置1
###### 如果某种协议你用不到,你可以把以下开关置1以便节省资源(但是还是可以播放,只是第一个播放者体验稍微差点),
###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
hls_demand=0
#rtsp[s]协议是否按需生成
rtsp_demand=0
#rtmp[s]、http[s]-flv、ws[s]-flv协议是否按需生成
rtmp_demand=0
#http[s]-ts协议是否按需生成
ts_demand=0
#http[s]-fmp4、ws[s]-fmp4协议是否按需生成
fmp4_demand=0

[general]
#是否启用虚拟主机
enableVhost=0
#播放器或推流器在断开后会触发hook.on_flow_report事件(使用多少流量事件),
#flowThreshold参数控制触发hook.on_flow_report事件阈值,使用流量超过该阈值后才触发,单位KB
flowThreshold=1024
#播放最多等待时间,单位毫秒
#播放在播放某个流时,如果该流不存在,
#ZLMediaKit会最多让播放器等待maxStreamWaitMS毫秒
#如果在这个时间内,该流注册成功,那么会立即返回播放器播放成功
#否则返回播放器未找到该流,该机制的目的是可以先播放再推流
maxStreamWaitMS=15000
#某个流无人观看时,触发hook.on_stream_none_reader事件的最大等待时间,单位毫秒
#在配合hook.on_stream_none_reader事件时,可以做到无人观看自动停止拉流或停止接收推流
streamNoneReaderDelayMS=20000
#拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
#如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
resetWhenRePlay=1
#合并写缓存大小(单位毫秒),合并写指服务器缓存一定的数据后才会一次性写入socket,这样能提高性能,但是会提高延时
#开启后会同时关闭TCP_NODELAY并开启MSG_MORE
mergeWriteMS=0
#服务器唯一id,用于触发hook时区别是哪台服务器
mediaServerId=your_server_id

#最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track
wait_track_ready_ms=10000
#如果流只有单Track,最多等待若干毫秒,超时后未收到其他Track的数据,则认为是单Track
#如果协议元数据有声明特定track数,那么无此等待时间
wait_add_track_ms=3000
#如果track未就绪,我们先缓存帧数据,但是有最大个数限制,防止内存溢出
unready_frame_cache=100

[hls]
#hls写文件的buf大小,调整参数可以提高文件io性能
fileBufSize=65536
#hls最大切片时间
segDur=2
#m3u8索引中,hls保留切片个数(实际保留切片个数大2~3个)
#如果设置为0,则不删除切片,而是保存为点播
segNum=3
#HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数
segRetain=5
#是否广播 ts 切片完成通知
broadcastRecordTs=0
#直播hls文件删除延时,单位秒,issue: #913
deleteDelaySec=10
#是否保留hls文件,此功能部分等效于segNum=0的情况
#不同的是这个保留不会在m3u8文件中体现
#0为不保留,不起作用
#1为保留,则不删除hls文件,如果开启此功能,注意磁盘大小,或者定期手动清理hls文件
segKeep=0

[hook]
#在推流时,如果url参数匹对admin_params,那么可以不经过hook鉴权直接推流成功,播放时亦然
#该配置项的目的是为了开发者自己调试测试,该参数暴露后会有泄露隐私的安全隐患
admin_params=secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc
#是否启用hook事件,启用后,推拉流都将进行鉴权
enable=0
#播放器或推流器使用流量事件,置空则关闭
on_flow_report=https://127.0.0.1/index/hook/on_flow_report
#访问http文件鉴权事件,置空则关闭鉴权
on_http_access=https://127.0.0.1/index/hook/on_http_access
#播放鉴权事件,置空则关闭鉴权
on_play=https://127.0.0.1/index/hook/on_play
#推流鉴权事件,置空则关闭鉴权
on_publish=https://127.0.0.1/index/hook/on_publish
#录制mp4切片完成事件
on_record_mp4=https://127.0.0.1/index/hook/on_record_mp4
# 录制 hls ts 切片完成事件
on_record_ts=https://127.0.0.1/index/hook/on_record_ts
#rtsp播放鉴权事件,此事件中比对rtsp的用户名密码
on_rtsp_auth=https://127.0.0.1/index/hook/on_rtsp_auth
#rtsp播放是否开启专属鉴权事件,置空则关闭rtsp鉴权。rtsp播放鉴权还支持url方式鉴权
#建议开发者统一采用url参数方式鉴权,rtsp用户名密码鉴权一般在设备上用的比较多
#开启rtsp专属鉴权后,将不再触发on_play鉴权事件
on_rtsp_realm=https://127.0.0.1/index/hook/on_rtsp_realm
#远程telnet调试鉴权事件
on_shell_login=https://127.0.0.1/index/hook/on_shell_login
#直播流注册或注销事件
on_stream_changed=https://127.0.0.1/index/hook/on_stream_changed
#无人观看流事件,通过该事件,可以选择是否关闭无人观看的流。配合general.streamNoneReaderDelayMS选项一起使用
on_stream_none_reader=https://127.0.0.1/index/hook/on_stream_none_reader
#播放时,未找到流事件,通过配合hook.on_stream_none_reader事件可以完成按需拉流
on_stream_not_found=https://127.0.0.1/index/hook/on_stream_not_found
#服务器启动报告,可以用于服务器的崩溃重启事件监听
on_server_started=https://127.0.0.1/index/hook/on_server_started
#server保活上报
on_server_keepalive=https://127.0.0.1/index/hook/on_server_keepalive
#发送rtp(startSendRtp)被动关闭时回调
on_send_rtp_stopped=https://127.0.0.1/index/hook/on_send_rtp_stopped
#rtp server 超时未收到数据
on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout

#hook api最大等待回复时间,单位秒
timeoutSec=10
#keepalive hook触发间隔,单位秒,float类型
alive_interval=10.0
#hook通知失败重试次数,正整数。为0不重试,1时重试一次,以此类推
retry=1
#hook通知失败重试延时,单位秒,float型
retry_delay=3.0

[cluster]
#设置源站拉流url模板, 格式跟printf类似,第一个%s指定app,第二个%s指定stream_id,
#开启集群模式后,on_stream_not_found和on_stream_none_reader hook将无效.
#溯源模式支持以下类型:
#rtmp方式: rtmp://127.0.0.1:1935/%s/%s
#rtsp方式: rtsp://127.0.0.1:554/%s/%s
#hls方式: http://127.0.0.1:80/%s/%s/hls.m3u8
#http-ts方式: http://127.0.0.1:80/%s/%s.live.ts
#支持多个源站,不同源站通过分号(;)分隔
origin_url=
#溯源总超时时长,单位秒,float型;假如源站有3个,那么单次溯源超时时间为timeout_sec除以3
#单次溯源超时时间不要超过general.maxStreamWaitMS配置
timeout_sec=15
#溯源失败尝试次数,-1时永久尝试
retry_count=3

[http]
#http服务器字符编码,windows上默认gb2312
charSet=utf-8
#http链接超时时间
keepAliveSecond=30
#http请求体最大字节数,如果post的body太大,则不适合缓存body在内存
maxReqSize=40960
#404网页内容,用户可以自定义404网页
#notFound=<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>您访问的资源不存在!</h1></center><hr><center>ZLMediaKit-4.0</center></body></html>
#http服务器监听端口
port=80
#http文件服务器根目录
#可以为相对(相对于本可执行程序目录)或绝对路径
rootPath=./www
#http文件服务器读文件缓存大小,单位BYTE,调整该参数可以优化文件io性能
sendBufSize=65536
#https服务器监听端口
sslport=443
#是否显示文件夹菜单,开启后可以浏览文件夹
dirMenu=1
#虚拟目录, 虚拟目录名和文件路径使用","隔开,多个配置路径间用";"隔开
#例如赋值为 app_a,/path/to/a;app_b,/path/to/b 那么
#访问 http://127.0.0.1/app_a/file_a 对应的文件路径为 /path/to/a/file_a
#访问 http://127.0.0.1/app_b/file_b 对应的文件路径为 /path/to/b/file_b
#访问其他http路径,对应的文件路径还是在rootPath内
virtualPath=
#禁止后缀的文件使用mmap缓存,使用“,”隔开
#例如赋值为 .mp4,.flv
#那么访问后缀为.mp4与.flv 的文件不缓存
forbidCacheSuffix=
#可以把http代理前真实客户端ip放在http头中:https://github.com/ZLMediaKit/ZLMediaKit/issues/1388
#切勿暴露此key,否则可能导致伪造客户端ip
forwarded_ip_header=

[multicast]
#rtp组播截止组播ip地址
addrMax=239.255.255.255
#rtp组播起始组播ip地址
addrMin=239.0.0.0
#组播udp ttl
udpTTL=64

[record]
#mp4录制或mp4点播的应用名,通过限制应用名,可以防止随意点播
#点播的文件必须放置在此文件夹下
appName=record
#mp4录制写文件缓存,单位BYTE,调整参数可以提高文件io性能
fileBufSize=65536
#mp4点播每次流化数据量,单位毫秒,
#减少该值可以让点播数据发送量更平滑,增大该值则更节省cpu资源
sampleMS=500
#mp4录制完成后是否进行二次关键帧索引写入头部
fastStart=0
#MP4点播(rtsp/rtmp/http-flv/ws-flv)是否循环播放文件
fileRepeat=0

[rtmp]
#rtmp必须在此时间内完成握手,否则服务器会断开链接,单位秒
handshakeSecond=15
#rtmp超时时间,如果该时间内未收到客户端的数据,
#或者tcp发送缓存超过这个时间,则会断开连接,单位秒
keepAliveSecond=15
#在接收rtmp推流时,是否重新生成时间戳(很多推流器的时间戳着实很烂)
modifyStamp=0
#rtmp服务器监听端口
port=1935
#rtmps服务器监听地址
sslport=0

[rtp]
#音频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400
#加大该值会明显增加直播延时
audioMtuSize=600
#视频mtu大小,该参数限制rtp最大字节数,推荐不要超过1400
videoMtuSize=1400
#rtp包最大长度限制,单位KB,主要用于识别TCP上下文破坏时,获取到错误的rtp
rtpMaxSize=10
# rtp 打包时,低延迟开关,默认关闭(为0),h264存在一帧多个slice(NAL)的情况,在这种情况下,如果开启可能会导致画面花屏
lowLatency=0

[rtp_proxy]
#导出调试数据(包括rtp/ps/h264)至该目录,置空则关闭数据导出
dumpDir=
#udp和tcp代理服务器,支持rtp(必须是ts或ps类型)代理
port=10000
#rtp超时时间,单位秒
timeoutSec=15
#随机端口范围,最少确保36个端口
#该范围同时限制rtsp服务器udp端口范围
port_range=30000-35000
#rtp h264 负载的pt
h264_pt=98
#rtp h265 负载的pt
h265_pt=99
#rtp ps 负载的pt
ps_pt=96
#rtp ts 负载的pt
ts_pt=33
#rtp opus 负载的pt
opus_pt=100
#rtp g711u 负载的pt
g711u_pt=0
#rtp g711a 负载的pt
g711a_pt=8


[rtc]
#rtc播放推流、播放超时时间
timeoutSec=15
#本机对rtc客户端的可见ip,作为服务器时一般为公网ip,可有多个,用','分开,当置空时,会自动获取网卡ip
#同时支持环境变量,以$开头,如"$EXTERN_IP"; 请参考:https://github.com/ZLMediaKit/ZLMediaKit/pull/1786
externIP=
#rtc udp服务器监听端口号,所有rtc客户端将通过该端口传输stun/dtls/srtp/srtcp数据,
#该端口是多线程的,同时支持客户端网络切换导致的连接迁移
#需要注意的是,如果服务器在nat内,需要做端口映射时,必须确保外网映射端口跟该端口一致
port=8000
#rtc tcp服务器监听端口号,在udp 不通的情况下,会使用tcp传输数据
#该端口是多线程的,同时支持客户端网络切换导致的连接迁移
#需要注意的是,如果服务器在nat内,需要做端口映射时,必须确保外网映射端口跟该端口一致
tcpPort = 8000
#设置remb比特率,非0时关闭twcc并开启remb。该设置在rtc推流时有效,可以控制推流画质
#目前已经实现twcc自动调整码率,关闭remb根据真实网络状况调整码率
rembBitRate=0
#rtc支持的音频codec类型,在前面的优先级更高
#以下范例为所有支持的音频codec
preferredCodecA=PCMU,PCMA,opus,mpeg4-generic
#rtc支持的视频codec类型,在前面的优先级更高
#以下范例为所有支持的视频codec
preferredCodecV=H264,H265,AV1,VP9,VP8

[srt]
#srt播放推流、播放超时时间,单位秒
timeoutSec=5
#srt udp服务器监听端口号,所有srt客户端将通过该端口传输srt数据,
#该端口是多线程的,同时支持客户端网络切换导致的连接迁移
port=9000
#srt 协议中延迟缓存的估算参数,在握手阶段估算rtt ,然后latencyMul*rtt 为最大缓存时长,此参数越大,表示等待重传的时长就越大
latencyMul=4
#包缓存的大小
pktBufSize=8192


[rtsp]
#rtsp专有鉴权方式是采用base64还是md5方式
authBasic=0
#rtsp拉流、推流代理是否是直接代理模式
#直接代理后支持任意编码格式,但是会导致GOP缓存无法定位到I帧,可能会导致开播花屏
#并且如果是tcp方式拉流,如果rtp大于mtu会导致无法使用udp方式代理
#假定您的拉流源地址不是264或265或AAC,那么你可以使用直接代理的方式来支持rtsp代理
#如果你是rtsp推拉流,但是webrtc播放,也建议关闭直接代理模式,
#因为直接代理时,rtp中可能没有sps pps,会导致webrtc无法播放; 另外webrtc也不支持Single NAL Unit Packets类型rtp
#默认开启rtsp直接代理,rtmp由于没有这些问题,是强制开启直接代理的
directProxy=1
#rtsp必须在此时间内完成握手,否则服务器会断开链接,单位秒
handshakeSecond=15
#rtsp超时时间,如果该时间内未收到客户端的数据,
#或者tcp发送缓存超过这个时间,则会断开连接,单位秒
keepAliveSecond=15
#rtsp服务器监听地址
port=554
#rtsps服务器监听地址
sslport=0
#rtsp 转发是否使用低延迟模式,当开启时,不会缓存rtp包,来提高并发,可以降低一帧的延迟
lowLatency=0
[shell]
#调试telnet服务器接受最大bufffer大小
maxReqSize=1024
#调试telnet服务器监听端口
port=0

四、二次封装aar

上班没有时间,大家有需要的话@我,周末有空将所有的api接口功能以及手机摄像头、桌面共享、视频推流到ZLMediaKit功能封装成Android依赖包分享出来给大家。

五、参考资料

ZLMediaKit:https://github.com/ZLMediaKit/ZLMediaKit

rtmp-rtsp-stream-client-java:https://github.com/pedroSG94/rtmp-rtsp-stream-client-java

Net:https://liangjingkanji.github.io/Net/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/110860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ES 的存储原理

目录 一、ES是什么 二、ES基本结构 2.1、结构图 2.2、基本概念 2.3、与关系数据库概念的类比 2.4、数据如何读写 2.5 容灾能力 三、ES的文件存储结构 每个分片的事务日志&#xff08;Transaction Log&#xff09; Index文件夹内文件含义(lucene文件夹) 四、存储步骤…

计算机必备小知识【数据库字段、估算内存】

计算机必备小知识【数据库、内存】 1 mysql数存储类型&#xff08;database&#xff09; 1.1 char与varcha区别 char的存储空间是固定长度&#xff1b;varchar是可变长varchar会比char多1至2个字节来存放数据的长度 1.2 varchar存储 ①varchar能存多少汉字、数字呢&#x…

直播弹幕系统(六)- SpringBoot + STOMP + RabbitMQ(使用MQ替代Spring代理)

直播弹幕系统&#xff08;六&#xff09;- SpringBoot STOMP RabbitMQ&#xff08;使用MQ替代Spring代理&#xff09;前言一. SpringBoot整合RabbitMQ代理Broker1.1 RabbitMQ安装STOMP插件&#xff08;Docker&#xff09;1.2 RabbitMQ相关准备1.3 其他代码二. 前端整合Rabbit…

Prometheus_原理架构-安装部署

文章目录1、prometheus简介常见监控软件优势2、组成图讲解3、安装和配置3.1 容器安装3.2 二进制安装3.3 配置热加载1、prometheus简介 是一个监控软件–》监控容器非常好&#xff0c;也可以监控其他的非容器的机器的业务&#xff0c;例如&#xff1a;MySQL&#xff0c;nginx&am…

locksupport的park和unpark

locksupport是什么 LockSupport是一个线程阻塞工具类&#xff0c;所有的方法都是静态方法&#xff0c;可以让线程在任意位置阻塞&#xff0c;当然阻塞之后肯定得有唤醒的方法。 有什么用 接下面我来看看LockSupport有哪些常用的方法。主要有两类方法&#xff1a;park和unpar…

java:jackson 二:Custom Deserialization in Jackson

java&#xff1a;jackson 二&#xff1a;Custom Deserialization in Jackson 1 前言 jackson支持自定义反序列化器&#xff0c;参考文档地址如下&#xff1a; https://www.baeldung.com/jacksonhttps://www.baeldung.com/jackson-deserialization依赖如下&#xff08;这里使…

基于FPGA的幅频均衡带通滤波器的设计

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 数字通信系统中&#xff0c;由于多径传输、信道衰落等影响&#xff0c;在接收端会产生严重的码间干扰&#xff0c;增大误码率。为了克服码间干扰&#xff0c;提高通信系统的性能&#xff0c;在接…

记录Android Jni编译过程

Gradle配置 我们主要看这个配置文件里面吧&#xff0c;这里面有关于ndk配置的选项。 大概介绍一下&#xff0c;这里面一些字段是干嘛的。 我们看&#xff0c;这里面有两个相仿的字段&#xff0c;都是externalNativeBuild字段&#xff0c;但是位于两个不同的位置&#xff0c;其…

小程序02/小程序 响应式单位rpx 、image组件概念说明 和 mode属性介绍

一. 响应式单位rpx rpx 说明 rpx: 规定不管屏幕为多少px , 100%的屏幕宽度就是750rpx 100% 屏幕的宽度 750rpx rpx响应单位 rpx是微信小程序独有的&#xff0c;解决屏幕自适应的尺寸单位 可以根据屏幕宽度进行自适应&#xff0c;不论大小屏幕&#xff0c;规定屏幕宽为750…

数据首发!空气悬挂前装搭载率破1%,明年冲刺70万套

新能源智能化的合力变革&#xff0c;带动汽车行业进入新的发展周期&#xff1a;如何进一步提升整车轻量化、驾驶和乘坐的安全和体验。这其中&#xff0c;乘用车悬挂系统也在发生新的变化。 此前&#xff0c;除了传统固定式金属螺旋弹簧悬挂&#xff0c;主动悬架系统的前装上车主…

学计算机网络太难?原来方法没用对...

计算机世界里的三座大山: 计算机网络&#xff0c;操作系统&#xff0c;算法与数据结构。跨过去的人都是神一样的存在了。 学计算机网络也要讲究学习方法 从实际案例出发&#xff08;比如我们在浏览器输入一个网址到展示出内容中间发生了什么事情&#xff09; 计算机网络出现的…

简单记录一下怎么看package.json文件

首先每个vue工程文件从仓库克隆代码下来的时候&#xff0c;一般都会包含这个文件&#xff0c;这个文件非常重要&#xff0c;package.json包含了关于项目重要信息&#xff0c;如下图所示 其中包含了name、version、description、author、scripts、dependencies、devDependencies…

Django基础

Django 1.项目的创建 创建项目&#xff1a; 删除一些内容&#xff1a; settings.py中&#xff1a; 2.默认项目文件的介绍 3.APP 创建APP&#xff1a; APP文件介绍&#xff1a; 4.快速上手 APP注册&#xff1a; 在app中找到apps.py&#xff1a; 在django的项目setti…

海量数据处理

1.给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址&#xff1f; 如何找到top K的IP&#xff1f; 思路&#xff1a;&#xff08;哈希切割&#xff09; 1.ip本身就是一个字符串&#xff0c;先把ip变成一个整数hash(ip) 2.文件的下标index…

用知识图谱打开梁山好汉一百单八将

说起《水浒传》大家一定不会陌生&#xff0c;《水浒传》是一部以描写古代农民起义为题材的长篇小说&#xff0c;全书描写北宋末年以宋江为首的108位好汉在梁山聚义&#xff0c;之后接受招安、四处征战的故事。它的一大看点便是其人物的描写&#xff0c;用金人瑞曾评的话说&…

算法之贪心算法

目录 前言&#xff1a; 如何理解贪心算法&#xff1f; 贪心算法的实战分析 分糖果 钱币找零 问题 总结&#xff1a; 参考资料 前言&#xff1a; 贪心算法有很多经典的应用&#xff0c;比如霍夫曼编码&#xff08;Huffman Coding&#xff09;、Prim 和 Kruskal 最小生成树…

Windows下Jenkins常见问题汇总

Jenkins运行时&#xff0c;场景遇到一些奇怪的问题&#xff0c;特别是在Powershell下能运行的命令&#xff0c;在Jenkins下运行就不行。 原因在于其特殊性&#xff1a;Jenkins执行脚本时&#xff0c;不是用当前Windows的登录账户执行的&#xff0c;所以当前登录账户的很多属性&…

数据库,计算机网络、操作系统刷题笔记16

数据库&#xff0c;计算机网络、操作系统刷题笔记16 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle…

【码极客精讲】二维数组

二维数组本质上是以数组作为数组元素的数组&#xff0c;即“数组的数组”&#xff0c;类型说明符 数组名[常量表达式][常量表达式]。二维数组又称为矩阵&#xff0c;行列数相等的矩阵称为方阵。对称矩阵a[i][j] a[j][i]&#xff0c;对角矩阵&#xff1a;n阶方阵主对角线外都是…

Go语言web极速入门-(Gin+Mysql实现后端接口)

文章目录Gin框架github地址 ⬅️点击此处安装Gin及安装框架超时问题解决参考地址 ⬅️点击此处Mysql操作建表增加测试数据代码实现需要导的包数据库连接函数及常量、数据传输结构体业务代码:获取一条信息(GET请求)业务代码:获取多条信息(GET请求)业务代码:保存一条信息(POST请求…