添加云端录像获取视频播放地址的接口
parent
3912d0b18a
commit
ed67afb7a2
|
@ -406,4 +406,24 @@ public class ZLMRESTfulUtils {
|
|||
param.put("name", fileName);
|
||||
return sendPost(mediaServerItem, "deleteRecordDirectory",param, null);
|
||||
}
|
||||
|
||||
public JSONObject loadMP4File(MediaServerItem mediaServerItem, String app, String stream, String file_path) {
|
||||
Map<String, Object> param = new HashMap<>(1);
|
||||
param.put("vhost", "__defaultVhost__");
|
||||
param.put("app", app);
|
||||
param.put("stream", stream);
|
||||
param.put("file_path", file_path);
|
||||
param.put("file_repeat", '0');
|
||||
param.put("enable_hls", '1');
|
||||
param.put("enable_hls_fmp4", '1');
|
||||
param.put("enable_mp4", '0');
|
||||
param.put("enable_rtsp", '1');
|
||||
param.put("enable_rtmp", '1');
|
||||
param.put("enable_ts", '1');
|
||||
param.put("enable_fmp4", '1');
|
||||
param.put("enable_audio", '1');
|
||||
param.put("add_mute_audio", '1');
|
||||
param.put("auto_close", '1');
|
||||
return sendPost(mediaServerItem, "loadMP4File",param, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -56,8 +58,5 @@ public interface ICloudRecordService {
|
|||
*/
|
||||
DownloadFileInfo getPlayUrlPath(Integer recordId);
|
||||
|
||||
/**
|
||||
* 点播视频流
|
||||
*/
|
||||
DownloadFileInfo getLivePath(Integer recordId);
|
||||
void getLivePath(Integer recordId, ErrorCallback<StreamInfo> callback);
|
||||
}
|
||||
|
|
|
@ -2,16 +2,31 @@ package com.genersoft.iot.vmp.service.impl;
|
|||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionStatus;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.service.ICloudRecordService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.IMediaService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
|
||||
|
@ -25,6 +40,9 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -39,6 +57,9 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
|
|||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private IMediaService mediaService;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
|
@ -46,7 +67,13 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
|
|||
private AssistRESTfulUtils assistRESTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private VideoStreamSessionManager streamSession;
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private ZlmHttpHookSubscribe subscribe;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Override
|
||||
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {
|
||||
|
@ -239,4 +266,46 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
|
|||
MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
|
||||
return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getLivePath(Integer recordId, ErrorCallback<StreamInfo> callback) {
|
||||
CloudRecordItem recordItem = cloudRecordServiceMapper.queryOne(recordId);
|
||||
if (recordItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在");
|
||||
}
|
||||
// 监听流上线
|
||||
String app = "record-live";
|
||||
String stream = recordItem.getId() + "";
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
|
||||
if (mediaServerItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "录像记录使用的流媒体节点不在线");
|
||||
}
|
||||
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, recordItem.getMediaServerId(), false);
|
||||
if (streamInfo != null) {
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||
return;
|
||||
}
|
||||
String timeOutTaskKey = UUID.randomUUID().toString();
|
||||
dynamicTask.startDelay(timeOutTaskKey, () -> {
|
||||
// 取消订阅消息监听
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(app, stream, true, "rtsp", mediaServerItem.getId());
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "加载视频文件为视频流超时", null);
|
||||
}, 10000);
|
||||
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(app, stream, true, "rtsp", mediaServerItem.getId());
|
||||
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam;
|
||||
StreamInfo streamInfoForHook = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, streamChangedHookParam.getTracks(), null);
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfoForHook);
|
||||
});
|
||||
JSONObject jsonObject = zlmresTfulUtils.loadMP4File(mediaServerItem, app, stream, recordItem.getFilePath());
|
||||
if (jsonObject == null || jsonObject.getInteger("code") != 0) {
|
||||
subscribe.removeSubscribe(hookSubscribe);
|
||||
dynamicTask.stop(timeOutTaskKey);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(),
|
||||
jsonObject != null ? jsonObject.getString("msg"): "加载视频文件为视频流失败", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.genersoft.iot.vmp.vmanager.cloudRecord;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
|
@ -12,9 +13,7 @@ import com.genersoft.iot.vmp.service.ICloudRecordService;
|
|||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPPageInfo;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.RecordFile;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.*;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
|
@ -26,7 +25,11 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
@ -47,6 +50,9 @@ public class CloudRecordController {
|
|||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/date/list")
|
||||
|
@ -265,11 +271,32 @@ public class CloudRecordController {
|
|||
|
||||
@ResponseBody
|
||||
@GetMapping("/play/live")
|
||||
@Operation(summary = "获取点播i地址")
|
||||
@Operation(summary = "获取点播地址")
|
||||
@Parameter(name = "recordId", description = "录像记录的ID", required = true)
|
||||
public DownloadFileInfo getLivePath(
|
||||
@RequestParam(required = true) Integer recordId
|
||||
public DeferredResult<WVPResult<StreamContent>> getLivePath(
|
||||
HttpServletRequest request, @RequestParam(required = true) Integer recordId
|
||||
){
|
||||
return cloudRecordService.getLivePath(recordId);
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>();
|
||||
cloudRecordService.getLivePath(recordId, (code, msg, data) -> {
|
||||
WVPResult<StreamContent> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
if (code == ErrorCode.SUCCESS.getCode()) {
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
data=data.clone();//深拷贝
|
||||
String host;
|
||||
try {
|
||||
URL url=new URL(request.getRequestURL().toString());
|
||||
host=url.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
host=request.getLocalAddr();
|
||||
}
|
||||
data.channgeStreamIp(host);
|
||||
}
|
||||
wvpResult.setData(new StreamContent(data));
|
||||
}
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue