离在线状态样式修改
修复未回复200ok导致catalog一直发送的bug
修改点播接口未收到视频后回复
| | |
| | | public class StreamInfo { |
| | | |
| | | private String ssrc; |
| | | private String deviceID; |
| | | private String cahnnelId; |
| | | private String flv; |
| | | private String WS_FLV; |
| | | private String RTMP; |
| | | private String HLS; |
| | | private String RTSP; |
| | | private String ws_flv; |
| | | private String rtmp; |
| | | private String hls; |
| | | private String rtsp; |
| | | |
| | | public String getSsrc() { |
| | | return ssrc; |
| | |
| | | this.flv = flv; |
| | | } |
| | | |
| | | public String getWS_FLV() { |
| | | return WS_FLV; |
| | | public String getWs_flv() { |
| | | return ws_flv; |
| | | } |
| | | |
| | | public void setWS_FLV(String WS_FLV) { |
| | | this.WS_FLV = WS_FLV; |
| | | public void setWs_flv(String ws_flv) { |
| | | this.ws_flv = ws_flv; |
| | | } |
| | | |
| | | public String getRTMP() { |
| | | return RTMP; |
| | | public String getRtmp() { |
| | | return rtmp; |
| | | } |
| | | |
| | | public void setRTMP(String RTMP) { |
| | | this.RTMP = RTMP; |
| | | public void setRtmp(String rtmp) { |
| | | this.rtmp = rtmp; |
| | | } |
| | | |
| | | public String getHLS() { |
| | | return HLS; |
| | | public String getHls() { |
| | | return hls; |
| | | } |
| | | |
| | | public void setHLS(String HLS) { |
| | | this.HLS = HLS; |
| | | public void setHls(String hls) { |
| | | this.hls = hls; |
| | | } |
| | | |
| | | public String getRTSP() { |
| | | return RTSP; |
| | | public String getRtsp() { |
| | | return rtsp; |
| | | } |
| | | |
| | | public void setRTSP(String RTSP) { |
| | | this.RTSP = RTSP; |
| | | public void setRtsp(String rtsp) { |
| | | this.rtsp = rtsp; |
| | | } |
| | | |
| | | public String getDeviceID() { |
| | | return deviceID; |
| | | } |
| | | |
| | | public void setDeviceID(String deviceID) { |
| | | this.deviceID = deviceID; |
| | | } |
| | | |
| | | public String getCahnnelId() { |
| | | return cahnnelId; |
| | | } |
| | | |
| | | public void setCahnnelId(String cahnnelId) { |
| | | this.cahnnelId = cahnnelId; |
| | | } |
| | | } |
| | |
| | | StreamInfo streamInfo = new StreamInfo();
|
| | | streamInfo.setSsrc(ssrc);
|
| | | // String streamId = Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()));
|
| | | String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); // ZLM 要求大写且首位补零
|
| | | streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setWS_FLV(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setRTMP(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
|
| | | streamInfo.setHLS(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setRTSP(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
|
| | |
|
| | | storager.startPlay(device.getDeviceId(), channelId, streamInfo);
|
| | | // String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); // ZLM 要求大写且首位补零
|
| | | // streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | // streamInfo.setWS_FLV(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | // streamInfo.setRTMP(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
|
| | | // streamInfo.setHLS(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | // streamInfo.setRTSP(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
|
| | | streamInfo.setCahnnelId(channelId);
|
| | | streamInfo.setDeviceID(device.getDeviceId());
|
| | | storager.startPlay(streamInfo);
|
| | | return streamInfo;
|
| | | } catch ( SipException | ParseException | InvalidArgumentException e) {
|
| | | e.printStackTrace();
|
| | |
| | | msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
|
| | | msg.setData(device);
|
| | | deferredResultHolder.invokeResult(msg);
|
| | |
|
| | | // 回复200
|
| | | responseAck(evt);
|
| | | }
|
| | | } catch (DocumentException e) {
|
| | | } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
|
| | | e.printStackTrace();
|
| | | }
|
| | | }
|
| | |
| | | package com.genersoft.iot.vmp.media.zlm;
|
| | |
|
| | | import java.math.BigInteger;
|
| | | import java.text.DecimalFormat;
|
| | | import java.util.ArrayList;
|
| | | import java.util.List;
|
| | |
|
| | | import com.alibaba.fastjson.JSON;
|
| | | import com.alibaba.fastjson.JSONArray;
|
| | | import com.genersoft.iot.vmp.common.StreamInfo;
|
| | | import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
| | | import com.genersoft.iot.vmp.utils.IpUtil;
|
| | |
| | | public class ZLMHttpHookListener {
|
| | |
|
| | | private final static Logger logger = LoggerFactory.getLogger(ZLMHttpHookListener.class);
|
| | | |
| | |
|
| | |
|
| | | @Autowired
|
| | | private SIPCommander cmder;
|
| | |
|
| | |
| | | logger.debug("ZLM HOOK on_flow_report API调用,参数:" + json.toString());
|
| | | }
|
| | | // TODO Auto-generated method stub
|
| | | |
| | |
|
| | |
|
| | | JSONObject ret = new JSONObject();
|
| | | ret.put("code", 0);
|
| | |
| | | if (logger.isDebugEnabled()) {
|
| | | logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString());
|
| | | }
|
| | | String app = json.getString("app");
|
| | | String streamId = json.getString("id");
|
| | | // String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
|
| | | String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
|
| | | StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
| | | if ("rtp".equals(app) && streamInfo != null ) {
|
| | | MediaServerConfig mediaInfo = storager.getMediaInfo();
|
| | | streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId));
|
| | | streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId));
|
| | | streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId));
|
| | | storager.startPlay(streamInfo);
|
| | | }
|
| | |
|
| | | // TODO Auto-generated method stub
|
| | |
|
| | | JSONObject ret = new JSONObject();
|
| | |
| | | if (logger.isDebugEnabled()) {
|
| | | logger.debug("ZLM HOOK on_stream_changed API调用,参数:" + json.toString());
|
| | | }
|
| | | // TODO Auto-generated method stub
|
| | | |
| | | // 流消失移除redis play
|
| | | String app = json.getString("app");
|
| | | String streamId = json.getString("stream");
|
| | | boolean regist = json.getBoolean("regist");
|
| | | // String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
|
| | | String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
|
| | | StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
| | | if ("rtp".equals(app) && !regist ) {
|
| | | storager.stopPlay(streamInfo);
|
| | | }
|
| | |
|
| | |
|
| | | JSONObject ret = new JSONObject();
|
| | | ret.put("code", 0);
|
| | | ret.put("msg", "success");
|
| | |
| | | /**
|
| | | * 开始播放时将流存入
|
| | | *
|
| | | * @param deviceId 设备ID
|
| | | * @param channelId 通道ID
|
| | | * @param stream 流信息
|
| | | * @return
|
| | | */
|
| | | public boolean startPlay(String deviceId, String channelId, StreamInfo stream);
|
| | | public boolean startPlay(StreamInfo stream);
|
| | |
|
| | | /**
|
| | | * 停止播放时删除
|
| | | *
|
| | | * @param deviceId 设备ID
|
| | | * @param channelId 通道ID
|
| | | * @return
|
| | | */
|
| | | public boolean stopPlay(String deviceId, String channelId);
|
| | | public boolean stopPlay(StreamInfo streamInfo);
|
| | |
|
| | | /**
|
| | | * 查找视频流
|
| | | *
|
| | | * @param deviceId 设备ID
|
| | | * @param channelId 通道ID
|
| | | * @return
|
| | | */
|
| | | public StreamInfo queryPlay(String deviceId, String channelId);
|
| | | public StreamInfo queryPlay(StreamInfo streamInfo);
|
| | |
|
| | | /**
|
| | | * 查询子设备
|
| | |
| | | * @param deviceId
|
| | | */
|
| | | void cleanChannelsForDevice(String deviceId);
|
| | |
|
| | | StreamInfo queryPlayBySSRC(String ssrc);
|
| | |
|
| | | StreamInfo queryPlayByDevice(String deviceId, String code);
|
| | | }
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean startPlay(String deviceId, String channelId, StreamInfo stream) {
|
| | | public boolean stopPlay(StreamInfo streamInfo) {
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean stopPlay(String deviceId, String channelId) {
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public StreamInfo queryPlay(String deviceId, String channelId) {
|
| | | public StreamInfo queryPlay(StreamInfo streamInfo) {
|
| | | return null;
|
| | | }
|
| | |
|
| | |
| | | public void cleanChannelsForDevice(String deviceId) {
|
| | |
|
| | | }
|
| | |
|
| | | @Override
|
| | | public boolean startPlay(StreamInfo stream) {
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public StreamInfo queryPlayBySSRC(String ssrc) {
|
| | | return null;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public StreamInfo queryPlayByDevice(String deviceId, String code) {
|
| | | return null;
|
| | | }
|
| | | }
|
| | |
| | | /** |
| | | * 开始播放时将流存入redis |
| | | * |
| | | * @param deviceId 设备ID |
| | | * @param channelId 通道ID |
| | | * @return |
| | | */ |
| | | @Override |
| | | public boolean startPlay(String deviceId, String channelId, StreamInfo stream) { |
| | | return redis.set(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId), |
| | | public boolean startPlay(StreamInfo stream) { |
| | | return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()), |
| | | stream); |
| | | } |
| | | |
| | | /** |
| | | * 停止播放时从redis删除 |
| | | * |
| | | * @param deviceId 设备ID |
| | | * @param channelId 通道ID |
| | | * @return |
| | | */ |
| | | @Override |
| | | public boolean stopPlay(String deviceId, String channelId) { |
| | | return redis.del(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId)); |
| | | public boolean stopPlay(StreamInfo streamInfo) { |
| | | return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, |
| | | streamInfo.getSsrc(), |
| | | streamInfo.getDeviceID(), |
| | | streamInfo.getCahnnelId())); |
| | | } |
| | | |
| | | /** |
| | | * 查询播放列表 |
| | | * @param deviceId 设备ID |
| | | * @param channelId 通道ID |
| | | * @return |
| | | */ |
| | | @Override |
| | | public StreamInfo queryPlay(String deviceId, String channelId) { |
| | | return (StreamInfo)redis.get(String.format("%S_%s_%s", VideoManagerConstants.PLAYER_PREFIX, deviceId, channelId)); |
| | | public StreamInfo queryPlay(StreamInfo streamInfo) { |
| | | return (StreamInfo)redis.get(String.format("%S_%s_%s_%s", |
| | | VideoManagerConstants.PLAYER_PREFIX, |
| | | streamInfo.getSsrc(), |
| | | streamInfo.getDeviceID(), |
| | | streamInfo.getCahnnelId())); |
| | | } |
| | | @Override |
| | | public StreamInfo queryPlayBySSRC(String ssrc) { |
| | | List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc)); |
| | | if (playLeys.size() == 0) return null; |
| | | return (StreamInfo)redis.get(playLeys.get(0).toString()); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public StreamInfo queryPlayByDevice(String deviceId, String code) { |
| | | List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, |
| | | deviceId, |
| | | code)); |
| | | return (StreamInfo)redis.get(playLeys.get(0).toString()); |
| | | } |
| | | |
| | | /** |
| | | * 更新流媒体信息 |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | Device device = storager.queryVideoDevice(deviceId); |
| | | StreamInfo streamInfo = cmder.playStreamCmd(device, channelId); |
| | | |
| | | // 等待推流, TODO 默认超时15s |
| | | |
| | | long startTime = System.currentTimeMillis(); |
| | | while (storager.queryPlay(streamInfo) == null || storager.queryPlay(streamInfo).getFlv() == null) { |
| | | try { |
| | | if (System.currentTimeMillis() - startTime > 15 * 1000) |
| | | Thread.sleep(200); |
| | | } catch (InterruptedException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | streamInfo = storager.queryPlay(streamInfo); |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",deviceId, channelId)); |
| | | logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc()))); |
| | |
| | | public ResponseEntity<String> playStop(@PathVariable String ssrc){ |
| | | |
| | | cmder.streamByeCmd(ssrc); |
| | | |
| | | StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); |
| | | storager.stopPlay(streamInfo); |
| | | if (logger.isDebugEnabled()) { |
| | | logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc)); |
| | | } |
| | |
| | | return result; |
| | | } |
| | | // 查询是否已经在播放 |
| | | StreamInfo streamInfo = storager.queryPlay(device.getDeviceId(), code); |
| | | StreamInfo streamInfo = storager.queryPlayByDevice(device.getDeviceId(), code); |
| | | if (streamInfo == null) streamInfo = cmder.playStreamCmd(device, code); |
| | | |
| | | if (logger.isDebugEnabled()) { |
| | |
| | | result.put("ChannelName", deviceChannel.getName()); |
| | | result.put("ChannelCustomName ", ""); |
| | | result.put("FLV ", streamInfo.getFlv()); |
| | | result.put("WS_FLV ", streamInfo.getWS_FLV()); |
| | | result.put("RTMP", streamInfo.getRTMP()); |
| | | result.put("HLS", streamInfo.getHLS()); |
| | | result.put("RTSP", streamInfo.getRTSP()); |
| | | result.put("WS_FLV ", streamInfo.getWs_flv()); |
| | | result.put("RTMP", streamInfo.getRtmp()); |
| | | result.put("HLS", streamInfo.getHls()); |
| | | result.put("RTSP", streamInfo.getRtsp()); |
| | | result.put("CDN", ""); |
| | | result.put("SnapURL", ""); |
| | | result.put("Transport", device.getTransport()); |
| | |
| | | @RequestParam(required = false)String check_outputs |
| | | |
| | | ){ |
| | | StreamInfo streamInfo = storager.queryPlay(serial, code); |
| | | StreamInfo streamInfo = storager.queryPlayByDevice(serial, code); |
| | | if (streamInfo == null) { |
| | | JSONObject result = new JSONObject(); |
| | | result.put("error","未找到流信息"); |
| | | return result; |
| | | } |
| | | cmder.streamByeCmd(streamInfo.getSsrc()); |
| | | storager.stopPlay(serial, code); |
| | | storager.stopPlay(streamInfo); |
| | | return null; |
| | | } |
| | | |
| | |
| | | * @param serial 设备编号 |
| | | * @param channel 通道序号 |
| | | * @param code 通道国标编号 |
| | | * @param check_outputs |
| | | * @return |
| | | */ |
| | | @RequestMapping(value = "/touch") |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="subCount" label="子节点数"> |
| | | </el-table-column> |
| | | <el-table-column prop="ptztypeText" label="云台类型"> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium" v-if="scope.row.status == 1">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.status == 0">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="ptztypeText" label="云台类型"> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="240" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">预览视频</el-button> |
| | |
| | | |
| | | </el-main> |
| | | </el-container> |
| | | <Loading v-if="isLoging" marginTop="-50%"></Loading> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import devicePlayer from './gb28181/devicePlayer.vue' |
| | | import uiHeader from './UiHeader.vue' |
| | | import Loading from './Loading.vue' |
| | | export default { |
| | | name: 'channelList', |
| | | components: { |
| | | devicePlayer, |
| | | uiHeader |
| | | uiHeader, |
| | | Loading |
| | | }, |
| | | data() { |
| | | return { |
| | |
| | | currentPage: parseInt(this.$route.params.page), |
| | | count: parseInt(this.$route.params.count), |
| | | total:0, |
| | | beforeUrl:"/videoList" |
| | | beforeUrl:"/videoList", |
| | | isLoging: false |
| | | }; |
| | | }, |
| | | |
| | |
| | | //通知设备上传媒体流 |
| | | sendDevicePush: function(itemData) { |
| | | let deviceId = this.deviceId; |
| | | |
| | | this.isLoging = true; |
| | | let channelId = itemData.channelId; |
| | | console.log("通知设备推流1:" + deviceId + " : " + channelId); |
| | | let that = this; |
| | |
| | | url: '/api/play/' + deviceId + '/' + channelId |
| | | }).then(function(res) { |
| | | let ssrc = res.data.ssrc; |
| | | that.isLoging = false |
| | | that.$refs.devicePlayer.play(res.data,deviceId,channelId); |
| | | }).catch(function(e) { |
| | | }); |
| | |
| | | deviceId: '', |
| | | channelId: '', |
| | | tabActiveName: 'media' |
| | | |
| | | }; |
| | | }, |
| | | methods: { |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <el-container> |
| | | |
| | | <el-header> |
| | | <uiHeader></uiHeader> |
| | | </el-header> |
| | |
| | | <el-table-column label="状态" width="180" align="center"> |
| | | <template slot-scope="scope"> |
| | | <div slot="reference" class="name-wrapper"> |
| | | <el-tag size="medium">{{ scope.row.online==1?'在线' :'离线'}}</el-tag> |
| | | <el-tag size="medium" v-if="scope.row.online == 1">在线</el-tag> |
| | | <el-tag size="medium" type="info" v-if="scope.row.online == 0">离线</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="操作" width="240" align="center" fixed="right"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> |
| | | <el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button> |
| | | <el-button size="mini" icon="el-icon-s-open" type="primary" @click="showChannelList(scope.row)">查看通道</el-button> |
| | | </template> |
| | | </el-table-column> |