修复点播判断错误导致的15s超长延时
增加默认不关闭推流, 无人观看超时或点击停止按钮关闭流 修复点播其他bug
This commit is contained in:
parent
fbdad00cdb
commit
3ec3b88456
@ -148,6 +148,11 @@ public class DeviceChannel {
|
||||
*/
|
||||
private boolean hasAudio;
|
||||
|
||||
/**
|
||||
* 是否正在播放
|
||||
*/
|
||||
private boolean play;
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
@ -388,4 +393,12 @@ public class DeviceChannel {
|
||||
public void setHasAudio(boolean hasAudio) {
|
||||
this.hasAudio = hasAudio;
|
||||
}
|
||||
|
||||
public boolean isPlay() {
|
||||
return play;
|
||||
}
|
||||
|
||||
public void setPlay(boolean play) {
|
||||
this.play = play;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ public class ZLMRunner implements CommandLineRunner {
|
||||
@Value("${media.secret}")
|
||||
private String mediaSecret;
|
||||
|
||||
@Value("${media.streamNoneReaderDelayMS}")
|
||||
private String streamNoneReaderDelayMS;
|
||||
|
||||
@Value("${sip.ip}")
|
||||
private String sipIP;
|
||||
|
||||
@ -54,9 +57,10 @@ public class ZLMRunner implements CommandLineRunner {
|
||||
MediaServerConfig mediaServerConfig = getMediaServerConfig();
|
||||
if (mediaServerConfig != null) {
|
||||
logger.info("zlm接入成功...");
|
||||
storager.updateMediaInfo(mediaServerConfig);
|
||||
logger.info("设置zlm...");
|
||||
saveZLMConfig();
|
||||
mediaServerConfig = getMediaServerConfig();
|
||||
storager.updateMediaInfo(mediaServerConfig);
|
||||
|
||||
}
|
||||
}
|
||||
@ -79,7 +83,7 @@ public class ZLMRunner implements CommandLineRunner {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
getMediaServerConfig();
|
||||
mediaServerConfig = getMediaServerConfig();
|
||||
}
|
||||
return mediaServerConfig;
|
||||
}
|
||||
@ -106,6 +110,7 @@ public class ZLMRunner implements CommandLineRunner {
|
||||
param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
|
||||
param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
|
||||
param.put("hook.timeoutSec","20");
|
||||
param.put("general.streamNoneReaderDelayMS",streamNoneReaderDelayMS);
|
||||
|
||||
JSONObject responseJSON = zlmresTfulUtils.setServerConfig(param);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.storager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.PageResult;
|
||||
@ -180,4 +181,6 @@ public interface IVideoManagerStorager {
|
||||
StreamInfo queryPlayBySSRC(String ssrc);
|
||||
|
||||
StreamInfo queryPlayByDevice(String deviceId, String code);
|
||||
|
||||
Map<String, StreamInfo> queryPlayByDeviceId(String deviceId);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.storager.jdbc;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.genersoft.iot.vmp.common.PageResult;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
@ -186,4 +187,9 @@ public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
|
||||
public StreamInfo queryPlayByDevice(String deviceId, String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,8 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
|
||||
@Override
|
||||
public PageResult queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
||||
// 获取到所有正在播放的流
|
||||
Map<String, StreamInfo> stringStreamInfoMap = queryPlayByDeviceId(deviceId);
|
||||
List<DeviceChannel> result = new ArrayList<>();
|
||||
PageResult pageResult = new PageResult<DeviceChannel>();
|
||||
String queryContent = "*";
|
||||
@ -154,7 +156,11 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
int maxCount = (page + 1 ) * count;
|
||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
||||
for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
|
||||
result.add((DeviceChannel)redis.get((String)deviceChannelList.get(i)));
|
||||
DeviceChannel deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(i));
|
||||
StreamInfo streamInfo = stringStreamInfoMap.get(deviceId + "_" + deviceChannel.getChannelId());
|
||||
deviceChannel.setPlay(streamInfo != null);
|
||||
if (streamInfo != null) deviceChannel.setSsrc(streamInfo.getSsrc());
|
||||
result.add(deviceChannel);
|
||||
}
|
||||
pageResult.setData(result);
|
||||
}
|
||||
@ -162,6 +168,8 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
|
||||
List<DeviceChannel> result = new ArrayList<>();
|
||||
@ -231,7 +239,13 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
|
||||
@Override
|
||||
public DeviceChannel queryChannel(String deviceId, String channelId) {
|
||||
return (DeviceChannel)redis.get(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + channelId + "_");
|
||||
DeviceChannel deviceChannel = null;
|
||||
List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
||||
"_" + channelId + "*");
|
||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
||||
deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(0));
|
||||
}
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
|
||||
@ -345,6 +359,12 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
@Override
|
||||
public boolean stopPlay(StreamInfo streamInfo) {
|
||||
if (streamInfo == null) return false;
|
||||
DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
|
||||
if (deviceChannel != null) {
|
||||
deviceChannel.setSsrc(null);
|
||||
deviceChannel.setPlay(false);
|
||||
updateChannel(streamInfo.getDeviceID(), deviceChannel);
|
||||
}
|
||||
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
||||
streamInfo.getSsrc(),
|
||||
streamInfo.getDeviceID(),
|
||||
@ -366,7 +386,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
@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;
|
||||
if (playLeys == null || playLeys.size() == 0) return null;
|
||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||
}
|
||||
|
||||
@ -375,6 +395,7 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
||||
deviceId,
|
||||
code));
|
||||
if (playLeys == null || playLeys.size() == 0) return null;
|
||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||
}
|
||||
|
||||
@ -438,6 +459,19 @@ public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
|
||||
Map<String, StreamInfo> streamInfos = new HashMap<>();
|
||||
List<Object> playLeys = redis.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
|
||||
if (playLeys.size() == 0) return streamInfos;
|
||||
for (int i = 0; i < playLeys.size(); i++) {
|
||||
String key = (String) playLeys.get(i);
|
||||
StreamInfo streamInfo = (StreamInfo)redis.get(key);
|
||||
streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getCahnnelId(), streamInfo);
|
||||
}
|
||||
return streamInfos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -41,18 +41,36 @@ public class PlayController {
|
||||
public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId){
|
||||
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
StreamInfo streamInfo = cmder.playStreamCmd(device, channelId);
|
||||
StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId);
|
||||
|
||||
if (streamInfo == null) {
|
||||
streamInfo = cmder.playStreamCmd(device, channelId);
|
||||
}else {
|
||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||
if (rtpInfo.getBoolean("exist")) {
|
||||
return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK);
|
||||
}else {
|
||||
storager.stopPlay(streamInfo);
|
||||
streamInfo = cmder.playStreamCmd(device, channelId);
|
||||
}
|
||||
|
||||
}
|
||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
||||
// 等待推流, TODO 默认超时15s
|
||||
boolean lockFlag = true;
|
||||
long startTime = System.currentTimeMillis();
|
||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
||||
|
||||
// 判断推流是否存在
|
||||
while (lockFlag) {
|
||||
try {
|
||||
|
||||
if (System.currentTimeMillis() - startTime > 15 * 1000) {
|
||||
storager.stopPlay(streamInfo);
|
||||
return new ResponseEntity<String>("timeout",HttpStatus.OK);
|
||||
}else {
|
||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||
if (rtpInfo == null){
|
||||
Boolean exist = rtpInfo.getBoolean("exist");
|
||||
if (rtpInfo == null || !rtpInfo.getBoolean("exist") || streamInfo.getFlv() != null){
|
||||
continue;
|
||||
}else {
|
||||
lockFlag = false;
|
||||
@ -72,10 +90,9 @@ public class PlayController {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Thread.sleep(200);
|
||||
streamInfo = storager.queryPlayByDevice(deviceId, channelId);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -43,4 +43,5 @@ media: #zlm服务器的ip与http端口, 重点: 这是http端口
|
||||
ip: 192.168.1.20
|
||||
port: 9080
|
||||
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||
streamNoneReaderDelayMS: 1800000 # 无人观看多久关闭流
|
||||
|
||||
|
@ -56,7 +56,8 @@
|
||||
</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-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button>
|
||||
<el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="scope.row.play" @click="stopDevicePush(scope.row)">停止</el-button>
|
||||
<el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.parental == 1" @click="changeSubchannel(scope.row)">查看子目录</el-button>
|
||||
<!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
|
||||
</template>
|
||||
@ -198,7 +199,7 @@
|
||||
message: '请求成功',
|
||||
type: 'success'
|
||||
});
|
||||
});;
|
||||
});
|
||||
},
|
||||
//通知设备上传媒体流
|
||||
sendDevicePush: function(itemData) {
|
||||
@ -212,12 +213,30 @@
|
||||
method: 'get',
|
||||
url: '/api/play/' + deviceId + '/' + channelId
|
||||
}).then(function(res) {
|
||||
console.log(res.data)
|
||||
let ssrc = res.data.ssrc;
|
||||
that.isLoging = false
|
||||
if (!!ssrc) {
|
||||
that.$refs.devicePlayer.play(res.data,deviceId,channelId,itemData.hasAudio);
|
||||
that.initData();
|
||||
}else {
|
||||
that.$message.error(res.data);
|
||||
}
|
||||
}).catch(function(e) {
|
||||
});
|
||||
},
|
||||
stopDevicePush: function(itemData) {
|
||||
console.log(itemData)
|
||||
var that = this;
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/play/' + itemData.ssrc + '/stop'
|
||||
}).then(function(res) {
|
||||
console.log(JSON.stringify(res));
|
||||
that.initData();
|
||||
});
|
||||
},
|
||||
|
||||
showDevice: function(){
|
||||
this.$router.push(this.beforeUrl).then(()=>{
|
||||
this.initParam();
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="devicePlayer">
|
||||
<el-dialog title="视频播放" top="0" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="stop()">
|
||||
<el-dialog title="视频播放" top="0" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()">
|
||||
<LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :hasaudio="hasaudio" fluent autoplay live ></LivePlayer>
|
||||
<div id="shared" style="text-align: right; margin-top: 1rem;">
|
||||
<el-tabs v-model="tabActiveName">
|
||||
@ -145,24 +145,11 @@
|
||||
this.showVideoDialog = true;
|
||||
console.log(this.ssrc);
|
||||
},
|
||||
stop: function() {
|
||||
close: function() {
|
||||
console.log('关闭视频');
|
||||
this.$refs.videoPlayer.pause();
|
||||
this.videoUrl = '';
|
||||
this.showVideoDialog = false;
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/play/' + this.ssrc + '/stop'
|
||||
}).then(function(res) {
|
||||
console.log(JSON.stringify(res));
|
||||
});
|
||||
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/playback/' + this.ssrc + '/stop'
|
||||
}).then(function(res) {
|
||||
console.log(JSON.stringify(res));
|
||||
});
|
||||
},
|
||||
copySharedInfo: function(data) {
|
||||
console.log('复制内容:' + data);
|
||||
|
Loading…
Reference in New Issue
Block a user