优化快照的存储与显示

pull/517/head
648540858 2022-06-02 10:55:41 +08:00
parent 936adf31fe
commit 9ae0691c80
5 changed files with 63 additions and 57 deletions

View File

@ -91,10 +91,9 @@ public class ZLMHttpHookListener {
public ResponseEntity<String> onServerKeepalive(@RequestBody JSONObject json){ public ResponseEntity<String> onServerKeepalive(@RequestBody JSONObject json){
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("[ ZLM HOOK ]on_server_keepalive API调用参数" + json.toString()); logger.debug("[ ZLM HOOK ] on_server_keepalive API调用参数" + json.toString());
} }
String mediaServerId = json.getString("mediaServerId"); String mediaServerId = json.getString("mediaServerId");
List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_keepalive); List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_keepalive);
if (subscribes != null && subscribes.size() > 0) { if (subscribes != null && subscribes.size() > 0) {
for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
@ -164,7 +163,6 @@ public class ZLMHttpHookListener {
if (mediaInfo != null) { if (mediaInfo != null) {
subscribe.response(mediaInfo, json); subscribe.response(mediaInfo, json);
} }
} }
JSONObject ret = new JSONObject(); JSONObject ret = new JSONObject();
ret.put("code", 0); ret.put("code", 0);

View File

@ -151,7 +151,7 @@ public class ZLMRESTfulUtils {
} }
} }
File snapFile = new File(targetPath + "/" + fileName); File snapFile = new File(targetPath + File.separator + fileName);
FileOutputStream outStream = new FileOutputStream(snapFile); FileOutputStream outStream = new FileOutputStream(snapFile);
outStream.write(Objects.requireNonNull(response.body()).bytes()); outStream.write(Objects.requireNonNull(response.body()).bytes());

View File

@ -123,36 +123,19 @@ public class PlayServiceImpl implements IPlayService {
result.onCompletion(()->{ result.onCompletion(()->{
// 点播结束时调用截图接口 // 点播结束时调用截图接口
// TODO 应该在上流时调用更好,结束也可能是错误结束 // TODO 应该在上流时调用更好,结束也可能是错误结束
try { String path = "snap";
String classPath = ResourceUtils.getURL("classpath:").getPath(); String fileName = deviceId + "_" + channelId + ".jpg";
// 兼容打包为jar的class路径 ResponseEntity responseEntity = (ResponseEntity)result.getResult();
if(classPath.contains("jar")) { if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
classPath = classPath.substring(0, classPath.lastIndexOf(".")); WVPResult wvpResult = (WVPResult)responseEntity.getBody();
classPath = classPath.substring(0, classPath.lastIndexOf("/") + 1); if (Objects.requireNonNull(wvpResult).getCode() == 0) {
StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
String streamUrl = streamInfoForSuccess.getFmp4();
// 请求截图
logger.info("[请求截图]: " + fileName);
zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
} }
if (classPath.startsWith("file:")) {
classPath = classPath.substring(classPath.indexOf(":") + 1);
}
String path = classPath + "static/static/snap/";
// 兼容Windows系统路径去除前面的“/”)
if(System.getProperty("os.name").contains("indows")) {
path = path.substring(1);
}
String fileName = deviceId + "_" + channelId + ".jpg";
ResponseEntity responseEntity = (ResponseEntity)result.getResult();
if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
WVPResult wvpResult = (WVPResult)responseEntity.getBody();
if (Objects.requireNonNull(wvpResult).getCode() == 0) {
StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
String streamUrl = streamInfoForSuccess.getFmp4();
// 请求截图
logger.info("[请求截图]: " + fileName);
zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} }
}); });
if (streamInfo != null) { if (streamInfo != null) {

View File

@ -21,16 +21,22 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.http.HttpResponse;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import javax.servlet.http.HttpServletResponse;
import javax.sip.DialogState; import javax.sip.DialogState;
import java.io.*;
import java.nio.file.Files;
import java.util.*; import java.util.*;
@Api(tags = "国标设备查询", value = "国标设备查询") @Api(tags = "国标设备查询", value = "国标设备查询")
@ -456,4 +462,17 @@ public class DeviceQuery {
wvpResult.setData(dialogStateMap); wvpResult.setData(dialogStateMap);
return wvpResult; return wvpResult;
} }
@GetMapping("/snap/{deviceId}/{channelId}")
@ApiOperation(value = "请求截图", notes = "请求截图")
public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId) {
try {
final InputStream in = Files.newInputStream(new File("snap" + File.separator + deviceId + "_" + channelId + ".jpg").toPath());
resp.setContentType(MediaType.IMAGE_PNG_VALUE);
IOUtils.copy(in, resp.getOutputStream());
} catch (IOException e) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
}
} }

