增加视频模块相关代码

This commit is contained in:
15683799673
2025-07-16 02:35:44 +08:00
parent be7002153c
commit fa28f2d351
21 changed files with 1187 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
package org.dromara.sis.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "zlm")
public class ZLMediaKitConfig {
private String ip;
private String apiSecret;
private Short rtspPort;
private Short rtmpPort;
private Short httpPort;
private String vhost;
}

View File

@@ -0,0 +1,125 @@
package org.dromara.sis.controller.zkmedia;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.sis.sdk.zkmedia.MediaServerUtils;
import org.dromara.sis.sdk.zkmedia.ZLMediaKitService;
import org.dromara.sis.sdk.zkmedia.model.AddStreamProxy;
import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp;
import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* ZKLmedia 流媒体服务
*
* @author lxj
* @since 2025-07-15
*/
@Slf4j
@RestController
@RequestMapping("/stream")
public class ZKLmediaController {
@Resource
private ZLMediaKitService zlMediaKitService;
private static final String HIK_REALTIME_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/Streaming/Channels/%s";
private static final String DAHUA_REALTIME_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/cam/realmonitor?channel=%s&subtype=0";
private static final String HIK_HISTORY_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/Streaming/tracks/%s?starttime=%s&endtime=%s";
private static final String DAHUA_HISTORY_RTSP_TEMPLATE = "rtsp://%s:%s@%s:%s/cam/playback?channel=%s&subtype=0&starttime=%s&endtime=%s";
/**
* 创建拉流任务返回null代表创建拉流任务失败
*
* @param data 创建拉流设备信息(如果外网不建议使用这种方式)
* @return 返回拉流任务信息
*/
@PostMapping("/realtime/add")
public R<AddStreamProxyResp> alarm(@RequestBody @Validated AddStreamProxy data) {
StartStreamProxy proxy = new StartStreamProxy();
proxy.setApp("realtime");
String s = IdUtil.fastSimpleUUID();
proxy.setStream(s);
if ("DS1010".equals(data.getFactoryNo())) {
proxy.setUrl(String.format(HIK_REALTIME_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId()));
} else if ("DS1014".equals(data.getFactoryNo())) {
proxy.setUrl(String.format(DAHUA_REALTIME_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId()));
} else {
throw new RuntimeException("未知的设备类型!");
}
AddStreamProxyResp addStreamProxyResp = zlMediaKitService.addStreamProxy(proxy);
if (addStreamProxyResp != null) {
return R.ok(addStreamProxyResp);
}
return R.fail();
}
/**
* 创建历史回放拉流任务返回null代表创建拉流任务失败
*
* @param data 创建拉流设备信息(如果外网不建议使用这种方式)
* @return 返回拉流任务信息
*/
@PostMapping("/history/add")
public R<AddStreamProxyResp> history(@RequestBody @Validated AddStreamProxy data) throws InterruptedException {
StartStreamProxy proxy = new StartStreamProxy();
proxy.setApp("history");
String s = IdUtil.fastSimpleUUID();
proxy.setStream(s);
if ("DS1010".equals(data.getFactoryNo())) {
String pattern = "yyyyMMdd'T'HHmmss'Z'";
String startTime = MediaServerUtils.formatTimestamp(data.getStartTime(), "yyyyMMdd'T'HHmmss'Z'");
String endTime = MediaServerUtils.formatTimestamp(data.getEndTime(), "yyyyMMdd'T'HHmmss'Z'");
proxy.setUrl(String.format(HIK_HISTORY_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId(), startTime, endTime));
} else if ("DS1014".equals(data.getFactoryNo())) {
String startTime = MediaServerUtils.formatTimestamp(data.getStartTime(), "yyyy_MM_dd_HH_mm_ss");
String endTime = MediaServerUtils.formatTimestamp(data.getEndTime(), "yyyy_MM_dd_HH_mm_ss");
proxy.setUrl(String.format(DAHUA_HISTORY_RTSP_TEMPLATE, data.getAccount(), data.getPwd(), data.getVideoIp(), data.getVideoPort(), data.getChannelId(), startTime, endTime));
} else {
throw new RuntimeException("未知的设备类型!");
}
AddStreamProxyResp addStreamProxyResp = zlMediaKitService.addStreamProxy(proxy);
if (addStreamProxyResp != null) {
return R.ok(addStreamProxyResp);
}
return R.fail();
}
/**
* 查询设备的信息
*
* @param data 设备ip
* @return
*/
/*@PostMapping("/queryMediaInfo")
public R<TpEqpAcquisitionDTO> queryMediaInfo(@RequestBody VideoConfigTreeDTO data) {
if (StringUtils.isEmpty(data.getVideoIp())) {
throw new BizException(ErrorType.VIDEOIP_FAIL, "视频IP不能为空");
}
logger.info("查询视频信息,参数:{}", JSONObject.toJSON(data.getVideoIp()));
TpEqpAcquisitionDTO result = tpEqpAcquisitionService.queryConfigByEqpNo(data.getVideoIp());
logger.info("查询视频信息,返回信息:{}", JSONObject.toJSON(result));
return BizResultVO.success(result);
}
@PostMapping("/history/delete/{stream}")
public BizResultVO<String> delete(@PathVariable("stream") String stream) throws InterruptedException {
StartStreamProxy proxy = new StartStreamProxy();
proxy.setApp("history");
proxy.setStream(stream);
String ss = zlMediaKitService.delStreamProxy(proxy);
if (ss != null) {
return BizResultVO.success(ss);
}
return BizResultVO.fail(ErrorType.ADD_STREAMPROXY_FAIL, null);
}*/
}

View File

@@ -0,0 +1,94 @@
package org.dromara.sis.sdk.zkmedia;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.dromara.sis.sdk.zkmedia.model.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class HttpClientUtil {
public static <T> T get(String url, Map<String, Object> params, TypeReference<T> reference) {
String s = get(url, params);
return JSONObject.parseObject(s, reference);
}
public static <T> R<T> get(String url, Map<String, Object> params, Class<T> cls) {
String s = get(url, params);
return JSONObject.parseObject(s, new TypeReference<R<T>>(cls) {
});
}
public static String get(String url, Map<String, Object> params) {
if (params != null && !params.isEmpty()) {
List<String> ls = new ArrayList<>(params.size());
for (Map.Entry<String, Object> entry : params.entrySet()) {
ls.add(entry.getKey() + "=" + entry.getValue());
}
url = url + "?" + CollectionUtil.join(ls, "&");
}
CloseableHttpResponse response;
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpGet httpGet = new HttpGet(url);
response = httpClient.execute(httpGet);
log.info("ZLM请求成功,url={}, code={}", url, response.getStatusLine().getStatusCode());
HttpEntity entity = response.getEntity();
String res = EntityUtils.toString(entity);
log.info("ZLM请求成功,result={}", res);
return res;
} catch (Exception e) {
log.info("ZLM发起请求失败,msg={}", e.getMessage());
return null;
}
}
public static <T> T post(String url, Map<String, Object> header, Map<String, Object> body, TypeReference<T> reference) {
String res = post(url, header, body);
return JSONObject.parseObject(res, reference);
}
public static <T> R<T> post(String url, Map<String, Object> header, Map<String, Object> body, Class<T> cls) {
String res = post(url, header, body);
return JSONObject.parseObject(res, new TypeReference<R<T>>(cls) {
});
}
public static String post(String url, Map<String, Object> header, Map<String, Object> body) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json");
if (header != null && !header.isEmpty()) {
for (Map.Entry<String, Object> entry : header.entrySet()) {
httpPost.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
}
}
if (body != null && !body.isEmpty()) {
httpPost.setEntity(new StringEntity(JSONObject.toJSONString(body)));
}
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
} catch (Exception e) {
log.info("ZLM发起请求失败,msg={}", e.getMessage());
return null;
}
}
}

View File

