优化录像下载。 支持八倍速(设备支持的最高速度)下载

master
lin 2025-03-13 16:48:15 +08:00
parent 1869945ff1
commit 298fb05378
9 changed files with 65 additions and 29 deletions

View File

@ -37,6 +37,10 @@ public class InviteInfo {
private Boolean record;
private String startTime;
private String endTime;
public static InviteInfo getInviteInfo(String deviceId, Integer channelId, String stream, SSRCInfo ssrcInfo, String mediaServerId,
String receiveIp, Integer receivePort, String streamMode,

View File

@ -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.MobilePositionSubscribeTask;
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.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@ -210,6 +209,13 @@ public class DeviceQuery {
public void updateChannelStreamIdentification(DeviceChannel 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))

View File

@ -390,6 +390,7 @@ public class PlayServiceImpl implements IPlayService {
rtpServerParam.setTcpMode(tcpMode);
rtpServerParam.setOnlyAuto(false);
rtpServerParam.setDisableAudio(!channel.isHasAudio());
SSRCInfo ssrcInfo = receiveRtpServerService.openRTPServer(rtpServerParam, (code, msg, result) -> {
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(),
mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
InviteSessionStatus.ready, true);
inviteInfo.setStartTime(startTime);
inviteInfo.setEndTime(endTime);
inviteStreamService.updateInviteInfo(inviteInfo);
try {

View File

@ -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.HookType;
import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.extern.slf4j.Slf4j;
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());
subscribe.removeSubscribe(hook);
if (ssrcTransaction.getPlatformId() != null) {
// 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题需要将点播CallId进行上下级绑定
SendRtpInfo sendRtpInfo = sendRtpServerService.queryByChannelId(ssrcTransaction.getChannelId(), ssrcTransaction.getPlatformId());
if (sendRtpInfo != null) {
@ -120,6 +120,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
log.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
}
}
}
}else {
log.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息");
}

View File

@ -807,7 +807,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Override
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();
streamInfoResult.setStream(stream);
streamInfoResult.setApp(app);

View File

@ -173,9 +173,9 @@ public class MediaServiceImpl implements IMediaService {
if (ssrcTransaction.getType() == InviteSessionType.DOWNLOAD) {
// 获取录像的总时长,然后设置为这个视频的时长
InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, channelId, stream);
if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) {
String startTime = inviteInfoForDownload.getStreamInfo().getStartTime();
String endTime = inviteInfoForDownload.getStreamInfo().getEndTime();
if (inviteInfoForDownload != null) {
String startTime = inviteInfoForDownload.getStartTime();
String endTime = inviteInfoForDownload.getEndTime();
long difference = DateUtil.getDifference(startTime, endTime) / 1000;
result.setMp4_max_second((int) difference);
result.setEnable_mp4(true);

View File

@ -33,6 +33,9 @@ public final class JsonUtil {
}
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);
if (Objects.isNull(jsonObject)) {
return null;

View File

@ -65,11 +65,7 @@
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu>
<el-dropdown-item command="0.25">0.25倍速</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-item v-for="(item,index) in downloadSpeedArray" :key="index" :command="item">{{item}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
@ -115,6 +111,7 @@
return {
deviceId: this.$route.params.deviceId,
channelId: this.$route.params.channelId,
downloadSpeedArray: [0.25, 0.5, 1, 2, 4],
recordsLoading: false,
streamId: "",
hasAudio: false,
@ -184,6 +181,7 @@
this.playerBoxStyle["height"] = this.winHeight + "px";
this.chooseDate = moment().format('YYYY-MM-DD')
this.dateChange();
this.getDownloadSpeedArray()
window.addEventListener('beforeunload', this.stopPlayRecord)
},
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(){
console.log('前端控制:播放');
this.$axios({
@ -317,7 +336,7 @@
this.$axios({
method: 'get',
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)=> {
if (res.data.code === 0) {
let streamInfo = res.data.data;

View File

@ -53,6 +53,7 @@ export default {
this.showDialog = true;
this.getProgressRun = true;
this.percentage = 0.0;
this.downloadFile = null;
this.getProgressTimer()
},
getProgressTimer: function (){