/device/video.mp4 改为 返回 url

This commit is contained in:
shikong 2023-10-17 11:25:41 +08:00
parent 71b75038e2
commit 9bcade0b2e
2 changed files with 46 additions and 6 deletions

View File

@ -2,6 +2,7 @@ package cn.skcks.docking.gb28181.wvp.api.video;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.skcks.docking.gb28181.common.json.JsonResponse;
import cn.skcks.docking.gb28181.media.config.ZlmMediaConfig;
import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoMp4Req;
import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoReq;
@ -25,6 +26,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.Date;
@ -60,10 +62,10 @@ public class VideoController {
}
}
@Operation(summary = "获取视频 (返回视频)")
@GetMapping(value = "/device/video.mp4",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@Operation(summary = "获取视频 (返回视频url)")
@GetMapping(value = "/device/video.mp4")
@ResponseBody
public void video(HttpServletRequest request, HttpServletResponse response, @ParameterObject VideoMp4Req req) {
public DeferredResult<JsonResponse<String>> video(@ParameterObject VideoMp4Req req) {
long forward = gb28181DeviceVideoApiConfig.getOffset().getForward().toMillis();
long back = gb28181DeviceVideoApiConfig.getOffset().getBack().toMillis();
DateTime reqStartTime = DateUtil.date(req.getStartTime());
@ -72,6 +74,6 @@ public class VideoController {
Date endTime = DateUtil.offsetMillisecond(reqEndTime, (int) back);
log.info("请求的时间范围 {} ~ {}", reqStartTime, reqEndTime);
log.info("偏移后的时间范围 {} ~ {}", startTime, endTime);
gb28181DownloadService.videoStream(request,response,req.getDeviceCode(), startTime, endTime);
return gb28181DownloadService.videoUrl(req.getDeviceCode(), startTime, endTime);
}
}

View File

@ -49,6 +49,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sdp.Connection;
import javax.sdp.SdpFactory;
@ -84,6 +85,7 @@ public class Gb28181DownloadService {
@AllArgsConstructor
@Data
public static class VideoInfo {
private String streamId;
private String url;
private String callId;
private WvpProxyDevice device;
@ -166,6 +168,42 @@ public class Gb28181DownloadService {
});
}
@SneakyThrows
public DeferredResult<JsonResponse<String>> videoUrl(String deviceCode, Date startTime, Date endTime) {
long time = DateUtil.between(startTime, endTime, DateUnit.MS);
DeferredResult<JsonResponse<String>> result = new DeferredResult<>(time);
result.onTimeout(()->{
result.setResult(JsonResponse.error("请求超时"));
});
WvpProxyDevice device = deviceService.getDeviceByDeviceCode(deviceCode).orElse(null);
if(device == null){
result.setResult(JsonResponse.error("设备不存在"));
return result;
}
WvpProxyDocking docking = dockingService.getDeviceByDeviceCode(device.getGbDeviceId()).orElse(null);
if(docking == null){
result.setResult(JsonResponse.error("设备(通道)不存在"));
return result;
}
download(deviceCode, startTime, endTime).whenComplete((videoInfo, e)->{
log.info("到达结束时间 发送 bye 关闭");
String cacheKey = CacheUtil.getKey(docking.getGbDeviceId(), device.getGbDeviceChannelId());
String existCallId = RedisUtil.StringOps.get(cacheKey);
scheduledExecutorService.schedule(()->{
String deviceIp = docking.getIp();
int devicePort = Integer.parseInt(docking.getPort());
sender.sendRequest((provider,localIp,localPort)->
SipRequestBuilder.createByeRequest(deviceIp, devicePort, device.getGbDeviceChannelId(), SipUtil.generateFromTag(), null, existCallId));
RedisUtil.KeyOps.delete(cacheKey);
zlmMediaService.closeRtpServer(CloseRtpServer.builder()
.streamId(videoInfo.streamId)
.build());
}, time, TimeUnit.MILLISECONDS);
result.setResult(JsonResponse.success(videoInfo.getUrl()));
});
return result;
}
@SneakyThrows
public void videoStream(HttpServletRequest request, HttpServletResponse response, String deviceCode, Date startTime, Date endTime) {
AsyncContext asyncContext = request.startAsync();
@ -289,7 +327,7 @@ public class Gb28181DownloadService {
SipRequestBuilder.createByeRequest(deviceIp, devicePort, device.getGbDeviceChannelId(), SipUtil.generateFromTag(), null, existCallId));
RedisUtil.KeyOps.delete(cacheKey);
log.info("关闭已存在的 点播请求 {} {}", cacheKey,existCallId);
Thread.sleep(200);
Thread.sleep(500);
}
return (provider, ip, port) -> {
@ -334,7 +372,7 @@ public class Gb28181DownloadService {
subscribe.getByeSubscribe().addSubscribe(key, byeSubscriber(key,cacheKey, streamId, time, unit));
return SipRequestBuilder.createAckRequest(Response.OK, ip, port, docking, device.getGbDeviceChannelId(), fromTag, toTag, callId);
}));
result.complete(new VideoInfo(videoUrl(streamId), callId, device));
result.complete(new VideoInfo(streamId,videoUrl(streamId), callId, device));
} else {
log.info("订阅 {} {} 连接流媒体服务时出现异常, 终止订阅", MessageProcessor.Method.INVITE, subscribeKey);
zlmMediaService.closeRtpServer(new CloseRtpServer(streamId));