@@ -0,0 +1,36 @@
package org.dromara.sis.sdk.zkmedia;
import org.springframework.util.ObjectUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class MediaServerUtils {
public static Map<String, String> urlParamToMap(String params) {
HashMap<String, String> map = new HashMap<>();
if (ObjectUtils.isEmpty(params)) {
return map;
}
String[] paramsArray = params.split("&");
if (paramsArray.length == 0) {
return map;
}
for (String param : paramsArray) {
String[] paramArray = param.split("=");
if (paramArray.length == 2) {
map.put(paramArray[0], paramArray[1]);
}
}
return map;
}
public static String formatTimestamp(String timestamp, String pattern) {
Date date = new Date(Long.parseLong(timestamp));
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(date);
}
}

View File

@@ -0,0 +1,159 @@
package org.dromara.sis.sdk.zkmedia;
import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp;
import org.dromara.sis.sdk.zkmedia.model.R;
import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy;
import org.dromara.sis.sdk.zkmedia.model.ThreadsLoadDelay;
import java.util.List;
public interface ZLMediaKitService {
/**
* 获取各后台 epoll(或 select)线程负载以及延时
*/
R<List<ThreadsLoadDelay>> getWorkThreadsLoad();
/**
* 获取ZLMediaKit服务器配置信息
*/
Object getServerConfig();
/**
* 设置服务器配置
*/
Object setServerConfig();
/**
* 重启服务器,只有 Daemon 方式才能重启,否则是直接关闭!
*/
Object restartServer();
/**
* 获取流列表,可选筛选参数
*/
Object getMediaList();
/**
* 关闭流(目前所有类型的流都支持关闭)
*/
Object closeStreams();
/**
* 获取所有 TcpSession 列表(获取所有 tcp 客户端相关信息)
*/
Object getAllSession();
/**
* 断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等
*/
Object kickSession();
/**
* 断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等
*/
Object kickSessions();
/**
* 动态添加 rtsp/rtmp/hls/http-ts/http-flv 拉流代理(只支持 H264/H265/aac/G711/opus 负载)
*/
AddStreamProxyResp addStreamProxy(StartStreamProxy startStreamProxy);
/**
* (流注册成功后也可以使用close_streams接口替代)
* 关闭拉流代理
*/
String delStreamProxy(StartStreamProxy startStreamProxy);
/**
* 通过 fork FFmpeg 进程的方式拉流代理,支持任意协议
*/
Object addFFmpegSource();
/**
* 流注册成功后也可以使用close_streams接口替代
*/
Object delFFmpegSource();
/**
* 获取 rtp 代理时的某路 ssrc rtp 信息
*/
Object getRtpInfo();
/**
* 搜索文件系统,获取流对应的录像文件列表或日期文件夹列表
*/
Object getMp4RecordFile();
/**
* 开始录制 hls 或 MP4
*/
Object startRecord();
/**
* 停止录制流
*/
Object stopRecord();
/**
* 获取流录制状态
*/
Object isRecording();
/**
* 获取截图或生成实时截图并返回
*/
Object getSnap();
/**
* 创建 GB28181 RTP 接收端口,如果该端口接收数据超时,则会自动被回收(不用调用 closeRtpServer 接口)
*/
Object openRtpServer();
/**
* 关闭 GB28181 RTP 接收端口
*/
Object closeRtpServer();
/**
* 获取 openRtpServer 接口创建的所有 RTP 服务器
*/
Object listRtpServer();
/**
* 作为 GB28181 客户端,启动 ps-rtp 推流,支持 rtp/udp 方式;该接口支持 rtsp/rtmp 等协议转 ps-rtp 推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试。
*/
Object startSendRtp();
/**
* 停止 GB28181 ps-rtp 推流
*/
Object stopSendRtp();
/**
* 获取主要对象个数统计,主要用于分析内存性能
*/
Object getStatistic();
/**
* 添加 rtsp/rtmp 主动推流(把本服务器的直播流推送到其他服务器去)
*/
Object addStreamPusherProxy();
/**
* 关闭推流,可以使用close_streams接口关闭源直播流也可以停止推流)
*/
Object delStreamPusherProxy();
/**
* 获取版本信息如分支commit id, 编译时间
*/
Object getVersion();
/**
* 获取某个流观看者列表
*/
Object getMediaPlayerList();
}

View File

