src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -87,6 +87,9 @@ @Value("${media.record-path:}") private String recordPath; @Value("${media.type:zlm}") private String type; public String getId() { return id; } @@ -217,8 +220,10 @@ mediaServerItem.setRtpPortRange(rtpPortRange); mediaServerItem.setSendRtpPortRange(rtpSendPortRange); mediaServerItem.setRecordAssistPort(recordAssistPort); mediaServerItem.setHookAliveInterval(30.00f); mediaServerItem.setHookAliveInterval(10f); mediaServerItem.setRecordDay(recordDay); mediaServerItem.setStatus(false); mediaServerItem.setType(type); if (recordPath != null) { mediaServerItem.setRecordPath(recordPath); } src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
@@ -1,16 +1,18 @@ package com.genersoft.iot.vmp.gb28181.event; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.media.zlm.event.MediaServerOfflineEvent; import com.genersoft.iot.vmp.media.zlm.event.MediaServerOnlineEvent; import com.genersoft.iot.vmp.media.event.MediaServerOfflineEvent; import com.genersoft.iot.vmp.media.event.MediaServerOnlineEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import javax.sip.TimeoutEvent; import java.util.ArrayList; @@ -39,7 +41,7 @@ applicationEventPublisher.publishEvent(alarmEvent); } public void zlmOfflineEventPublish(String mediaServerId){ public void mediaServerOfflineEventPublish(String mediaServerId){ MediaServerOfflineEvent outEvent = new MediaServerOfflineEvent(this); outEvent.setMediaServerId(mediaServerId); applicationEventPublisher.publishEvent(outEvent); src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java
@@ -38,11 +38,19 @@ // æ¸ çææå¨çº¿èç¹çç¼åä¿¡æ¯ mediaServerService.clearMediaServerForOnline(); MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer(); if (defaultMediaServer == null) { mediaServerService.addToDatabase(mediaConfig.getMediaSerItem()); MediaServerItem mediaSerItemInConfig = mediaConfig.getMediaSerItem(); if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) { mediaServerService.update(mediaSerItemInConfig); }else { MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); mediaServerService.updateToDatabase(mediaSerItem); if (defaultMediaServer != null) { mediaServerService.delete(defaultMediaServer.getId()); } MediaServerItem mediaServerItem = mediaServerService.getOneFromDatabase(mediaSerItemInConfig.getId()); if (mediaServerItem == null) { mediaServerService.add(mediaSerItemInConfig); }else { mediaServerService.update(mediaSerItemInConfig); } } // åéåªä½èç¹ååäºä»¶ mediaServerService.syncCatchFromDatabase(); src/main/java/com/genersoft/iot/vmp/media/abl/ABLMediaNodeServerService.java
@@ -42,4 +42,9 @@ public void online(MediaServerItem mediaServerItem) { } @Override public MediaServerItem checkMediaServer(String ip, int port, String secret) { return null; } } src/main/java/com/genersoft/iot/vmp/media/event/MediaServerChangeEvent.java
@@ -3,6 +3,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import org.springframework.context.ApplicationEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -23,6 +24,7 @@ } public void setMediaServerItemList(MediaServerItem... mediaServerItemArray) { this.mediaServerItemList = new ArrayList<>(); this.mediaServerItemList.addAll(Arrays.asList(mediaServerItemArray)); } src/main/java/com/genersoft/iot/vmp/media/event/MediaServerDeleteEvent.java
New file @@ -0,0 +1,11 @@ package com.genersoft.iot.vmp.media.event; /** * zlmå¨çº¿äºä»¶ */ public class MediaServerDeleteEvent extends MediaServerEventAbstract { public MediaServerDeleteEvent(Object source) { super(source); } } src/main/java/com/genersoft/iot/vmp/media/event/MediaServerEventAbstract.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/zlm/event/MediaServerEventAbstract.java @@ -1,4 +1,4 @@ package com.genersoft.iot.vmp.media.zlm.event; package com.genersoft.iot.vmp.media.event; import org.springframework.context.ApplicationEvent; src/main/java/com/genersoft/iot/vmp/media/event/MediaServerOfflineEvent.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/zlm/event/MediaServerOfflineEvent.java @@ -1,4 +1,6 @@ package com.genersoft.iot.vmp.media.zlm.event; package com.genersoft.iot.vmp.media.event; import com.genersoft.iot.vmp.media.event.MediaServerEventAbstract; /** * zlm离线äºä»¶ç±» src/main/java/com/genersoft/iot/vmp/media/event/MediaServerOnlineEvent.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/zlm/event/MediaServerOnlineEvent.java @@ -1,4 +1,6 @@ package com.genersoft.iot.vmp.media.zlm.event; package com.genersoft.iot.vmp.media.event; import com.genersoft.iot.vmp.media.event.MediaServerEventAbstract; /** * zlmå¨çº¿äºä»¶ src/main/java/com/genersoft/iot/vmp/media/event/MediaServerStatusEventListener.java
File was renamed from src/main/java/com/genersoft/iot/vmp/media/zlm/event/MediaServerStatusEventListener.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.media.zlm.event; package com.genersoft.iot.vmp.media.event; import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamPushService; @@ -31,15 +30,12 @@ private IStreamProxyService streamProxyService; @Autowired private IMediaServerService mediaServerService; @Autowired private IPlayService playService; @Async("taskExecutor") @EventListener public void onApplicationEvent(MediaServerOnlineEvent event) { logger.info("[ZLM] ä¸çº¿ IDï¼" + event.getMediaServerId()); logger.info("[åªä½èç¹] ä¸çº¿ IDï¼" + event.getMediaServerId()); streamPushService.zlmServerOnline(event.getMediaServerId()); streamProxyService.zlmServerOnline(event.getMediaServerId()); playService.zlmServerOnline(event.getMediaServerId()); @@ -49,9 +45,8 @@ @EventListener public void onApplicationEvent(MediaServerOfflineEvent event) { logger.info("[ZLM] 离线ï¼IDï¼" + event.getMediaServerId()); logger.info("[åªä½èç¹] 离线ï¼IDï¼" + event.getMediaServerId()); // å¤çZLM离线 mediaServerService.zlmServerOffline(event.getMediaServerId()); streamProxyService.zlmServerOffline(event.getMediaServerId()); streamPushService.zlmServerOffline(event.getMediaServerId()); playService.zlmServerOffline(event.getMediaServerId()); src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java
@@ -17,4 +17,6 @@ boolean checkNodeId(MediaServerItem mediaServerItem); void online(MediaServerItem mediaServerItem); MediaServerItem checkMediaServer(String ip, int port, String secret); } src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java
@@ -1,9 +1,7 @@ package com.genersoft.iot.vmp.media.service; import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; import com.genersoft.iot.vmp.service.bean.MediaServerLoad; import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -13,6 +11,8 @@ * åªä½æå¡èç¹ */ public interface IMediaServerService { List<MediaServerItem> getAllOnlineList(); List<MediaServerItem> getAll(); @@ -24,23 +24,7 @@ void syncCatchFromDatabase(); /** * æ°çèç¹å å ¥ * @param zlmServerConfig * @return */ void zlmServerOnline(ZLMServerConfig zlmServerConfig); /** * èç¹ç¦»çº¿ * @param mediaServerId * @return */ void zlmServerOffline(String mediaServerId); MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist); void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); void updateVmServer(List<MediaServerItem> mediaServerItemList); @@ -70,30 +54,19 @@ void add(MediaServerItem mediaSerItem); int addToDatabase(MediaServerItem mediaSerItem); int updateToDatabase(MediaServerItem mediaSerItem); void resetOnlineServerItem(MediaServerItem serverItem); MediaServerItem checkMediaServer(String ip, int port, String secret); MediaServerItem checkMediaServer(String ip, int port, String secret, String type); boolean checkMediaRecordServer(String ip, int port); void delete(String id); void deleteDb(String id); MediaServerItem getDefaultMediaServer(); void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data); /** * è·åè´è½½ä¿¡æ¯ * @return */ MediaServerLoad getLoad(MediaServerItem mediaServerItem); List<MediaServerItem> getAllWithAssistPort(); MediaServerItem getOneFromDatabase(String id); } src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java
@@ -1,24 +1,17 @@ package com.genersoft.iot.vmp.media.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent; import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent; import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; import com.genersoft.iot.vmp.media.zlm.*; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.service.bean.MediaServerLoad; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -33,15 +26,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.util.ObjectUtils; import java.io.File; import java.time.LocalDateTime; import java.util.*; @@ -54,47 +43,14 @@ private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); private final String zlmKeepaliveKeyPrefix = "zlm-keepalive_"; @Autowired private SipConfig sipConfig; @Autowired private SSRCFactory ssrcFactory; @Value("${server.ssl.enabled:false}") private boolean sslEnabled; @Value("${server.port}") private Integer serverPort; @Autowired private UserSetting userSetting; @Autowired private SendRtpPortManager sendRtpPortManager; @Autowired private AssistRESTfulUtils assistRESTfulUtils; @Autowired private MediaServerMapper mediaServerMapper; @Autowired private DataSourceTransactionManager dataSourceTransactionManager; @Autowired private TransactionDefinition transactionDefinition; @Autowired private ZLMServerFactory zlmServerFactory; @Autowired private EventPublisher publisher; @Autowired private DynamicTask dynamicTask; @Autowired private IRedisCatchStorage redisCatchStorage; @@ -107,6 +63,9 @@ @Autowired private Map<String, IMediaNodeServerService> nodeServerServiceMap; @Autowired private ApplicationEventPublisher applicationEventPublisher; /** @@ -259,18 +218,28 @@ mediaServerMapper.update(mediaSerItem); MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); if (mediaServerItemInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { if (mediaServerItemInDataBase == null) { return; } mediaServerItemInDataBase.setStatus(mediaSerItem.isStatus()); if (mediaServerItemInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaServerItemInDataBase.getId())) { ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null); } String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); redisTemplate.opsForValue().set(key, mediaServerItemInDataBase); if (mediaSerItem.isStatus()) { resetOnlineServerItem(mediaSerItem); if (mediaServerItemInDataBase.isStatus()) { resetOnlineServerItem(mediaServerItemInDataBase); }else { // åéäºä»¶ MediaServerChangeEvent event = new MediaServerChangeEvent(this); event.setMediaServerItemList(mediaServerItemInDataBase); applicationEventPublisher.publishEvent(event); } } @Override public List<MediaServerItem> getAll() { public List<MediaServerItem> getAllOnlineList() { List<MediaServerItem> result = new ArrayList<>(); List<Object> mediaServerKeys = RedisUtil.scan(redisTemplate, String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + "_" )); String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); @@ -296,6 +265,21 @@ return sortResult; }); return result; } @Override public List<MediaServerItem> getAll() { List<MediaServerItem> mediaServerList = mediaServerMapper.queryAll(); if (mediaServerList.isEmpty()) { return new ArrayList<>(); } for (MediaServerItem mediaServerItem : mediaServerList) { MediaServerItem mediaServerItemInRedis = getOne(mediaServerItem.getId()); if (mediaServerItemInRedis != null) { mediaServerItem.setStatus(mediaServerItemInRedis.isStatus()); } } return mediaServerList; } @@ -351,12 +335,15 @@ public void add(MediaServerItem mediaServerItem) { mediaServerItem.setCreateTime(DateUtil.getNow()); mediaServerItem.setUpdateTime(DateUtil.getNow()); mediaServerItem.setHookAliveInterval(30f); if (mediaServerItem.getHookAliveInterval() == null || mediaServerItem.getHookAliveInterval() == 0F) { mediaServerItem.setHookAliveInterval(10F); } if (mediaServerItem.getType() == null) { logger.info("[æ·»å åªä½èç¹] 失败, mediaServerItemçç±»åï¼ä¸ºç©º"); return; } if (mediaServerMapper.queryOne(mediaServerItem.getId()) != null) { logger.info("[æ·»å åªä½èç¹] 失败, åªä½æå¡IDå·²åå¨ï¼è¯·ä¿®æ¹åªä½æå¡å¨é ç½®, {}", mediaServerItem.getId()); throw new ControllerException(ErrorCode.ERROR100.getCode(),"ä¿å失败ï¼åªä½æå¡ID [ " + mediaServerItem.getId() + " ] å·²åå¨ï¼è¯·ä¿®æ¹åªä½æå¡å¨é ç½®"); } IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType()); @@ -364,109 +351,15 @@ logger.info("[æ·»å åªä½èç¹] 失败, mediaServerItemçç±»åï¼ {}ï¼æªæ¾å°å¯¹åºçå®ç°ç±»", mediaServerItem.getType()); return; } if (mediaNodeServerService.checkNodeId(mediaServerItem)) { mediaServerMapper.add(mediaServerItem); mediaServerMapper.add(mediaServerItem); if (mediaServerItem.isStatus()) { mediaNodeServerService.online(mediaServerItem); }else { throw new ControllerException(ErrorCode.ERROR100.getCode(),"ä¿å失败ï¼åªä½æå¡ID [ " + mediaServerItem.getId() + " ] å·²åå¨ï¼è¯·ä¿®æ¹åªä½æå¡å¨é ç½®"); // åéäºä»¶ MediaServerChangeEvent event = new MediaServerChangeEvent(this); event.setMediaServerItemList(mediaServerItem); applicationEventPublisher.publishEvent(event); } } @Override public int addToDatabase(MediaServerItem mediaSerItem) { return mediaServerMapper.add(mediaSerItem); } @Override public int updateToDatabase(MediaServerItem mediaSerItem) { int result = 0; if (mediaSerItem.isDefaultServer()) { TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); int delResult = mediaServerMapper.delDefault(); if (delResult == 0) { logger.error("ç§»é¤æ°æ®åºé»è®¤åªä½æå¡èç¹èç¹å¤±è´¥"); //äºå¡åæ» dataSourceTransactionManager.rollback(transactionStatus); return 0; } result = mediaServerMapper.add(mediaSerItem); dataSourceTransactionManager.commit(transactionStatus); //æå¨æäº¤ }else { result = mediaServerMapper.update(mediaSerItem); } return result; } /** * å¤çåªä½æå¡èç¹ä¸çº¿ * @param zlmServerConfig åªä½æå¡èç¹ä¸çº¿æºå¸¦çåæ° */ @Override public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); if (serverItem == null) { logger.warn("[æªæ³¨åçåªä½æå¡èç¹] ææ¥æ¥å ¥ï¼{}æ¥èª{}ï¼{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); logger.warn("è¯·æ£æ¥åªä½æå¡èç¹çIDé ç½®æ¯å¦ä¸WVPç<media.id>ä¸è´"); return; }else { logger.info("[åªä½æå¡èç¹] æ£å¨è¿æ¥ : {} -> {}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); } serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); if (serverItem.getHttpPort() == 0) { serverItem.setHttpPort(zlmServerConfig.getHttpPort()); } if (serverItem.getHttpSSlPort() == 0) { serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); } if (serverItem.getRtmpPort() == 0) { serverItem.setRtmpPort(zlmServerConfig.getRtmpPort()); } if (serverItem.getRtmpSSlPort() == 0) { serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); } if (serverItem.getRtspPort() == 0) { serverItem.setRtspPort(zlmServerConfig.getRtspPort()); } if (serverItem.getRtspSSLPort() == 0) { serverItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); } if (serverItem.getRtpProxyPort() == 0) { serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); } serverItem.setStatus(true); if (ObjectUtils.isEmpty(serverItem.getId())) { logger.warn("[æªæ³¨åçåªä½æå¡èç¹] serverItem缺å°IDï¼ æ æ³æ¥å ¥ï¼{}ï¼{}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); return; } mediaServerMapper.update(serverItem); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); if (!ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); } redisTemplate.opsForValue().set(key, serverItem); resetOnlineServerItem(serverItem); if (serverItem.isAutoConfig()) { setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); } final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); dynamicTask.stop(zlmKeepaliveKey); dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (serverItem.getHookAliveInterval().intValue() + 5) * 1000); publisher.mediaServerOnlineEventPublish(serverItem.getId()); logger.info("[åªä½æå¡èç¹] è¿æ¥æå {} - {}:{} ", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); } @Override public void zlmServerOffline(String mediaServerId) { delete(mediaServerId); final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerId; dynamicTask.stop(zlmKeepaliveKey); } @Override @@ -549,111 +442,23 @@ return mediaServerItem; } /** * 对åªä½æå¡èç¹æå¡å¨è¿è¡åºç¡é ç½® * @param mediaServerItem æå¡ID * @param restart æ¯å¦éå¯åªä½æå¡èç¹ */ @Override public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { logger.info("[åªä½æå¡èç¹] æ£å¨è®¾ç½® ï¼{} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); String protocol = sslEnabled ? "https" : "http"; String hookPrefix = 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 -frames:v 1 %s"); } param.put("hook.enable","1"); param.put("hook.on_flow_report",""); param.put("hook.on_play",String.format("%s/on_play", hookPrefix)); param.put("hook.on_http_access",""); param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix)); 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", hookPrefix)); param.put("hook.on_shell_login",""); param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix)); param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix)); param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix)); param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix)); param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix)); param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix)); param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix)); param.put("hook.timeoutSec","20"); // æ¨æµæå¼åå¯ä»¥å¨è¶ æ¶æ¶é´å éæ°è¿æ¥ä¸ç»§ç»æ¨æµï¼è¿æ ·ææ¾å¨ä¼æ¥çææ¾ã // ç½®0å ³éæ¤ç¹æ§(æ¨æµæå¼ä¼å¯¼è´ç«å³æå¼ææ¾å¨) // æ¤åæ°ä¸åºå¤§äºææ¾å¨è¶ æ¶æ¶é´ // ä¼åæ¤æ¶æ¯ä»¥æ´å¿«çæ¶å°æµæ³¨éäºä»¶ param.put("protocol.continue_push_ms", "3000" ); // æå¤çå¾ æªåå§åçTrackæ¶é´ï¼å使¯«ç§ï¼è¶ æ¶ä¹åä¼å¿½ç¥æªåå§åçTrack, 设置æ¤é项ä¼åé£äºé³é¢é误çä¸è§èæµï¼ // çzlmæ¯æç»æ¯ä¸ªrtpServerè®¾ç½®å ³éé³é¢çæ¶åå¯ä»¥ä¸è®¾ç½®æ¤é项 if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); } if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) { File recordPathFile = new File(mediaServerItem.getRecordPath()); param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath()); param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath()); param.put("record.appName", recordPathFile.getName()); } JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); if (responseJSON != null && responseJSON.getInteger("code") == 0) { if (restart) { logger.info("[åªä½æå¡èç¹] 设置æå,å¼å§éå¯ä»¥ä¿è¯é ç½®çæ {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); zlmresTfulUtils.restartServer(mediaServerItem); }else { logger.info("[åªä½æå¡èç¹] 设置æå {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } }else { logger.info("[åªä½æå¡èç¹] 设置åªä½æå¡èç¹å¤±è´¥ {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } } @Override public MediaServerItem checkMediaServer(String ip, int port, String secret) { public MediaServerItem checkMediaServer(String ip, int port, String secret, String type) { if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "æ¤è¿æ¥å·²åå¨"); } MediaServerItem mediaServerItem = new MediaServerItem(); mediaServerItem.setIp(ip); mediaServerItem.setHttpPort(port); mediaServerItem.setSecret(secret); JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); if (responseJSON == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "è¿æ¥å¤±è´¥"); IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(type); if (mediaNodeServerService == null) { logger.info("[closeRTPServer] 失败, mediaServerItemçç±»åï¼ {}ï¼æªæ¾å°å¯¹åºçå®ç°ç±»", type); return null; } JSONArray data = responseJSON.getJSONArray("data"); ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); if (zlmServerConfig == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "读åé 置失败"); MediaServerItem mediaServerItem = mediaNodeServerService.checkMediaServer(ip, port, secret); if (mediaServerItem != null) { if (mediaServerMapper.queryOne(mediaServerItem.getId()) != null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "åªä½æå¡ID [" + mediaServerItem.getId() + " ] å·²åå¨ï¼è¯·ä¿®æ¹åªä½æå¡å¨é ç½®"); } } if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "åªä½æå¡ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] å·²åå¨ï¼è¯·ä¿®æ¹åªä½æå¡å¨é ç½®"); } mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort()); mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort()); mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort()); mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); mediaServerItem.setStreamIp(ip); mediaServerItem.setHookIp(sipConfig.getIp().split(",")[0]); mediaServerItem.setSdpIp(ip); return mediaServerItem; } @@ -678,46 +483,24 @@ @Override public void delete(String id) { mediaServerMapper.delOne(id); redisTemplate.opsForZSet().remove(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), id); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + id; redisTemplate.delete(key); } @Override public void deleteDb(String id){ //忥å 餿°æ®åºä¸çæ°æ® mediaServerMapper.delOne(id); // åéèç¹ç§»é¤éç¥ MediaServerDeleteEvent event = new MediaServerDeleteEvent(this); event.setMediaServerId(id); applicationEventPublisher.publishEvent(event); } @Override public void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data) { MediaServerItem mediaServerItem = getOne(mediaServerId); if (mediaServerItem == null) { // ç¼åä¸åå¨ï¼ä»æ°æ®åºæ¥è¯¢ï¼å¦ææ°æ®åºä¸åå¨åæ¯é误ç mediaServerItem = getOneFromDatabase(mediaServerId); if (mediaServerItem == null) { logger.warn("[æ´æ°åªä½æå¡èç¹ ä¿æ´»ä¿¡æ¯] æµåªä½{}å°æªå å ¥ä½¿ç¨,è¯·æ£æ¥èç¹ä¸æ¯å¦å«ææ¤æµåªä½ ", mediaServerId); return; } // åªä½æå¡èç¹è¿æ¥éè¯ logger.warn("[æ´æ°åªä½æå¡èç¹ ä¿æ´»ä¿¡æ¯]å°è¯é¾æ¥zml id {}", mediaServerId); ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); redisTemplate.opsForValue().set(key, mediaServerItem); resetOnlineServerItem(mediaServerItem); clearRTPServer(mediaServerItem); } final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); dynamicTask.stop(zlmKeepaliveKey); dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), (mediaServerItem.getHookAliveInterval().intValue() + 5) * 1000); } private MediaServerItem getOneFromDatabase(String mediaServerId) { public MediaServerItem getOneFromDatabase(String mediaServerId) { return mediaServerMapper.queryOne(mediaServerId); } @Override public void syncCatchFromDatabase() { List<MediaServerItem> allInCatch = getAll(); List<MediaServerItem> allInCatch = getAllOnlineList(); List<MediaServerItem> allInDatabase = mediaServerMapper.queryAll(); Map<String, MediaServerItem> mediaServerItemMap = new HashMap<>(); @@ -748,4 +531,6 @@ public List<MediaServerItem> getAllWithAssistPort() { return mediaServerMapper.queryAllWithAssistPort(); } } src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java
@@ -83,6 +83,7 @@ } private synchronized int getSendPort(int startPort, int endPort, String sendIndexKey, Map<Integer, SendRtpItem> sendRtpItemMap){ // TODO è¿éæ¹ä¸ºåªåå¶æ°ç«¯å£ RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory()); if (redisAtomicInteger.get() < startPort) { redisAtomicInteger.set(startPort); src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -10,8 +10,8 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -21,6 +21,8 @@ import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.media.zlm.dto.hook.*; import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerKeepaliveEvent; import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -35,6 +37,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ObjectUtils; @@ -69,9 +72,6 @@ @Autowired private AudioBroadcastManager audioBroadcastManager; @Autowired private ZLMServerFactory zlmServerFactory; @Autowired private IPlayService playService; @@ -122,9 +122,6 @@ private VideoStreamSessionManager sessionManager; @Autowired private AssistRESTfulUtils assistRESTfulUtils; @Autowired private SSRCFactory ssrcFactory; @Qualifier("taskExecutor") @@ -134,6 +131,9 @@ @Autowired private RedisTemplate<Object, Object> redisTemplate; @Autowired private ApplicationEventPublisher applicationEventPublisher; /** * æå¡å¨å®æ¶ä¸æ¥æ¶é´ï¼ä¸æ¥é´éå¯é ç½®ï¼é»è®¤10s䏿¥ä¸æ¬¡ */ @@ -141,8 +141,6 @@ @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { taskExecutor.execute(() -> { List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); if (subscribes != null && subscribes.size() > 0) { @@ -151,8 +149,16 @@ } } }); mediaServerService.updateMediaServerKeepalive(param.getMediaServerId(), param.getData()); try { HookZlmServerKeepaliveEvent event = new HookZlmServerKeepaliveEvent(this); MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); if (mediaServerItem != null) { event.setMediaServerItem(mediaServerItem); applicationEventPublisher.publishEvent(event); } }catch (Exception e) { logger.info("[ZLM-HOOK-å¿è·³] åééç¥å¤±è´¥ ", e); } return HookResult.SUCCESS(); } @@ -160,7 +166,6 @@ * ææ¾å¨é´æäºä»¶ï¼rtsp/rtmp/http-flv/ws-flv/hlsçææ¾é½å°è§¦åæ¤é´æäºä»¶ã */ @ResponseBody @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") public HookResult onPlay(@RequestBody OnPlayHookParam param) { if (logger.isDebugEnabled()) { @@ -199,6 +204,7 @@ JSONObject json = (JSONObject) JSON.toJSON(param); logger.info("[ZLM HOOK]æ¨æµé´æï¼{}->{}", param.getMediaServerId(), param); // TODO å å¿«å¤çé度 String mediaServerId = json.getString("mediaServerId"); MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); @@ -801,8 +807,17 @@ subscribe.response(null, zlmServerConfig); } } mediaServerService.zlmServerOnline(zlmServerConfig); }); try { HookZlmServerStartEvent event = new HookZlmServerStartEvent(this); MediaServerItem mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId()); if (mediaServerItem != null) { event.setMediaServerItem(mediaServerItem); applicationEventPublisher.publishEvent(event); } }catch (Exception e) { logger.info("[ZLM-HOOK-ZLMå¯å¨] åééç¥å¤±è´¥ ", e); } return HookResult.SUCCESS(); } src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java
@@ -4,10 +4,13 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service("zlm") @@ -19,9 +22,12 @@ @Autowired private ZLMServerFactory zlmServerFactory; @Value("${sip.ip}") private String sipIp; @Override public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { return zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrc, port, onlyAuto, reUsePort, tcpMode);; return zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrc, port, onlyAuto, reUsePort, tcpMode); } @Override @@ -68,4 +74,36 @@ public void online(MediaServerItem mediaServerItem) { } @Override public MediaServerItem checkMediaServer(String ip, int port, String secret) { MediaServerItem mediaServerItem = new MediaServerItem(); mediaServerItem.setIp(ip); mediaServerItem.setHttpPort(port); mediaServerItem.setSecret(secret); JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); if (responseJSON == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "è¿æ¥å¤±è´¥"); } JSONArray data = responseJSON.getJSONArray("data"); if (data == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "读åé 置失败"); } ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); if (zlmServerConfig == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "读åé 置失败"); } mediaServerItem.setId(zlmServerConfig.getGeneralMediaServerId()); mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort()); mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort()); mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort()); mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); mediaServerItem.setStreamIp(ip); mediaServerItem.setHookIp(sipIp.split(",")[0]); mediaServerItem.setSdpIp(ip); mediaServerItem.setType("zlm"); return mediaServerItem; } } src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java
@@ -4,7 +4,9 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.media.event.MediaServerChangeEvent; import com.genersoft.iot.vmp.media.event.MediaServerDeleteEvent; import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; @@ -13,12 +15,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; /** @@ -41,6 +48,15 @@ @Autowired private DynamicTask dynamicTask; @Value("${server.ssl.enabled:false}") private boolean sslEnabled; @Value("${server.port}") private Integer serverPort; @Autowired private UserSetting userSetting; private final String type = "zlm"; @@ -74,15 +90,13 @@ return; } logger.info("[ZLM-HOOKäºä»¶-æå¡å¯å¨] IDï¼" + event.getMediaServerItem().getId()); online(serverItem); online(serverItem, null); } @Async("taskExecutor") @EventListener public void onApplicationEvent(HookZlmServerKeepaliveEvent event) { if (event.getMediaServerItem() == null || !type.equals(event.getMediaServerItem().getType()) || event.getMediaServerItem().isStatus()) { if (event.getMediaServerItem() == null) { return; } MediaServerItem serverItem = mediaServerService.getOne(event.getMediaServerItem().getId()); @@ -90,7 +104,19 @@ return; } logger.info("[ZLM-HOOKäºä»¶-å¿è·³] IDï¼" + event.getMediaServerItem().getId()); online(serverItem); online(serverItem, null); } @Async("taskExecutor") @EventListener public void onApplicationEvent(MediaServerDeleteEvent event) { if (event.getMediaServerId() == null) { return; } logger.info("[ZLM-èç¹è¢«ç§»é¤] IDï¼" + event.getMediaServerId()); offlineZlmPrimaryMap.remove(event.getMediaServerId()); offlineZlmsecondaryMap.remove(event.getMediaServerId()); offlineZlmTimeMap.remove(event.getMediaServerId()); } @Scheduled(fixedDelay = 10*1000) //æ¯é10ç§æ£æ¥ä¸æ¬¡ @@ -101,7 +127,7 @@ } if (!offlineZlmPrimaryMap.isEmpty()) { for (MediaServerItem mediaServerItem : offlineZlmPrimaryMap.values()) { if (offlineZlmTimeMap.get(mediaServerItem.getId()) > 30*60*1000) { if (offlineZlmTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) { offlineZlmsecondaryMap.put(mediaServerItem.getId(), mediaServerItem); offlineZlmPrimaryMap.remove(mediaServerItem.getId()); continue; @@ -119,13 +145,13 @@ }else { zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); initPort(mediaServerItem, zlmServerConfig); online(mediaServerItem); online(mediaServerItem, zlmServerConfig); } } } if (!offlineZlmsecondaryMap.isEmpty()) { for (MediaServerItem mediaServerItem : offlineZlmsecondaryMap.values()) { if (offlineZlmTimeMap.get(mediaServerItem.getId()) < 30*60*1000) { if (offlineZlmTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) { continue; } logger.info("[ZLM-å°è¯è¿æ¥] IDï¼{}, å°åï¼ {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); @@ -143,20 +169,34 @@ }else { zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); initPort(mediaServerItem, zlmServerConfig); online(mediaServerItem); online(mediaServerItem, zlmServerConfig); } } } } private void online(MediaServerItem mediaServerItem) { private void online(MediaServerItem mediaServerItem, ZLMServerConfig config) { offlineZlmPrimaryMap.remove(mediaServerItem.getId()); offlineZlmsecondaryMap.remove(mediaServerItem.getId()); offlineZlmTimeMap.remove(mediaServerItem.getId()); if (!mediaServerItem.isStatus()) { logger.info("[ZLM-è¿æ¥æå] IDï¼{}, å°åï¼ {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); mediaServerItem.setStatus(true); mediaServerItem.setHookAliveInterval(10F); mediaServerService.update(mediaServerItem); if(mediaServerItem.isAutoConfig()) { if (config == null) { JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); JSONArray data = responseJSON.getJSONArray("data"); if (data != null && !data.isEmpty()) { config = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); } } if (config != null) { setZLMConfig(mediaServerItem, "0".equals(config.getHookEnable()) || !Objects.equals(mediaServerItem.getHookAliveInterval(), config.getHookAliveInterval())); } } } // 设置两次å¿è·³æªæ¶å°å认为zlm离线 String key = "zlm-keepalive-" + mediaServerItem.getId(); @@ -165,6 +205,8 @@ mediaServerItem.setStatus(false); offlineZlmPrimaryMap.put(mediaServerItem.getId(), mediaServerItem); offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis()); // TODO åé离线éç¥ mediaServerService.update(mediaServerItem); }, (int)(mediaServerItem.getHookAliveInterval() * 2 * 1000)); } private void initPort(MediaServerItem mediaServerItem, ZLMServerConfig zlmServerConfig) { @@ -186,7 +228,72 @@ if (mediaServerItem.getRtpProxyPort() == 0) { mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); } mediaServerItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); mediaServerItem.setHookAliveInterval(10F); } public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { logger.info("[åªä½æå¡èç¹] æ£å¨è®¾ç½® ï¼{} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); String protocol = sslEnabled ? "https" : "http"; String hookPrefix = 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 -frames:v 1 %s"); } param.put("hook.enable","1"); param.put("hook.on_flow_report",""); param.put("hook.on_play",String.format("%s/on_play", hookPrefix)); param.put("hook.on_http_access",""); param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix)); 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", hookPrefix)); param.put("hook.on_shell_login",""); param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix)); param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix)); param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix)); param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix)); param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix)); param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix)); param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix)); param.put("hook.timeoutSec","30"); param.put("hook.alive_interval", mediaServerItem.getHookAliveInterval()); // æ¨æµæå¼åå¯ä»¥å¨è¶ æ¶æ¶é´å éæ°è¿æ¥ä¸ç»§ç»æ¨æµï¼è¿æ ·ææ¾å¨ä¼æ¥çææ¾ã // ç½®0å ³éæ¤ç¹æ§(æ¨æµæå¼ä¼å¯¼è´ç«å³æå¼ææ¾å¨) // æ¤åæ°ä¸åºå¤§äºææ¾å¨è¶ æ¶æ¶é´ // ä¼åæ¤æ¶æ¯ä»¥æ´å¿«çæ¶å°æµæ³¨éäºä»¶ param.put("protocol.continue_push_ms", "3000" ); // æå¤çå¾ æªåå§åçTrackæ¶é´ï¼å使¯«ç§ï¼è¶ æ¶ä¹åä¼å¿½ç¥æªåå§åçTrack, 设置æ¤é项ä¼åé£äºé³é¢é误çä¸è§èæµï¼ // çzlmæ¯æç»æ¯ä¸ªrtpServerè®¾ç½®å ³éé³é¢çæ¶åå¯ä»¥ä¸è®¾ç½®æ¤é项 if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); } if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) { File recordPathFile = new File(mediaServerItem.getRecordPath()); param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath()); param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath()); param.put("record.appName", recordPathFile.getName()); } JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); if (responseJSON != null && responseJSON.getInteger("code") == 0) { if (restart) { logger.info("[åªä½æå¡èç¹] 设置æå,å¼å§éå¯ä»¥ä¿è¯é ç½®çæ {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); zlmresTfulUtils.restartServer(mediaServerItem); }else { logger.info("[åªä½æå¡èç¹] 设置æå {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } }else { logger.info("[åªä½æå¡èç¹] 设置åªä½æå¡èç¹å¤±è´¥ {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } } } src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -34,6 +34,7 @@ "record_day,"+ "record_path,"+ "default_server,"+ "type,"+ "create_time,"+ "update_time,"+ "hook_alive_interval"+ @@ -60,6 +61,7 @@ "#{recordDay}, " + "#{recordPath}, " + "#{defaultServer}, " + "#{type}, " + "#{createTime}, " + "#{updateTime}, " + "#{hookAliveInterval})") @@ -88,6 +90,7 @@ "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" + "<if test=\"type != null\">, type=#{type}</if>" + "WHERE id=#{id}"+ " </script>"}) int update(MediaServerItem mediaServerItem); @@ -113,6 +116,7 @@ "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" + "<if test=\"type != null\">, type=#{type}</if>" + "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + "WHERE ip=#{ip} and http_port=#{httpPort}"+ " </script>"}) src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
@@ -76,7 +76,7 @@ } mediaServerItems.add(mediaServerItem); } else { mediaServerItems = mediaServerService.getAll(); mediaServerItems = mediaServerService.getAllOnlineList(); } if (mediaServerItems.isEmpty()) { return new ArrayList<>(); @@ -119,7 +119,7 @@ } mediaServerItems.add(mediaServerItem); } else { mediaServerItems = mediaServerService.getAll(); mediaServerItems = mediaServerService.getAllOnlineList(); } if (mediaServerItems.isEmpty()) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "å½åæ æµåªä½"); src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -108,8 +108,8 @@ @Parameter(name = "secret", description = "æµåªä½æå¡secret", required = true) @GetMapping(value = "/media_server/check") @ResponseBody public MediaServerItem checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret) { return mediaServerService.checkMediaServer(ip, port, secret); public MediaServerItem checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret, @RequestParam String type) { return mediaServerService.checkMediaServer(ip, port, secret, type); } @Operation(summary = "æµè¯æµåªä½å½å管çæå¡", security = @SecurityRequirement(name = JwtUtils.HEADER)) @@ -129,7 +129,7 @@ @PostMapping(value = "/media_server/save") @ResponseBody public void saveMediaServer(@RequestBody MediaServerItem mediaServerItem) { MediaServerItem mediaServerItemInDatabase = mediaServerService.getOne(mediaServerItem.getId()); MediaServerItem mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServerItem.getId()); if (mediaServerItemInDatabase != null) { mediaServerService.update(mediaServerItem); @@ -143,11 +143,7 @@ @DeleteMapping(value = "/media_server/delete") @ResponseBody public void deleteMediaServer(@RequestParam String id) { if (mediaServerService.getOne(id) == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "æªæ¾å°æ¤èç¹"); } mediaServerService.delete(id); mediaServerService.deleteDb(id); } web_src/src/components/dialog/MediaServerEdit.vue
@@ -20,6 +20,12 @@ <el-form-item label="SECRET" prop="secret"> <el-input v-model="mediaServerForm.secret" placeholder="åªä½æå¡SECRET" clearable :disabled="mediaServerForm.defaultServer"></el-input> </el-form-item> <el-form-item label="ç±»å" prop="type"> <el-select v-model="mediaServerForm.type" style="float: left; width: 100%" > <el-option key="zlm" label="ZLMediaKit" value="zlm"></el-option> <el-option key="abl" label="ABLMediaServer" value="abl"></el-option> </el-select> </el-form-item> <el-form-item> <div style="float: right;"> <el-button type="primary" v-if="currentStep === 1 && serverCheck === 1" @click="next" >ä¸ä¸æ¥</el-button> @@ -170,7 +176,7 @@ hookIp: "", sdpIp: "", streamIp: "", secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", secret: "", httpPort: "", httpSSlPort: "", recordAssistPort: "", @@ -182,6 +188,7 @@ rtpProxyPort: "", rtspPort: "", rtspSSLPort: "", type: "zlm", }, rtpPortRange1:30000, rtpPortRange2:30500, @@ -330,7 +337,7 @@ hookIp: "", sdpIp: "", streamIp: "", secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", secret: "", httpPort: "", httpSSlPort: "", recordAssistPort: "", web_src/src/components/service/MediaServer.js
@@ -45,7 +45,8 @@ params: { ip: param.ip, port: param.httpPort, secret: param.secret secret: param.secret, type: param.type } }).then(function (res) { if (typeof (callback) == "function") callback(res.data) Êý¾Ý¿â/abl/¸üÐÂ-mysql-2.7.0.sql
@@ -1,2 +1,2 @@ alter table wvp_media_server add type character varying(50) default 'zlm',; add type character varying(50) default 'zlm';