New file |
| | |
| | | package com.genersoft.iot.vmp.common; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| | | import org.jetbrains.annotations.NotNull; |
| | | |
| | | import java.util.List; |
| | | |
| | | |
| | | public class RealVideo implements Comparable<RealVideo>{ |
| | | |
| | | /** |
| | | * 应用名 |
| | | */ |
| | | private String app; |
| | | |
| | | /** |
| | | * 流id |
| | | */ |
| | | private String stream; |
| | | |
| | | /** |
| | | * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv |
| | | */ |
| | | private String totalReaderCount; |
| | | |
| | | /** |
| | | * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv |
| | | */ |
| | | private List<MediaSchema> schemas; |
| | | |
| | | /** |
| | | * 产生源类型, |
| | | * 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 MediaItem.OriginSock originSock; |
| | | |
| | | /** |
| | | * 产生源类型的字符串描述 |
| | | */ |
| | | private String originTypeStr; |
| | | |
| | | /** |
| | | * 产生源的url |
| | | */ |
| | | private String originUrl; |
| | | |
| | | /** |
| | | * GMT unix系统时间戳,单位秒 |
| | | */ |
| | | private Long createStamp; |
| | | |
| | | /** |
| | | * 存活时间,单位秒 |
| | | */ |
| | | private Long aliveSecond; |
| | | |
| | | /** |
| | | * 音视频轨道 |
| | | */ |
| | | private List<MediaItem.MediaTrack> tracks; |
| | | |
| | | /** |
| | | * 音视频轨道 |
| | | */ |
| | | private String vhost; |
| | | |
| | | public String getVhost() { |
| | | return vhost; |
| | | } |
| | | |
| | | public void setVhost(String vhost) { |
| | | this.vhost = vhost; |
| | | } |
| | | |
| | | @Override |
| | | public int compareTo(@NotNull RealVideo realVideo) { |
| | | return new Long(this.createStamp - realVideo.getCreateStamp().intValue()).intValue(); |
| | | } |
| | | |
| | | public static class MediaSchema { |
| | | private String schema; |
| | | private Long bytesSpeed; |
| | | |
| | | public String getSchema() { |
| | | return schema; |
| | | } |
| | | |
| | | public void setSchema(String schema) { |
| | | this.schema = schema; |
| | | } |
| | | |
| | | public Long getBytesSpeed() { |
| | | return bytesSpeed; |
| | | } |
| | | |
| | | public void setBytesSpeed(Long bytesSpeed) { |
| | | this.bytesSpeed = bytesSpeed; |
| | | } |
| | | } |
| | | |
| | | |
| | | public String getApp() { |
| | | return app; |
| | | } |
| | | |
| | | public void setApp(String app) { |
| | | this.app = app; |
| | | } |
| | | |
| | | public String getStream() { |
| | | return stream; |
| | | } |
| | | |
| | | public void setStream(String stream) { |
| | | this.stream = stream; |
| | | } |
| | | |
| | | public String getTotalReaderCount() { |
| | | return totalReaderCount; |
| | | } |
| | | |
| | | public void setTotalReaderCount(String totalReaderCount) { |
| | | this.totalReaderCount = totalReaderCount; |
| | | } |
| | | |
| | | public List<MediaSchema> getSchemas() { |
| | | return schemas; |
| | | } |
| | | |
| | | public void setSchemas(List<MediaSchema> schemas) { |
| | | this.schemas = schemas; |
| | | } |
| | | |
| | | public int getOriginType() { |
| | | return originType; |
| | | } |
| | | |
| | | public void setOriginType(int originType) { |
| | | this.originType = originType; |
| | | } |
| | | |
| | | public MediaItem.OriginSock getOriginSock() { |
| | | return originSock; |
| | | } |
| | | |
| | | public void setOriginSock(MediaItem.OriginSock originSock) { |
| | | this.originSock = originSock; |
| | | } |
| | | |
| | | |
| | | public String getOriginTypeStr() { |
| | | return originTypeStr; |
| | | } |
| | | |
| | | public void setOriginTypeStr(String originTypeStr) { |
| | | this.originTypeStr = originTypeStr; |
| | | } |
| | | |
| | | public String getOriginUrl() { |
| | | return originUrl; |
| | | } |
| | | |
| | | public void setOriginUrl(String originUrl) { |
| | | this.originUrl = originUrl; |
| | | } |
| | | |
| | | public Long getCreateStamp() { |
| | | return createStamp; |
| | | } |
| | | |
| | | public void setCreateStamp(Long createStamp) { |
| | | this.createStamp = createStamp; |
| | | } |
| | | |
| | | public Long getAliveSecond() { |
| | | return aliveSecond; |
| | | } |
| | | |
| | | public void setAliveSecond(Long aliveSecond) { |
| | | this.aliveSecond = aliveSecond; |
| | | } |
| | | |
| | | public List<MediaItem.MediaTrack> getTracks() { |
| | | return tracks; |
| | | } |
| | | |
| | | public void setTracks(List<MediaItem.MediaTrack> tracks) { |
| | | this.tracks = tracks; |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | |
| | |
|
| | | public static final String MEDIA_SERVER_PREFIX = "VMP_media_server";
|
| | |
|
| | | public static final String MEDIA_STREAM_PREFIX = "VMP_media_stream";
|
| | |
|
| | | public static final String DEVICE_PREFIX = "VMP_device_";
|
| | |
|
| | | public static final String CACHEKEY_PREFIX = "VMP_channel_";
|
| | |
| | | @Autowired
|
| | | private IRedisCatchStorage redisCatchStorage;
|
| | |
|
| | | // @Autowired
|
| | | // private ZLMRESTfulUtils zlmresTfulUtils;
|
| | | @Autowired
|
| | | private ZLMMediaListManager zlmMediaListManager;
|
| | |
|
| | | @Autowired
|
| | | private ZLMHttpHookSubscribe subscribe;
|
| | |
| | | // 流消失移除redis play
|
| | | String app = json.getString("app");
|
| | | String streamId = json.getString("stream");
|
| | | String schema = json.getString("schema");
|
| | | boolean regist = json.getBoolean("regist");
|
| | | StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
| | | if ("rtp".equals(app) && !regist ) {
|
| | |
| | | streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
| | | redisCatchStorage.stopPlayback(streamInfo);
|
| | | }
|
| | | }else {
|
| | | if (!"rtp".equals(app) && "rtsp".equals(schema)){
|
| | | zlmMediaListManager.updateMediaList();
|
| | | }
|
| | | }
|
| | | JSONObject ret = new JSONObject();
|
| | | ret.put("code", 0);
|
New file |
| | |
| | | package com.genersoft.iot.vmp.media.zlm; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.alibaba.fastjson.TypeReference; |
| | | import com.genersoft.iot.vmp.common.RealVideo; |
| | | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| | | import com.genersoft.iot.vmp.gb28181.session.SsrcUtil; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl; |
| | | 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.stereotype.Component; |
| | | |
| | | import java.util.*; |
| | | |
| | | @Component |
| | | public class ZLMMediaListManager { |
| | | |
| | | private Logger logger = LoggerFactory.getLogger("ZLMMediaListManager"); |
| | | |
| | | @Autowired |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | |
| | | public void updateMediaList() { |
| | | JSONObject mediaList = zlmresTfulUtils.getMediaList(); |
| | | String dataStr = mediaList.getString("data"); |
| | | |
| | | Integer code = mediaList.getInteger("code"); |
| | | Map<String, RealVideo> result = new HashMap<>(); |
| | | if (code == 0 ) { |
| | | if (dataStr != null) { |
| | | List<MediaItem> mediaItems = JSON.parseObject(dataStr, new TypeReference<List<MediaItem>>() {}); |
| | | for (MediaItem item : mediaItems) { |
| | | if ("rtp".equals(item.getApp())) { |
| | | continue; |
| | | } |
| | | String key = item.getApp() + "_" + item.getStream(); |
| | | RealVideo realVideo = result.get(key); |
| | | if (realVideo == null) { |
| | | realVideo = new RealVideo(); |
| | | realVideo.setApp(item.getApp()); |
| | | realVideo.setStream(item.getStream()); |
| | | realVideo.setAliveSecond(item.getAliveSecond()); |
| | | realVideo.setCreateStamp(item.getCreateStamp()); |
| | | realVideo.setOriginSock(item.getOriginSock()); |
| | | realVideo.setTotalReaderCount(item.getTotalReaderCount()); |
| | | realVideo.setOriginType(item.getOriginType()); |
| | | realVideo.setOriginTypeStr(item.getOriginTypeStr()); |
| | | realVideo.setOriginUrl(item.getOriginUrl()); |
| | | realVideo.setCreateStamp(item.getCreateStamp()); |
| | | realVideo.setAliveSecond(item.getAliveSecond()); |
| | | |
| | | ArrayList<RealVideo.MediaSchema> mediaSchemas = new ArrayList<>(); |
| | | realVideo.setSchemas(mediaSchemas); |
| | | realVideo.setTracks(item.getTracks()); |
| | | realVideo.setVhost(item.getVhost()); |
| | | result.put(key, realVideo); |
| | | } |
| | | |
| | | RealVideo.MediaSchema mediaSchema = new RealVideo.MediaSchema(); |
| | | mediaSchema.setSchema(item.getSchema()); |
| | | mediaSchema.setBytesSpeed(item.getBytesSpeed()); |
| | | realVideo.getSchemas().add(mediaSchema); |
| | | } |
| | | |
| | | } |
| | | }else { |
| | | logger.warn("更新视频流失败,错误code: " + code); |
| | | } |
| | | |
| | | List<RealVideo> realVideos = new ArrayList<>(result.values()); |
| | | Collections.sort(realVideos); |
| | | redisCatchStorage.updateMediaList(realVideos); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | return sendPost("getMediaList",param); |
| | | } |
| | | |
| | | public JSONObject getMediaList(){ |
| | | return sendPost("getMediaList",null); |
| | | } |
| | | |
| | | public JSONObject getMediaInfo(String app, String schema, String stream){ |
| | | Map<String, Object> param = new HashMap<>(); |
| | | param.put("app",app); |
| | |
| | | @Autowired |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | @Autowired |
| | | private ZLMMediaListManager zlmMediaListManager; |
| | | |
| | | @Override |
| | | public void run(String... strings) throws Exception { |
| | | // 获取zlm信息 |
| | |
| | | if (autoConfig) saveZLMConfig(); |
| | | mediaServerConfig = getMediaServerConfig(); |
| | | redisCatchStorage.updateMediaInfo(mediaServerConfig); |
| | | // 更新流列表 |
| | | zlmMediaListManager.updateMediaList(); |
| | | } |
| | | } |
| | | |
| | |
| | | logger.info("设置zlm失败: " + responseJSON.getString("msg")); |
| | | } |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.media.zlm.dto; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | |
| | | import java.util.List; |
| | | |
| | | public class MediaItem { |
| | | |
| | | /** |
| | | * 应用名 |
| | | */ |
| | | private String app; |
| | | |
| | | /** |
| | | * 流id |
| | | */ |
| | | private String stream; |
| | | |
| | | /** |
| | | * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv |
| | | */ |
| | | private String 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; |
| | | |
| | | /** |
| | | * GMT unix系统时间戳,单位秒 |
| | | */ |
| | | private Long createStamp; |
| | | |
| | | /** |
| | | * 存活时间,单位秒 |
| | | */ |
| | | private Long aliveSecond; |
| | | |
| | | /** |
| | | * 数据产生速度,单位byte/s |
| | | */ |
| | | private Long bytesSpeed; |
| | | |
| | | /** |
| | | * 音视频轨道 |
| | | */ |
| | | private List<MediaTrack> tracks; |
| | | |
| | | /** |
| | | * 音视频轨道 |
| | | */ |
| | | private String vhost; |
| | | |
| | | |
| | | public static class MediaTrack { |
| | | /** |
| | | * 音频通道数 |
| | | */ |
| | | private int channels; |
| | | |
| | | /** |
| | | * H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4 |
| | | */ |
| | | private int codecId; |
| | | |
| | | /** |
| | | * 编码类型名称 CodecAAC CodecH264 |
| | | */ |
| | | private String codecIdName; |
| | | |
| | | /** |
| | | * Video = 0, Audio = 1 |
| | | */ |
| | | private int codecType; |
| | | |
| | | /** |
| | | * 轨道是否准备就绪 |
| | | */ |
| | | private boolean ready; |
| | | |
| | | /** |
| | | * 音频采样位数 |
| | | */ |
| | | private int sampleBit; |
| | | |
| | | /** |
| | | * 音频采样率 |
| | | */ |
| | | private int sampleRate; |
| | | |
| | | /** |
| | | * 视频fps |
| | | */ |
| | | private int fps; |
| | | |
| | | /** |
| | | * 视频高 |
| | | */ |
| | | private int height; |
| | | |
| | | /** |
| | | * 视频宽 |
| | | */ |
| | | private int width; |
| | | |
| | | public int getChannels() { |
| | | return channels; |
| | | } |
| | | |
| | | public void setChannels(int channels) { |
| | | this.channels = channels; |
| | | } |
| | | |
| | | public int getCodecId() { |
| | | return codecId; |
| | | } |
| | | |
| | | public void setCodecId(int codecId) { |
| | | this.codecId = codecId; |
| | | } |
| | | |
| | | public String getCodecIdName() { |
| | | return codecIdName; |
| | | } |
| | | |
| | | public void setCodecIdName(String codecIdName) { |
| | | this.codecIdName = codecIdName; |
| | | } |
| | | |
| | | public int getCodecType() { |
| | | return codecType; |
| | | } |
| | | |
| | | public void setCodecType(int codecType) { |
| | | this.codecType = codecType; |
| | | } |
| | | |
| | | public boolean isReady() { |
| | | return ready; |
| | | } |
| | | |
| | | public void setReady(boolean ready) { |
| | | this.ready = ready; |
| | | } |
| | | |
| | | public int getSampleBit() { |
| | | return sampleBit; |
| | | } |
| | | |
| | | public void setSampleBit(int sampleBit) { |
| | | this.sampleBit = sampleBit; |
| | | } |
| | | |
| | | public int getSampleRate() { |
| | | return sampleRate; |
| | | } |
| | | |
| | | public void setSampleRate(int sampleRate) { |
| | | this.sampleRate = sampleRate; |
| | | } |
| | | |
| | | public int getFps() { |
| | | return fps; |
| | | } |
| | | |
| | | public void setFps(int fps) { |
| | | this.fps = fps; |
| | | } |
| | | |
| | | public int getHeight() { |
| | | return height; |
| | | } |
| | | |
| | | public void setHeight(int height) { |
| | | this.height = height; |
| | | } |
| | | |
| | | public int getWidth() { |
| | | return width; |
| | | } |
| | | |
| | | public void setWidth(int width) { |
| | | this.width = width; |
| | | } |
| | | } |
| | | |
| | | public static class OriginSock{ |
| | | private String identifier; |
| | | private String local_ip; |
| | | private int local_port; |
| | | private String peer_ip; |
| | | private int peer_port; |
| | | |
| | | public String getIdentifier() { |
| | | return identifier; |
| | | } |
| | | |
| | | public void setIdentifier(String identifier) { |
| | | this.identifier = identifier; |
| | | } |
| | | |
| | | public String getLocal_ip() { |
| | | return local_ip; |
| | | } |
| | | |
| | | public void setLocal_ip(String local_ip) { |
| | | this.local_ip = local_ip; |
| | | } |
| | | |
| | | public int getLocal_port() { |
| | | return local_port; |
| | | } |
| | | |
| | | public void setLocal_port(int local_port) { |
| | | this.local_port = local_port; |
| | | } |
| | | |
| | | public String getPeer_ip() { |
| | | return peer_ip; |
| | | } |
| | | |
| | | public void setPeer_ip(String peer_ip) { |
| | | this.peer_ip = peer_ip; |
| | | } |
| | | |
| | | public int getPeer_port() { |
| | | return peer_port; |
| | | } |
| | | |
| | | public void setPeer_port(int peer_port) { |
| | | this.peer_port = peer_port; |
| | | } |
| | | } |
| | | |
| | | public String getApp() { |
| | | return app; |
| | | } |
| | | |
| | | public void setApp(String app) { |
| | | this.app = app; |
| | | } |
| | | |
| | | public String getStream() { |
| | | return stream; |
| | | } |
| | | |
| | | public void setStream(String stream) { |
| | | this.stream = stream; |
| | | } |
| | | |
| | | public String getTotalReaderCount() { |
| | | return totalReaderCount; |
| | | } |
| | | |
| | | public void setTotalReaderCount(String totalReaderCount) { |
| | | this.totalReaderCount = totalReaderCount; |
| | | } |
| | | |
| | | |
| | | public int getOriginType() { |
| | | return originType; |
| | | } |
| | | |
| | | public void setOriginType(int originType) { |
| | | this.originType = originType; |
| | | } |
| | | |
| | | |
| | | public String getOriginTypeStr() { |
| | | return originTypeStr; |
| | | } |
| | | |
| | | public void setOriginTypeStr(String originTypeStr) { |
| | | this.originTypeStr = originTypeStr; |
| | | } |
| | | |
| | | public String getOriginUrl() { |
| | | return originUrl; |
| | | } |
| | | |
| | | public void setOriginUrl(String originUrl) { |
| | | this.originUrl = originUrl; |
| | | } |
| | | |
| | | public Long getCreateStamp() { |
| | | return createStamp; |
| | | } |
| | | |
| | | public void setCreateStamp(Long createStamp) { |
| | | this.createStamp = createStamp; |
| | | } |
| | | |
| | | public Long getAliveSecond() { |
| | | return aliveSecond; |
| | | } |
| | | |
| | | public void setAliveSecond(Long aliveSecond) { |
| | | this.aliveSecond = aliveSecond; |
| | | } |
| | | |
| | | public List<MediaTrack> getTracks() { |
| | | return tracks; |
| | | } |
| | | |
| | | public void setTracks(List<MediaTrack> tracks) { |
| | | this.tracks = tracks; |
| | | } |
| | | |
| | | public String getSchema() { |
| | | return schema; |
| | | } |
| | | |
| | | public void setSchema(String schema) { |
| | | this.schema = schema; |
| | | } |
| | | |
| | | public void setOriginSock(OriginSock originSock) { |
| | | this.originSock = originSock; |
| | | } |
| | | |
| | | public Long getBytesSpeed() { |
| | | return bytesSpeed; |
| | | } |
| | | |
| | | public void setBytesSpeed(Long bytesSpeed) { |
| | | this.bytesSpeed = bytesSpeed; |
| | | } |
| | | |
| | | public String getVhost() { |
| | | return vhost; |
| | | } |
| | | |
| | | public void setVhost(String vhost) { |
| | | this.vhost = vhost; |
| | | } |
| | | |
| | | public OriginSock getOriginSock() { |
| | | return originSock; |
| | | } |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.storager; |
| | | |
| | | import com.genersoft.iot.vmp.common.RealVideo; |
| | | import com.genersoft.iot.vmp.common.StreamInfo; |
| | | import com.genersoft.iot.vmp.conf.MediaServerConfig; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| | | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | public interface IRedisCatchStorage { |
| | |
| | | */ |
| | | boolean isChannelSendingRTP(String channelId); |
| | | |
| | | /** |
| | | * 更新媒体流列表 |
| | | * @param mediaList |
| | | */ |
| | | void updateMediaList(List<RealVideo> mediaList); |
| | | |
| | | /** |
| | | * 获取当前媒体流列表 |
| | | * @return List<RealVideo> |
| | | */ |
| | | List<Object> getMediaList(int start, int end); |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.storager.impl; |
| | | |
| | | import com.genersoft.iot.vmp.common.RealVideo; |
| | | import com.genersoft.iot.vmp.common.StreamInfo; |
| | | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| | | import com.genersoft.iot.vmp.conf.MediaServerConfig; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | |
| | | @Component |
| | | public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 更新媒体流列表 |
| | | * @param mediaList |
| | | */ |
| | | @Override |
| | | public void updateMediaList(List<RealVideo> mediaList) { |
| | | String key = VideoManagerConstants.MEDIA_STREAM_PREFIX; |
| | | redis.del(key); |
| | | for (int i = 0; i < mediaList.size(); i++) { |
| | | RealVideo realVideo = mediaList.get(i); |
| | | redis.zAdd(key, realVideo, realVideo.getCreateStamp()); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取当前媒体流列表 |
| | | * @return List<RealVideo> |
| | | */ |
| | | @Override |
| | | public List<Object> getMediaList(int start, int end) { |
| | | String key = VideoManagerConstants.MEDIA_STREAM_PREFIX; |
| | | Set<Object> realVideos = redis.ZRange(key, start, end); |
| | | return new ArrayList(realVideos); |
| | | } |
| | | } |
| | |
| | | * @param value
|
| | | * @param score
|
| | | */
|
| | | public void zAdd(String key, String value, double score) {
|
| | | public void zAdd(Object key, Object value, double score) {
|
| | | redisTemplate.opsForZSet().add(key, value, score);
|
| | | }
|
| | |
|
| | |
| | | * @param key
|
| | | * @param value
|
| | | */
|
| | | public void zRemove(String key, String value) {
|
| | | public void zRemove(Object key, Object value) {
|
| | | redisTemplate.opsForZSet().remove(key, value);
|
| | | }
|
| | |
|
| | |
| | | * @param value
|
| | | * @param score
|
| | | */
|
| | | public Double zIncrScore(String key, String value, double score) {
|
| | | public Double zIncrScore(Object key, Object value, double score) {
|
| | | return redisTemplate.opsForZSet().incrementScore(key, value, score);
|
| | | }
|
| | |
|
| | |
| | | * @param value
|
| | | * @return
|
| | | */
|
| | | public Double zScore(String key, String value) {
|
| | | public Double zScore(Object key, Object value) {
|
| | | return redisTemplate.opsForZSet().score(key, value);
|
| | | }
|
| | |
|
| | |
| | | * @param value
|
| | | * @return
|
| | | */
|
| | | public Long zRank(String key, String value) {
|
| | | public Long zRank(Object key, Object value) {
|
| | | return redisTemplate.opsForZSet().rank(key, value);
|
| | | }
|
| | |
|
| | |
| | | * @param key
|
| | | * @return
|
| | | */
|
| | | public Long zSize(String key) {
|
| | | public Long zSize(Object key) {
|
| | | return redisTemplate.opsForZSet().zCard(key);
|
| | | }
|
| | |
|
| | |
| | | * @param end
|
| | | * @return
|
| | | */
|
| | | public Set<String> ZRange(String key, int start, int end) {
|
| | | public Set<Object> ZRange(Object key, int start, int end) {
|
| | | return redisTemplate.opsForZSet().range(key, start, end);
|
| | | }
|
| | | /**
|
| | |
| | | * @param end
|
| | | * @return
|
| | | */
|
| | | public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(String key, int start, int end) {
|
| | | public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
|
| | | return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
|
| | | }
|
| | | /**
|
| | |
| | | * @param end
|
| | | * @return
|
| | | */
|
| | | public Set<String> zRevRange(String key, int start, int end) {
|
| | | public Set<String> zRevRange(Object key, int start, int end) {
|
| | | return redisTemplate.opsForZSet().reverseRange(key, start, end);
|
| | | }
|
| | | /**
|
| | |
| | | * @param max
|
| | | * @return
|
| | | */
|
| | | public Set<String> zSortRange(String key, int min, int max) {
|
| | | public Set<String> zSortRange(Object key, int min, int max) {
|
| | | return redisTemplate.opsForZSet().rangeByScore(key, min, max);
|
| | | }
|
| | |
|
New file |
| | |
| | | package com.genersoft.iot.vmp.web; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.genersoft.iot.vmp.common.RealVideo; |
| | | import com.genersoft.iot.vmp.conf.SipConfig; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Controller; |
| | | import org.springframework.web.bind.annotation.CrossOrigin; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.ResponseBody; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 兼容LiveGBS的API:系统接口 |
| | | */ |
| | | @Controller |
| | | @CrossOrigin |
| | | @RequestMapping(value = "/api/v1/media") |
| | | public class ApiMediaController { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(ApiMediaController.class); |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | |
| | | @RequestMapping(value = "/list") |
| | | @ResponseBody |
| | | public JSONObject list( @RequestParam(required = false)Integer start, |
| | | @RequestParam(required = false)Integer limit, |
| | | @RequestParam(required = false)String q, |
| | | @RequestParam(required = false)Boolean online ){ |
| | | |
| | | List<Object> mediaList = redisCatchStorage.getMediaList(start - 1, start - 1 + limit); |
| | | JSONObject jsonObject = new JSONObject(); |
| | | jsonObject.put("code", 0); |
| | | jsonObject.put("data", mediaList); |
| | | return jsonObject; |
| | | } |
| | | } |
New file |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | | <el-main> |
| | | <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> |
| | | <span style="font-size: 1rem; font-weight: bold;">推流列表</span> |
| | | <div style="position: absolute; right: 1rem; top: 0.3rem;"> |
| | | <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button> |
| | | </div> |
| | | </div> |
| | | <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> |
| | | <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> |
| | | <el-table-column prop="schema" label="协议" width="180" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="streamUrl" label="流地址" width="240" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="online" label="在线人数" width="240" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="startTime" label="开始时间" align="center"> |
| | | </el-table-column> |
| | | |
| | | |
| | | <el-table-column label="操作" width="360" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> |
| | | <el-button-group> |
| | | <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button> |
| | | <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button> |
| | | </el-button-group> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-pagination |
| | | style="float: right" |
| | | @size-change="handleSizeChange" |
| | | @current-change="currentChange" |
| | | :current-page="currentPage" |
| | | :page-size="count" |
| | | :page-sizes="[15, 25, 35, 50]" |
| | | layout="total, sizes, prev, pager, next" |
| | | :total="total"> |
| | | </el-pagination> |
| | | |
| | | </el-main> |
| | | </el-container> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import uiHeader from './UiHeader.vue' |
| | | export default { |
| | | name: 'app', |
| | | components: { |
| | | uiHeader |
| | | }, |
| | | data() { |
| | | return { |
| | | deviceList: [], //设备列表 |
| | | currentDevice: {}, //当前操作设备对象 |
| | | |
| | | videoComponentList: [], |
| | | updateLooper: 0, //数据刷新轮训标志 |
| | | currentDeviceChannelsLenth:0, |
| | | winHeight: window.innerHeight - 200, |
| | | currentPage:1, |
| | | count:15, |
| | | total:0, |
| | | getDeviceListLoading: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | getcurrentDeviceChannels: function() { |
| | | let data = this.currentDevice['channelMap']; |
| | | let channels = null; |
| | | if (data) { |
| | | channels = Object.keys(data).map(key => { |
| | | return data[key]; |
| | | }); |
| | | this.currentDeviceChannelsLenth = channels.length; |
| | | } |
| | | |
| | | console.log("数据:" + JSON.stringify(channels)); |
| | | return channels; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.initData(); |
| | | this.updateLooper = setInterval(this.initData, 10000); |
| | | }, |
| | | destroyed() { |
| | | this.$destroy('videojs'); |
| | | clearTimeout(this.updateLooper); |
| | | }, |
| | | methods: { |
| | | initData: function() { |
| | | this.getDeviceList(); |
| | | }, |
| | | currentChange: function(val){ |
| | | this.currentPage = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | handleSizeChange: function(val){ |
| | | this.count = val; |
| | | this.getDeviceList(); |
| | | }, |
| | | getDeviceList: function() { |
| | | let that = this; |
| | | this.getDeviceListLoading = true; |
| | | this.$axios.get(`/api/devices`,{ |
| | | params: { |
| | | page: that.currentPage, |
| | | count: that.count |
| | | } |
| | | } ) |
| | | .then(function (res) { |
| | | console.log(res); |
| | | console.log(res.data.list); |
| | | that.total = res.data.total; |
| | | that.deviceList = res.data.list; |
| | | that.getDeviceListLoading = false; |
| | | }) |
| | | .catch(function (error) { |
| | | console.log(error); |
| | | that.getDeviceListLoading = false; |
| | | }); |
| | | |
| | | }, |
| | | showChannelList: function(row) { |
| | | console.log(JSON.stringify(row)) |
| | | this.$router.push(`/channelList/${row.deviceId}/0/15/1`); |
| | | }, |
| | | showDevicePosition: function(row) { |
| | | console.log(JSON.stringify(row)) |
| | | this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); |
| | | }, |
| | | |
| | | //gb28181平台对接 |
| | | //刷新设备信息 |
| | | refDevice: function(itemData) { |
| | | ///api/devices/{deviceId}/sync |
| | | console.log("刷新对应设备:" + itemData.deviceId); |
| | | var that = this; |
| | | that.$refs[itemData.deviceId + 'refbtn' ].loading = true; |
| | | this.$axios({ |
| | | method: 'post', |
| | | url: '/api/devices/' + itemData.deviceId + '/sync' |
| | | }).then(function(res) { |
| | | console.log("刷新设备结果:"+JSON.stringify(res)); |
| | | if (!res.data.deviceId) { |
| | | that.$message({ |
| | | showClose: true, |
| | | message: res.data, |
| | | type: 'error' |
| | | }); |
| | | }else{ |
| | | that.$message({ |
| | | showClose: true, |
| | | message: '请求成功', |
| | | type: 'success' |
| | | }); |
| | | } |
| | | that.initData() |
| | | that.$refs[itemData.deviceId + 'refbtn' ].loading = false; |
| | | }).catch(function(e) { |
| | | console.error(e) |
| | | that.$refs[itemData.deviceId + 'refbtn' ].loading = false; |
| | | });; |
| | | }, |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function(itemData) { |
| | | // let deviceId = this.currentDevice.deviceId; |
| | | // let channelId = itemData.channelId; |
| | | // console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | // let that = this; |
| | | // this.$axios({ |
| | | // method: 'get', |
| | | // url: '/api/play/' + deviceId + '/' + channelId |
| | | // }).then(function(res) { |
| | | // let ssrc = res.data.ssrc; |
| | | // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); |
| | | // }).catch(function(e) { |
| | | // }); |
| | | }, |
| | | transportChange: function (row) { |
| | | console.log(row); |
| | | console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `); |
| | | let that = this; |
| | | this.$axios({ |
| | | method: 'get', |
| | | url: '/api/devices/' + row.deviceId + '/transport/' + row.streamMode |
| | | }).then(function(res) { |
| | | |
| | | }).catch(function(e) { |
| | | }); |
| | | } |
| | | |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .videoList { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-content: flex-start; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | width: 15rem; |
| | | height: 10rem; |
| | | margin-right: 1rem; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-img { |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | |
| | | .video-item-img:after { |
| | | content: ""; |
| | | display: inline-block; |
| | | position: absolute; |
| | | z-index: 2; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: auto; |
| | | width: 3rem; |
| | | height: 3rem; |
| | | background-image: url("../assets/loading.png"); |
| | | background-size: cover; |
| | | background-color: #000000; |
| | | } |
| | | |
| | | .video-item-title { |
| | | position: absolute; |
| | | bottom: 0; |
| | | color: #000000; |
| | | background-color: #ffffff; |
| | | line-height: 1.5rem; |
| | | padding: 0.3rem; |
| | | width: 14.4rem; |
| | | } |
| | | </style> |
| | |
| | | <el-menu router :default-active="this.$route.path" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> |
| | | <el-menu-item index="/">控制台</el-menu-item> |
| | | <el-menu-item index="/deviceList">设备列表</el-menu-item> |
| | | <el-menu-item index="/pushVideoList">推流列表</el-menu-item> |
| | | <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> |
| | | <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> |
| | | <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item> |
| | |
| | | import control from '../components/control.vue' |
| | | import deviceList from '../components/DeviceList.vue' |
| | | import channelList from '../components/channelList.vue' |
| | | import pushVideoList from '../components/PushVideoList.vue' |
| | | import devicePosition from '../components/devicePosition.vue' |
| | | import login from '../components/Login.vue' |
| | | import parentPlatformList from '../components/ParentPlatformList.vue' |
| | |
| | | component: deviceList, |
| | | }, |
| | | { |
| | | path: '/pushVideoList', |
| | | component: pushVideoList, |
| | | }, |
| | | { |
| | | path: '/login', |
| | | name: '登录', |
| | | component: login, |