@@ -0,0 +1,248 @@
package org.dromara.sis.sdk.zkmedia;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sis.config.ZLMediaKitConfig;
import org.dromara.sis.sdk.zkmedia.model.AddStreamProxyResp;
import org.dromara.sis.sdk.zkmedia.model.R;
import org.dromara.sis.sdk.zkmedia.model.StartStreamProxy;
import org.dromara.sis.sdk.zkmedia.model.ThreadsLoadDelay;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service("com.parkclouds.media.service.ZLMediaKitServiceImpl")
public class ZLMediaKitServiceImpl implements ZLMediaKitService {
@Resource
private ZLMediaKitConfig zlmConfig;
private static volatile String ZLM_REQUEST_PREFIX = null;
public String getRequestUrl(String uri) {
if (ZLM_REQUEST_PREFIX == null) {
synchronized (ZLMediaKitServiceImpl.class) {
if (ZLM_REQUEST_PREFIX == null) {
ZLM_REQUEST_PREFIX = String.format("http://%s:%d/index/api/", zlmConfig.getIp(), zlmConfig.getHttpPort());
}
}
}
return ZLM_REQUEST_PREFIX + uri;
}
public Map<String, Object> getCommonParams() {
Map<String, Object> params = new HashMap<>(16);
params.put("secret", zlmConfig.getApiSecret());
return params;
}
@Override
public R<List<ThreadsLoadDelay>> getWorkThreadsLoad() {
String url = getRequestUrl("getThreadsLoad");
Map<String, Object> commonParams = getCommonParams();
return HttpClientUtil.get(url, commonParams, new TypeReference<R<List<ThreadsLoadDelay>>>() {
});
}
@Override
public Object getServerConfig() {
return null;
}
@Override
public Object setServerConfig() {
return null;
}
@Override
public Object restartServer() {
return null;
}
@Override
public Object getMediaList() {
return null;
}
@Override
public Object closeStreams() {
return null;
}
@Override
public Object getAllSession() {
return null;
}
@Override
public Object kickSession() {
return null;
}
@Override
public Object kickSessions() {
return null;
}
/**
* 获取拉流地址
*/
private AddStreamProxyResp setPlayerUrl(String app, String streamId, AddStreamProxyResp resp) {
if (resp == null) {
resp = new AddStreamProxyResp();
}
// RTMP 播放地址
resp.setRtmp(String.format("rtmp://%s:%d/%s/%s", zlmConfig.getIp(), zlmConfig.getRtmpPort(), app, streamId));
// RTSP 播放地址
resp.setRtsp(String.format("rtsp://%s:%d/%s/%s", zlmConfig.getIp(), zlmConfig.getRtspPort(), app, streamId));
// HTTP-FLV 播放地址
resp.setFlv(String.format("http://%s:%d/%s/%s.live.flv", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId));
resp.setWsFlv(String.format("ws://%s:%d/%s/%s.live.flv", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId));
// HLS 播放地址
resp.setHls(String.format("http://%s:%d/%s/%s/hls.m3u8", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId));
// MP4 播放地址
resp.setMp4(String.format("http://%s:%d/%s/%s.live.mp4", zlmConfig.getIp(), zlmConfig.getHttpPort(), app, streamId));
return resp;
}
@Override
public AddStreamProxyResp addStreamProxy(StartStreamProxy startStreamProxy) {
Map<String, Object> commonParams = getCommonParams();
commonParams.put("vhost", zlmConfig.getVhost());
commonParams.put("app", startStreamProxy.getApp());
commonParams.put("stream", startStreamProxy.getStream());
commonParams.put("url", startStreamProxy.getUrl());
commonParams.put("rtp_type", startStreamProxy.getRtpType());
R<AddStreamProxyResp> result = HttpClientUtil.get(getRequestUrl("addStreamProxy"), commonParams, AddStreamProxyResp.class);
if (result != null) {
if (result.getCode() == 0) {
log.info("创建拉流任务成功.");
}
// 此处代表拉流任务已存在
if (result.getCode() == -1) {
log.info("拉流任务已存在,返回播放地址。");
}
return setPlayerUrl(startStreamProxy.getApp(), startStreamProxy.getStream(), result.getData());
}
return null;
}
@Override
public String delStreamProxy(StartStreamProxy startStreamProxy) {
Map<String, Object> commonParams = getCommonParams();
commonParams.put("schema", "rtsp");
commonParams.put("vhost", zlmConfig.getVhost());
commonParams.put("app", startStreamProxy.getApp());
commonParams.put("stream", startStreamProxy.getStream());
commonParams.put("force", 1);
R<AddStreamProxyResp> result = HttpClientUtil.get(getRequestUrl("close_streams"), commonParams, AddStreamProxyResp.class);
if (result != null) {
String s =null;
if (result.getCode() == 0) {
s = "关闭流成功";
}
// 此处代表拉流任务已存在
if (result.getCode() == -1) {
s = "关闭流失败";
}
log.info("{},关闭流数量:{}",s,result.getData());
return s;
}
return null;
}
@Override
public Object addFFmpegSource() {
return null;
}
@Override
public Object delFFmpegSource() {
return null;
}
@Override
public Object getRtpInfo() {
return null;
}
@Override
public Object getMp4RecordFile() {
return null;
}
@Override
public Object startRecord() {
return null;
}
@Override
public Object stopRecord() {
return null;
}
@Override
public Object isRecording() {
return null;
}
@Override
public Object getSnap() {
return null;
}
@Override
public Object openRtpServer() {
return null;
}
@Override
public Object closeRtpServer() {
return null;
}
@Override
public Object listRtpServer() {
return null;
}
@Override
public Object startSendRtp() {
return null;
}
@Override
public Object stopSendRtp() {
return null;
}
@Override
public Object getStatistic() {
return null;
}
@Override
public Object addStreamPusherProxy() {
return null;
}
@Override
public Object delStreamPusherProxy() {
return null;
}
@Override
public Object getVersion() {
return null;
}
@Override
public Object getMediaPlayerList() {
return null;
}
}

