/device/video.mp4 改为 返回 url
This commit is contained in:
parent
71b75038e2
commit
9bcade0b2e
@ -2,6 +2,7 @@ package cn.skcks.docking.gb28181.wvp.api.video;
|
|||||||
|
|
||||||
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateTime;
|
||||||
import cn.hutool.core.date.DateUtil;
|
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.media.config.ZlmMediaConfig;
|
||||||
import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoMp4Req;
|
import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoMp4Req;
|
||||||
import cn.skcks.docking.gb28181.wvp.api.video.dto.VideoReq;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -60,10 +62,10 @@ public class VideoController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取视频 (返回视频流)")
|
@Operation(summary = "获取视频 (返回视频url)")
|
||||||
@GetMapping(value = "/device/video.mp4",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
@GetMapping(value = "/device/video.mp4")
|
||||||
@ResponseBody
|
@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 forward = gb28181DeviceVideoApiConfig.getOffset().getForward().toMillis();
|
||||||
long back = gb28181DeviceVideoApiConfig.getOffset().getBack().toMillis();
|
long back = gb28181DeviceVideoApiConfig.getOffset().getBack().toMillis();
|
||||||
DateTime reqStartTime = DateUtil.date(req.getStartTime());
|
DateTime reqStartTime = DateUtil.date(req.getStartTime());
|
||||||
@ -72,6 +74,6 @@ public class VideoController {
|
|||||||
Date endTime = DateUtil.offsetMillisecond(reqEndTime, (int) back);
|
Date endTime = DateUtil.offsetMillisecond(reqEndTime, (int) back);
|
||||||
log.info("请求的时间范围 {} ~ {}", reqStartTime, reqEndTime);
|
log.info("请求的时间范围 {} ~ {}", reqStartTime, reqEndTime);
|
||||||
log.info("偏移后的时间范围 {} ~ {}", startTime, endTime);
|
log.info("偏移后的时间范围 {} ~ {}", startTime, endTime);
|
||||||
gb28181DownloadService.videoStream(request,response,req.getDeviceCode(), startTime, endTime);
|
return gb28181DownloadService.videoUrl(req.getDeviceCode(), startTime, endTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
import javax.sdp.Connection;
|
import javax.sdp.Connection;
|
||||||
import javax.sdp.SdpFactory;
|
import javax.sdp.SdpFactory;
|
||||||
@ -84,6 +85,7 @@ public class Gb28181DownloadService {
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Data
|
@Data
|
||||||
public static class VideoInfo {
|
public static class VideoInfo {
|
||||||
|
private String streamId;
|
||||||
private String url;
|
private String url;
|
||||||
private String callId;
|
private String callId;
|
||||||
private WvpProxyDevice device;
|
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
|
@SneakyThrows
|
||||||
public void videoStream(HttpServletRequest request, HttpServletResponse response, String deviceCode, Date startTime, Date endTime) {
|
public void videoStream(HttpServletRequest request, HttpServletResponse response, String deviceCode, Date startTime, Date endTime) {
|
||||||
AsyncContext asyncContext = request.startAsync();
|
AsyncContext asyncContext = request.startAsync();
|
||||||
@ -289,7 +327,7 @@ public class Gb28181DownloadService {
|
|||||||
SipRequestBuilder.createByeRequest(deviceIp, devicePort, device.getGbDeviceChannelId(), SipUtil.generateFromTag(), null, existCallId));
|
SipRequestBuilder.createByeRequest(deviceIp, devicePort, device.getGbDeviceChannelId(), SipUtil.generateFromTag(), null, existCallId));
|
||||||
RedisUtil.KeyOps.delete(cacheKey);
|
RedisUtil.KeyOps.delete(cacheKey);
|
||||||
log.info("关闭已存在的 点播请求 {} {}", cacheKey,existCallId);
|
log.info("关闭已存在的 点播请求 {} {}", cacheKey,existCallId);
|
||||||
Thread.sleep(200);
|
Thread.sleep(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (provider, ip, port) -> {
|
return (provider, ip, port) -> {
|
||||||
@ -334,7 +372,7 @@ public class Gb28181DownloadService {
|
|||||||
subscribe.getByeSubscribe().addSubscribe(key, byeSubscriber(key,cacheKey, streamId, time, unit));
|
subscribe.getByeSubscribe().addSubscribe(key, byeSubscriber(key,cacheKey, streamId, time, unit));
|
||||||
return SipRequestBuilder.createAckRequest(Response.OK, ip, port, docking, device.getGbDeviceChannelId(), fromTag, toTag, callId);
|
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 {
|
} else {
|
||||||
log.info("订阅 {} {} 连接流媒体服务时出现异常, 终止订阅", MessageProcessor.Method.INVITE, subscribeKey);
|
log.info("订阅 {} {} 连接流媒体服务时出现异常, 终止订阅", MessageProcessor.Method.INVITE, subscribeKey);
|
||||||
zlmMediaService.closeRtpServer(new CloseRtpServer(streamId));
|
zlmMediaService.closeRtpServer(new CloseRtpServer(streamId));
|
||||||
|
Loading…
Reference in New Issue
Block a user