View File

@ -39,21 +39,22 @@
</el-table-column> </el-table-column>
<el-table-column label="快照" width="80" align="center"> <el-table-column label="快照" width="80" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<img style="max-height: 3rem;max-width: 4rem;" <!-- <img style="max-height: 3rem;max-width: 4rem;"-->
v-if="scope.row.subCount === 0 && scope.row.parental === 0" <!-- v-if="scope.row.subCount === 0 && scope.row.parental === 0"-->
:id="scope.row.deviceId + '_' + scope.row.channelId" <!-- :deviceId="scope.row.deviceId"-->
:src="getSnap(scope.row)" <!-- :channelId="scope.row.channelId"-->
@error="getSnapErrorEvent($event.target.id)" <!-- :src="getSnap(scope.row)"-->
alt=""> <!-- @error="getSnapErrorEvent($event.target.deviceId, $event.target.channelId)"-->
<!-- <el-image--> <!-- alt="">-->
<!-- :id="'snapImg_' + scope.row.deviceId + '_' + scope.row.channelId"--> <el-image
<!-- :src="getSnap(scope.row)"--> :src="getSnap(scope.row)"
<!-- @error="getSnapErrorEvent($event, scope.row)"--> :preview-src-list="getBigSnap(scope.row)"
<!-- :fit="'contain'">--> @error="getSnapErrorEvent(scope.row.deviceId, cope.row.channelId)"
<!-- <div slot="error" class="image-slot">--> :fit="'contain'">
<!-- <i class="el-icon-picture-outline"></i>--> <div slot="error" class="image-slot">
<!-- </div>--> <i class="el-icon-picture-outline"></i>
<!-- </el-image>--> </div>
</el-image>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="subCount" label="子节点数"> <el-table-column prop="subCount" label="子节点数">
@ -227,7 +228,7 @@ export default {
setTimeout(() => { setTimeout(() => {
let snapId = deviceId + "_" + channelId; let snapId = deviceId + "_" + channelId;
that.loadSnap[snapId] = 0; that.loadSnap[deviceId + channelId] = 0;
that.getSnapErrorEvent(snapId) that.getSnapErrorEvent(snapId)
}, 5000) }, 5000)
that.$refs.devicePlayer.openDialog("media", deviceId, channelId, { that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
@ -269,19 +270,24 @@ export default {
}); });
}, },
getSnap: function (row) { getSnap: function (row) {
return '/static/snap/' + row.deviceId + '_' + row.channelId + '.jpg' let url = (process.env.NODE_ENV === 'development'? "debug": "") + '/api/device/query/snap/' + row.deviceId + '/' + row.channelId
return url
}, },
getSnapErrorEvent: function (id) { getBigSnap: function (row) {
return [this.getSnap(row)]
},
getSnapErrorEvent: function (deviceId, channelId) {
if (typeof (this.loadSnap[id]) != "undefined") { if (typeof (this.loadSnap[deviceId + channelId]) != "undefined") {
console.log("下载截图" + this.loadSnap[id]) console.log("下载截图" + this.loadSnap[deviceId + channelId])
if (this.loadSnap[id] > 5) { if (this.loadSnap[deviceId + channelId] > 5) {
delete this.loadSnap[id]; delete this.loadSnap[deviceId + channelId];
return; return;
} }
setTimeout(() => { setTimeout(() => {
this.loadSnap[id]++ let url = (process.env.NODE_ENV === 'development'? "debug": "") + '/api/device/query/snap/' + deviceId + '/' + channelId
document.getElementById(id).setAttribute("src", '/static/snap/' + id + '.jpg?' + new Date().getTime()) this.loadSnap[deviceId + channelId]++
document.getElementById(deviceId + channelId).setAttribute("src", url + '?' + new Date().getTime())
}, 1000) }, 1000)
} }