View File

@@ -0,0 +1,36 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class AddStreamProxy {
@NotBlank
private String videoIp;
@NotNull
private Integer videoPort;
@NotBlank
private String factoryNo;
@NotBlank
private String account;
@NotBlank
private String pwd;
@NotNull
private String channelId;
private String startTime;
private String endTime;
private String stream;
}

View File

@@ -0,0 +1,23 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class AddStreamProxyResp implements Serializable {
private String key;
private String rtsp;
private String rtmp;
private String flv;
private String wsFlv;
private String mp4;
private String hls;
}

View File

@@ -0,0 +1,14 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
/**
* zlm hook事件的参数
* @author lin
*/
@Data
public class HookParam {
private String mediaServerId;
}

View File

@@ -0,0 +1,28 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class HookResult {
private int code;
private String msg;
// 此字段在部分返回结果中用到
private Boolean close;
public HookResult() {
}
public HookResult(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static HookResult SUCCESS() {
return new HookResult(0, "success");
}
}

View File

@@ -0,0 +1,17 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class HookResultForOnPublish extends HookResult {
private boolean enable_audio;
private boolean enable_mp4;
private int mp4_max_second;
private String mp4_save_path;
private String stream_replace;
private Integer modify_stamp;
}

View File

@@ -0,0 +1,22 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* zlm hook事件中的on_play事件的参数
*
* @author lin
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OnPlayHookParam extends HookParam {
private String id;
private String app;
private String stream;
private String ip;
private String params;
private int port;
private String schema;
private String vhost;
}

View File

@@ -0,0 +1,29 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class OnPushParam extends HookParam{
private String app;
private String id;
private String ip;
private String params;
private Integer port;
private String schema;
private String stream;
private String vhost;
}

View File

@@ -0,0 +1,20 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* zlm hook事件中的on_play事件的参数
*
* @author lin
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OnServerKeepaliveHookParam extends HookParam {
private Object data;
private Integer hook_index;
}

View File

@@ -0,0 +1,203 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.Map;
/**
* @author lin
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OnStreamChangedHookParam extends HookParam {
/**
* 注册/注销
*/
private boolean regist;
/**
* 应用名
*/
private String app;
/**
* 流id
*/
private String stream;
/**
* 推流鉴权Id
*/
private String callId;
/**
* 观看总人数包括hls/rtsp/rtmp/http-flv/ws-flv
*/
private int totalReaderCount;
/**
* 协议 包括hls/rtsp/rtmp/http-flv/ws-flv
*/
private String schema;
/**
* 产生源类型,
* unknown = 0,
* rtmp_push=1,
* rtsp_push=2,
* rtp_push=3,
* pull=4,
* ffmpeg_pull=5,
* mp4_vod=6,
* device_chn=7
*/
private int originType;
/**
* 客户端和服务器网络信息可能为null类型
*/
private OriginSock originSock;
/**
* 产生源类型的字符串描述
*/
private String originTypeStr;
/**
* 产生源的url
*/
private String originUrl;
/**
* 服务器id
*/
private String severId;
/**
* GMT unix系统时间戳单位秒
*/
private Long createStamp;
/**
* 存活时间,单位秒
*/
private Long aliveSecond;
/**
* 数据产生速度单位byte/s
*/
private Long bytesSpeed;
/**
* 音视频轨道
*/
private List<MediaTrack> tracks;
/**
* 音视频轨道
*/
private String vhost;
/**
* 额外的参数字符串
*/
private String params;
/**
* 额外的参数
*/
private Map<String, String> paramMap;
@Data
public static class MediaTrack {
/**
* 音频通道数
*/
private int channels;
/**
* H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
*/
private int codec_id;
/**
* 编码类型名称 CodecAAC CodecH264
*/
private String codec_id_name;
/**
* Video = 0, Audio = 1
*/
private int codec_type;
/**
* 轨道是否准备就绪
*/
private boolean ready;
/**
* 音频采样位数
*/
private int sample_bit;
/**
* 音频采样率
*/
private int sample_rate;
/**
* 视频fps
*/
private float fps;
/**
* 视频高
*/
private int height;
/**
* 视频宽
*/
private int width;
/**
* 帧数
*/
private int frames;
/**
* 关键帧数
*/
private int key_frames;
/**
* GOP大小
*/
private int gop_size;
/**
* GOP间隔时长(ms)
*/
private int gop_interval_ms;
/**
* 丢帧率
*/
private float loss;
}
@Data
public static class OriginSock {
private String identifier;
private String local_ip;
private int local_port;
private String peer_ip;
private int peer_port;
}
}

View File

@@ -0,0 +1,15 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class OnStreamNoneReaderHookParam extends HookParam{
private String schema;
private String app;
private String stream;
private String vhost;
}

View File

@@ -0,0 +1,21 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* zlm hook事件中的on_stream_not_found事件的参数
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OnStreamNotFoundHookParam extends HookParam {
private String id;
private String app;
private String stream;
private String ip;
private String params;
private int port;
private String schema;
private String vhost;
}

View File

@@ -0,0 +1,12 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
@Data
public class R<T> {
private Integer code;
private T data;
}

View File

@@ -0,0 +1,25 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
@Data
public class ServerKeepaliveData {
private Integer Buffer;
private String BufferLikeString;
private Integer BufferList;
private Integer BufferRaw;
private Integer Frame;
private Integer FrameImp;
private Integer MediaSource;
private Integer MultiMediaSourceMuxer;
private Integer RtmpPacket;
private Integer RtpPacket;
private Integer Socket;
private Integer TcpClient;
private Integer TcpServer;
private Integer TcpSession;
private Integer UdpServer;
private Integer UdpSession;
}

View File

@@ -0,0 +1,18 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
import java.io.Serializable;
@Data
public class StartStreamProxy implements Serializable {
private String app = "live";
private String stream;
private String url;
private Integer rtpType = 1;
}

View File

@@ -0,0 +1,18 @@
package org.dromara.sis.sdk.zkmedia.model;
import lombok.Data;
@Data
public class ThreadsLoadDelay {
/**
* 该线程延时
*/
private Integer delay;
/**
* 该线程负载0 ~ 100
*/
private Integer load;
}