优化录像下载。 支持八倍速(设备支持的最高速度)下载
parent
1869945ff1
commit
298fb05378
|
@ -37,6 +37,10 @@ public class InviteInfo {
|
||||||
|
|
||||||
private Boolean record;
|
private Boolean record;
|
||||||
|
|
||||||
|
private String startTime;
|
||||||
|
|
||||||
|
private String endTime;
|
||||||
|
|
||||||
|
|
||||||
public static InviteInfo getInviteInfo(String deviceId, Integer channelId, String stream, SSRCInfo ssrcInfo, String mediaServerId,
|
public static InviteInfo getInviteInfo(String deviceId, Integer channelId, String stream, SSRCInfo ssrcInfo, String mediaServerId,
|
||||||
String receiveIp, Integer receivePort, String streamMode,
|
String receiveIp, Integer receivePort, String streamMode,
|
||||||
|
|
|
@ -15,7 +15,6 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
||||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
|
||||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||||
|
@ -210,6 +209,13 @@ public class DeviceQuery {
|
||||||
public void updateChannelStreamIdentification(DeviceChannel channel){
|
public void updateChannelStreamIdentification(DeviceChannel channel){
|
||||||
deviceChannelService.updateChannelStreamIdentification(channel);
|
deviceChannelService.updateChannelStreamIdentification(channel);
|
||||||
}
|
}
|
||||||
|
@Operation(summary = "获取单个通道详情", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "deviceId", description = "设备的国标编码", required = true)
|
||||||
|
@Parameter(name = "channelDeviceId", description = "通道的国标编码", required = true)
|
||||||
|
@GetMapping("/channel/one")
|
||||||
|
public DeviceChannel getChannel(String deviceId, String channelDeviceId){
|
||||||
|
return deviceChannelService.getOne(deviceId, channelDeviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
@Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
|
|
@ -390,6 +390,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
rtpServerParam.setTcpMode(tcpMode);
|
rtpServerParam.setTcpMode(tcpMode);
|
||||||
rtpServerParam.setOnlyAuto(false);
|
rtpServerParam.setOnlyAuto(false);
|
||||||
rtpServerParam.setDisableAudio(!channel.isHasAudio());
|
rtpServerParam.setDisableAudio(!channel.isHasAudio());
|
||||||
|
|
||||||
SSRCInfo ssrcInfo = receiveRtpServerService.openRTPServer(rtpServerParam, (code, msg, result) -> {
|
SSRCInfo ssrcInfo = receiveRtpServerService.openRTPServer(rtpServerParam, (code, msg, result) -> {
|
||||||
|
|
||||||
if (code == InviteErrorCode.SUCCESS.getCode() && result != null && result.getHookData() != null) {
|
if (code == InviteErrorCode.SUCCESS.getCode() && result != null && result.getHookData() != null) {
|
||||||
|
@ -1055,6 +1056,8 @@ public class PlayServiceImpl implements IPlayService {
|
||||||
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getId(), ssrcInfo.getStream(), ssrcInfo, mediaServerItem.getId(),
|
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getId(), ssrcInfo.getStream(), ssrcInfo, mediaServerItem.getId(),
|
||||||
mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
|
mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
|
||||||
InviteSessionStatus.ready, true);
|
InviteSessionStatus.ready, true);
|
||||||
|
inviteInfo.setStartTime(startTime);
|
||||||
|
inviteInfo.setEndTime(endTime);
|
||||||
|
|
||||||
inviteStreamService.updateInviteInfo(inviteInfo);
|
inviteStreamService.updateInviteInfo(inviteInfo);
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.media.event.hook.Hook;
|
||||||
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
|
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.event.hook.HookType;
|
import com.genersoft.iot.vmp.media.event.hook.HookType;
|
||||||
import com.genersoft.iot.vmp.service.ISendRtpServerService;
|
import com.genersoft.iot.vmp.service.ISendRtpServerService;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
|
||||||
import gov.nist.javax.sip.message.SIPRequest;
|
import gov.nist.javax.sip.message.SIPRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
|
@ -101,6 +100,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
|
||||||
// 去除监听流注销自动停止下载的监听
|
// 去除监听流注销自动停止下载的监听
|
||||||
Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcTransaction.getStream(), ssrcTransaction.getMediaServerId());
|
Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcTransaction.getStream(), ssrcTransaction.getMediaServerId());
|
||||||
subscribe.removeSubscribe(hook);
|
subscribe.removeSubscribe(hook);
|
||||||
|
if (ssrcTransaction.getPlatformId() != null) {
|
||||||
// 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
|
// 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
|
||||||
SendRtpInfo sendRtpInfo = sendRtpServerService.queryByChannelId(ssrcTransaction.getChannelId(), ssrcTransaction.getPlatformId());
|
SendRtpInfo sendRtpInfo = sendRtpServerService.queryByChannelId(ssrcTransaction.getChannelId(), ssrcTransaction.getPlatformId());
|
||||||
if (sendRtpInfo != null) {
|
if (sendRtpInfo != null) {
|
||||||
|
@ -120,6 +120,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
|
||||||
log.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
|
log.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
log.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息");
|
log.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息");
|
||||||
}
|
}
|
||||||
|
|
|
@ -807,7 +807,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay) {
|
public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay) {
|
||||||
System.out.println(callId);
|
|
||||||
StreamInfo streamInfoResult = new StreamInfo();
|
StreamInfo streamInfoResult = new StreamInfo();
|
||||||
streamInfoResult.setStream(stream);
|
streamInfoResult.setStream(stream);
|
||||||
streamInfoResult.setApp(app);
|
streamInfoResult.setApp(app);
|
||||||
|
|
|
@ -173,9 +173,9 @@ public class MediaServiceImpl implements IMediaService {
|
||||||
if (ssrcTransaction.getType() == InviteSessionType.DOWNLOAD) {
|
if (ssrcTransaction.getType() == InviteSessionType.DOWNLOAD) {
|
||||||
// 获取录像的总时长,然后设置为这个视频的时长
|
// 获取录像的总时长,然后设置为这个视频的时长
|
||||||
InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channelId, stream);
|
InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channelId, stream);
|
||||||
if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) {
|
if (inviteInfoForDownload != null) {
|
||||||
String startTime = inviteInfoForDownload.getStreamInfo().getStartTime();
|
String startTime = inviteInfoForDownload.getStartTime();
|
||||||
String endTime = inviteInfoForDownload.getStreamInfo().getEndTime();
|
String endTime = inviteInfoForDownload.getEndTime();
|
||||||
long difference = DateUtil.getDifference(startTime, endTime) / 1000;
|
long difference = DateUtil.getDifference(startTime, endTime) / 1000;
|
||||||
result.setMp4_max_second((int) difference);
|
result.setMp4_max_second((int) difference);
|
||||||
result.setEnable_mp4(true);
|
result.setEnable_mp4(true);
|
||||||
|
|
|
@ -33,6 +33,9 @@ public final class JsonUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T redisHashJsonToObject(RedisTemplate<Object, Object> redisTemplate, String key, String objKey, Class<T> clazz) {
|
public static <T> T redisHashJsonToObject(RedisTemplate<Object, Object> redisTemplate, String key, String objKey, Class<T> clazz) {
|
||||||
|
// if (key == null || objKey == null) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
Object jsonObject = redisTemplate.opsForHash().get(key, objKey);
|
Object jsonObject = redisTemplate.opsForHash().get(key, objKey);
|
||||||
if (Objects.isNull(jsonObject)) {
|
if (Objects.isNull(jsonObject)) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -65,11 +65,7 @@
|
||||||
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
|
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item command="0.25">0.25倍速</el-dropdown-item>
|
<el-dropdown-item v-for="(item,index) in downloadSpeedArray" :key="index" :command="item">{{item}}倍速</el-dropdown-item>
|
||||||
<el-dropdown-item command="0.5">0.5倍速</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="1.0">1倍速</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="2.0">2倍速</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="4.0">4倍速</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
|
<el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
|
||||||
|
@ -115,6 +111,7 @@
|
||||||
return {
|
return {
|
||||||
deviceId: this.$route.params.deviceId,
|
deviceId: this.$route.params.deviceId,
|
||||||
channelId: this.$route.params.channelId,
|
channelId: this.$route.params.channelId,
|
||||||
|
downloadSpeedArray: [0.25, 0.5, 1, 2, 4],
|
||||||
recordsLoading: false,
|
recordsLoading: false,
|
||||||
streamId: "",
|
streamId: "",
|
||||||
hasAudio: false,
|
hasAudio: false,
|
||||||
|
@ -184,6 +181,7 @@
|
||||||
this.playerBoxStyle["height"] = this.winHeight + "px";
|
this.playerBoxStyle["height"] = this.winHeight + "px";
|
||||||
this.chooseDate = moment().format('YYYY-MM-DD')
|
this.chooseDate = moment().format('YYYY-MM-DD')
|
||||||
this.dateChange();
|
this.dateChange();
|
||||||
|
this.getDownloadSpeedArray()
|
||||||
window.addEventListener('beforeunload', this.stopPlayRecord)
|
window.addEventListener('beforeunload', this.stopPlayRecord)
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
@ -274,6 +272,27 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getDownloadSpeedArray(){
|
||||||
|
this.$axios({
|
||||||
|
method: 'get',
|
||||||
|
url: '/api/device/query/channel/one',
|
||||||
|
params: {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelDeviceId: this.channelId,
|
||||||
|
}
|
||||||
|
}).then((res)=> {
|
||||||
|
if (res.data.code === 0 && res.data.data.downloadSpeed) {
|
||||||
|
let speedArray = res.data.data.downloadSpeed.split('/');
|
||||||
|
|
||||||
|
speedArray.forEach(item => {
|
||||||
|
if (parseInt(item) > 4) {
|
||||||
|
this.downloadSpeedArray.push(parseInt(item));
|
||||||
|
console.log(this.downloadSpeedArray);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
gbPlay(){
|
gbPlay(){
|
||||||
console.log('前端控制:播放');
|
console.log('前端控制:播放');
|
||||||
this.$axios({
|
this.$axios({
|
||||||
|
@ -317,7 +336,7 @@
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
|
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
|
||||||
row.endTime + '&downloadSpeed=4'
|
row.endTime + '&downloadSpeed='+ this.downloadSpeedArray[this.downloadSpeedArray.length - 1]
|
||||||
}).then( (res)=> {
|
}).then( (res)=> {
|
||||||
if (res.data.code === 0) {
|
if (res.data.code === 0) {
|
||||||
let streamInfo = res.data.data;
|
let streamInfo = res.data.data;
|
||||||
|
|
|
@ -53,6 +53,7 @@ export default {
|
||||||
this.showDialog = true;
|
this.showDialog = true;
|
||||||
this.getProgressRun = true;
|
this.getProgressRun = true;
|
||||||
this.percentage = 0.0;
|
this.percentage = 0.0;
|
||||||
|
this.downloadFile = null;
|
||||||
this.getProgressTimer()
|
this.getProgressTimer()
|
||||||
},
|
},
|
||||||
getProgressTimer: function (){
|
getProgressTimer: function (){
|
||||||
|
|
Loading…
Reference in New Issue