支持拉流代理检索,播放

结构优化
648540858 2024-01-14 00:01:34 +08:00
parent 8805966f89
commit be011a7c85
5 changed files with 168 additions and 80 deletions

View File

@ -26,7 +26,7 @@ public interface IStreamProxyService {
* @param count * @param count
* @return * @return
*/ */
PageInfo<StreamProxy> getAll(Integer page, Integer count); PageInfo<StreamProxy> getAll(String query, Boolean online, String mediaServerId, Integer page, Integer count);
/** /**
@ -109,4 +109,10 @@ public interface IStreamProxyService {
* *
*/ */
void edit(StreamProxy param, GeneralCallback<StreamInfo> callback); void edit(StreamProxy param, GeneralCallback<StreamInfo> callback);
/**
*
*/
void getStreamProxyById(Integer id, GeneralCallback<StreamInfo> callback);
} }

View File

@ -34,9 +34,11 @@ import com.github.pagehelper.PageInfo;
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.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionDefinition;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -97,6 +99,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
@Autowired @Autowired
TransactionDefinition transactionDefinition; TransactionDefinition transactionDefinition;
@Qualifier("taskExecutor")
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Override @Override
@Transactional @Transactional
@ -164,16 +170,22 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> { hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> {
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, param.getApp(), param.getStream(), null, null); mediaInfo, param.getApp(), param.getStream(), null, null);
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
}
}); });
if (param.isEnable()) { if (param.isEnable()) {
startProxy(param, mediaInfo, (code, msg, data) -> { startProxy(param, mediaInfo, (code, msg, data) -> {
if (code != ErrorCode.SUCCESS.getCode()) { if (code != ErrorCode.SUCCESS.getCode()) {
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data);
}
param.setStatus(true); param.setStatus(true);
streamProxyMapper.update(param); streamProxyMapper.update(param);
}else { }else {
if (callback != null) {
callback.run(code, msg, null); callback.run(code, msg, null);
}
param.setEnable(false); param.setEnable(false);
// 直接移除 // 直接移除
if (param.isEnableRemoveNoneReader()) { if (param.isEnableRemoveNoneReader()) {
@ -186,9 +198,11 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} else{ } else{
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, param.getApp(), param.getStream(), null, null); mediaInfo, param.getApp(), param.getStream(), null, null);
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
} }
} }
}
@Override @Override
@Transactional @Transactional
@ -211,14 +225,13 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} }
if (!param.isEnable()) { if (!param.isEnable()) {
param.setStatus(false); param.setStatus(false);
addProxyToDb(param);
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, param.getApp(), param.getStream(), null, null);
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
return;
} }
addProxyToDb(param);
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
}
taskExecutor.execute(()->{
startProxy(param, mediaInfo, (code, msg, data) -> { startProxy(param, mediaInfo, (code, msg, data) -> {
callback.run(code, msg, data);
if (code == ErrorCode.SUCCESS.getCode()) { if (code == ErrorCode.SUCCESS.getCode()) {
param.setStatus(true); param.setStatus(true);
} else { } else {
@ -230,6 +243,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} }
addProxyToDb(param); addProxyToDb(param);
}); });
});
} }
@Override @Override
@ -251,6 +265,11 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} }
proxyParamHandler(param); proxyParamHandler(param);
param.setMediaServerId(mediaInfo.getId()); param.setMediaServerId(mediaInfo.getId());
updateProxyToDb(param);
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
}
taskExecutor.execute(()->{
// 国标编号发生变化,修改通用通道国标变化,通用通道应发送删除再发送添加命令通知上级 // 国标编号发生变化,修改通用通道国标变化,通用通道应发送删除再发送添加命令通知上级
// 类型变化,启用->启用:需要重新拉起视频流, 启用->未启用: 停止旧的视频流, 未启用->启用:发起新的视频流 // 类型变化,启用->启用:需要重新拉起视频流, 启用->未启用: 停止旧的视频流, 未启用->启用:发起新的视频流
// 流地址发生变化。停止旧的,拉起新的 // 流地址发生变化。停止旧的,拉起新的
@ -278,14 +297,11 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
param.setProxyError(msg); param.setProxyError(msg);
} }
updateProxyToDb(param); updateProxyToDb(param);
callback.run(code, msg, null);
}; };
if(stopOldProxy) { if(stopOldProxy) {
stopProxy(param, mediaInfo, (code, msg, data) -> { stopProxy(param, mediaInfo, (code, msg, data) -> {
if (param.isEnable()) { if (param.isEnable()) {
startProxy(param, mediaInfo, startProxyCallback); startProxy(param, mediaInfo, startProxyCallback);
}else {
callback.run(code, msg, null);
} }
}); });
}else { }else {
@ -294,9 +310,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
}else { }else {
param.setStatus(false); param.setStatus(false);
updateProxyToDb(param); updateProxyToDb(param);
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
} }
} }
});
} }
public void startProxy(StreamProxy streamProxy, MediaServerItem mediaInfo, GeneralCallback<StreamInfo> callback) { public void startProxy(StreamProxy streamProxy, MediaServerItem mediaInfo, GeneralCallback<StreamInfo> callback) {
@ -316,8 +332,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, streamProxy.getApp(), streamProxy.getStream(), null, null); mediaInfo, streamProxy.getApp(), streamProxy.getStream(), null, null);
logger.info("[开始拉流代理] 已拉起,直接返回 {}/{}", streamProxy.getApp(), streamProxy.getStream()); logger.info("[开始拉流代理] 已拉起,直接返回 {}/{}", streamProxy.getApp(), streamProxy.getStream());
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
} }
}
return; return;
} }
String delayTalkKey = UUID.randomUUID().toString(); String delayTalkKey = UUID.randomUUID().toString();
@ -329,13 +347,17 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
mediaInfo, streamProxy.getApp(), streamProxy.getStream(), null, null); mediaInfo, streamProxy.getApp(), streamProxy.getStream(), null, null);
logger.info("[开始拉流代理] 成功: {}/{}", streamProxy.getApp(), streamProxy.getStream()); logger.info("[开始拉流代理] 成功: {}/{}", streamProxy.getApp(), streamProxy.getStream());
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
}
}); });
dynamicTask.startDelay(delayTalkKey, ()->{ dynamicTask.startDelay(delayTalkKey, ()->{
hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); hookSubscribe.removeSubscribe(hookSubscribeForStreamChange);
dynamicTask.stop(delayTalkKey); dynamicTask.stop(delayTalkKey);
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "启用超时,请检查源地址是否可用", null); callback.run(ErrorCode.ERROR100.getCode(), "启用超时,请检查源地址是否可用", null);
}
streamProxy.setProxyError("启用超时"); streamProxy.setProxyError("启用超时");
}, 10000); }, 10000);
JSONObject result; JSONObject result;
@ -348,24 +370,32 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
streamProxy.isEnableAudio(), streamProxy.isEnableMp4(), streamProxy.getRtpType()); streamProxy.isEnableAudio(), streamProxy.isEnableMp4(), streamProxy.getRtpType());
} }
if (result == null) { if (result == null) {
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "接口调用失败", null); callback.run(ErrorCode.ERROR100.getCode(), "接口调用失败", null);
}
return; return;
} }
if (result.getInteger("code") != 0) { if (result.getInteger("code") != 0) {
hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); hookSubscribe.removeSubscribe(hookSubscribeForStreamChange);
dynamicTask.stop(delayTalkKey); dynamicTask.stop(delayTalkKey);
if (callback != null) {
callback.run(result.getInteger("code"), result.getString("msg"), null); callback.run(result.getInteger("code"), result.getString("msg"), null);
}
}else { }else {
JSONObject data = result.getJSONObject("data"); JSONObject data = result.getJSONObject("data");
if (data == null) { if (data == null) {
logger.warn("[获取拉流代理的结果数据Data] 失败: {}", result ); logger.warn("[获取拉流代理的结果数据Data] 失败: {}", result );
if (callback != null) {
callback.run(result.getInteger("code"), result.getString("msg"), null); callback.run(result.getInteger("code"), result.getString("msg"), null);
}
return; return;
} }
String key = data.getString("key"); String key = data.getString("key");
if (key == null) { if (key == null) {
logger.warn("[获取拉流代理的结果数据Data中的KEY] 失败: {}", result ); logger.warn("[获取拉流代理的结果数据Data中的KEY] 失败: {}", result );
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "获取代理流结果中的KEY失败", null); callback.run(ErrorCode.ERROR100.getCode(), "获取代理流结果中的KEY失败", null);
}
return; return;
} }
streamProxy.setStreamKey(key); streamProxy.setStreamKey(key);
@ -392,8 +422,10 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
redisTemplate.delete(key); redisTemplate.delete(key);
} }
logger.info("[停止拉流代理] 成功 {}/{}", streamProxy.getApp(), streamProxy.getStream()); logger.info("[停止拉流代理] 成功 {}/{}", streamProxy.getApp(), streamProxy.getStream());
if (callback != null) {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
} }
}
public void proxyParamHandler(StreamProxy param) { public void proxyParamHandler(StreamProxy param) {
if ("ffmpeg".equalsIgnoreCase(param.getType())) { if ("ffmpeg".equalsIgnoreCase(param.getType())) {
@ -497,9 +529,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} }
@Override @Override
public PageInfo<StreamProxy> getAll(Integer page, Integer count) { public PageInfo<StreamProxy> getAll(String query, Boolean online, String mediaServerId, Integer page, Integer count) {
PageHelper.startPage(page, count); PageHelper.startPage(page, count);
List<StreamProxy> all = streamProxyMapper.selectAll(); List<StreamProxy> all = streamProxyMapper.selectAll(query, online, mediaServerId);
return new PageInfo<>(all); return new PageInfo<>(all);
} }
@ -546,13 +578,17 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
public void start(String app, String stream, GeneralCallback<StreamInfo> callback) { public void start(String app, String stream, GeneralCallback<StreamInfo> callback) {
StreamProxy streamProxy = streamProxyMapper.selectOne(app, stream); StreamProxy streamProxy = streamProxyMapper.selectOne(app, stream);
if (streamProxy == null || !streamProxy.isEnable()){ if (streamProxy == null || !streamProxy.isEnable()){
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "代理不存在或未启用", null); callback.run(ErrorCode.ERROR100.getCode(), "代理不存在或未启用", null);
}
return; return;
} }
String mediaServerId = streamProxy.getMediaServerId(); String mediaServerId = streamProxy.getMediaServerId();
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem == null) { if (mediaServerItem == null) {
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "使用的媒体节点不存在", null); callback.run(ErrorCode.ERROR100.getCode(), "使用的媒体节点不存在", null);
}
return; return;
} }
startProxy(streamProxy, mediaServerItem, (code, msg, data) -> { startProxy(streamProxy, mediaServerItem, (code, msg, data) -> {
@ -563,7 +599,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
} }
streamProxy.setUpdateTime(DateUtil.getNow()); streamProxy.setUpdateTime(DateUtil.getNow());
updateProxyToDb(streamProxy); updateProxyToDb(streamProxy);
if (callback != null) {
callback.run(code, msg, data); callback.run(code, msg, data);
}
}); });
} }
@ -572,20 +610,26 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
public void stop(String app, String stream, GeneralCallback<StreamInfo> callback) { public void stop(String app, String stream, GeneralCallback<StreamInfo> callback) {
StreamProxy streamProxy = streamProxyMapper.selectOne(app, stream); StreamProxy streamProxy = streamProxyMapper.selectOne(app, stream);
if (streamProxy == null || !streamProxy.isEnable()){ if (streamProxy == null || !streamProxy.isEnable()){
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "代理不存在或未启用", null); callback.run(ErrorCode.ERROR100.getCode(), "代理不存在或未启用", null);
}
return; return;
} }
String mediaServerId = streamProxy.getMediaServerId(); String mediaServerId = streamProxy.getMediaServerId();
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem == null) { if (mediaServerItem == null) {
if (callback != null) {
callback.run(ErrorCode.ERROR100.getCode(), "使用的媒体节点不存在", null); callback.run(ErrorCode.ERROR100.getCode(), "使用的媒体节点不存在", null);
}
return; return;
} }
stopProxy(streamProxy, mediaServerItem, (code, msg, data) -> { stopProxy(streamProxy, mediaServerItem, (code, msg, data) -> {
streamProxy.setStatus(false); streamProxy.setStatus(false);
streamProxy.setUpdateTime(DateUtil.getNow()); streamProxy.setUpdateTime(DateUtil.getNow());
updateProxyToDb(streamProxy); updateProxyToDb(streamProxy);
if (callback != null) {
callback.run(code, msg, data); callback.run(code, msg, data);
}
}); });
} }
@ -820,4 +864,17 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
return streamProxyMapper.selectForEnable(true); return streamProxyMapper.selectForEnable(true);
} }
@Override
public void getStreamProxyById(Integer id, GeneralCallback<StreamInfo> callback) {
assert id != null;
StreamProxy streamProxy = streamProxyMapper.selectOneById(id);
assert streamProxy != null;
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(
streamProxy.getApp(), streamProxy.getStream(), streamProxy.getMediaServerId(), false);
if (streamInfo == null) {
callback.run(ErrorCode.ERROR100.getCode(), "地址获取失败", null);
}else {
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
}
}
} }

View File

@ -107,7 +107,7 @@ public interface DeviceChannelMapper {
"wvp_device_channel dc " + "wvp_device_channel dc " +
"WHERE " + "WHERE " +
"dc.device_id = #{deviceId} " + "dc.device_id = #{deviceId} " +
" <if test='query != null'> AND (dc.channel_id LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " + " <if test='query != null'> AND (dc.channel_id LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='parentChannelId != null'> AND (dc.parent_id=#{parentChannelId} OR dc.civil_code = #{parentChannelId}) </if> " + " <if test='parentChannelId != null'> AND (dc.parent_id=#{parentChannelId} OR dc.civil_code = #{parentChannelId}) </if> " +
" <if test='online == true' > AND dc.status= true</if>" + " <if test='online == true' > AND dc.status= true</if>" +
" <if test='online == false' > AND dc.status= false</if>" + " <if test='online == false' > AND dc.status= false</if>" +

View File

@ -47,8 +47,17 @@ public interface StreamProxyMapper {
@Delete("DELETE FROM wvp_stream_proxy WHERE app=#{app} AND stream=#{stream}") @Delete("DELETE FROM wvp_stream_proxy WHERE app=#{app} AND stream=#{stream}")
int del(String app, String stream); int del(String app, String stream);
@Select("SELECT * FROM wvp_stream_proxy order by create_time desc") @Select(" <script>" +
List<StreamProxy> selectAll(); "SELECT * FROM wvp_stream_proxy where 1 = 1 " +
" <if test='query != null'> AND (app LIKE '%${query}%' OR stream LIKE '%${query}%' OR name LIKE '%${query}%')</if> " +
" <if test='mediaServerId != null'> AND media_server_id=#{mediaServerId}</if> " +
" <if test='online == true' > AND status=true</if>" +
" <if test='online == false' > AND status=false</if>" +
"order by create_time desc"+
" </script>" )
List<StreamProxy> selectAll(@Param("query") String query,
@Param("online") Boolean online,
@Param("mediaServerId") String mediaServerId);
@Select("SELECT st.* FROM wvp_stream_proxy st WHERE st.enable=#{enable} order by st.create_time desc") @Select("SELECT st.* FROM wvp_stream_proxy st WHERE st.enable=#{enable} order by st.create_time desc")
List<StreamProxy> selectForEnable(boolean enable); List<StreamProxy> selectForEnable(boolean enable);

View File

@ -56,14 +56,16 @@ public class StreamProxyController {
@Parameter(name = "count", description = "每页查询数量") @Parameter(name = "count", description = "每页查询数量")
@Parameter(name = "query", description = "查询内容") @Parameter(name = "query", description = "查询内容")
@Parameter(name = "online", description = "是否在线") @Parameter(name = "online", description = "是否在线")
@Parameter(name = "mediaServerId", description = "节点ID")
@GetMapping(value = "/list") @GetMapping(value = "/list")
@ResponseBody @ResponseBody
public PageInfo<StreamProxy> list(@RequestParam(required = false)Integer page, public PageInfo<StreamProxy> list(@RequestParam(required = false)Integer page,
@RequestParam(required = false)Integer count, @RequestParam(required = false)Integer count,
@RequestParam(required = false)String query, @RequestParam(required = false)String query,
@RequestParam(required = false)String mediaServerId,
@RequestParam(required = false)Boolean online ){ @RequestParam(required = false)Boolean online ){
return streamProxyService.getAll(page, count); return streamProxyService.getAll(query, online, mediaServerId, page, count);
} }
@Operation(summary = "查询流代理", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Operation(summary = "查询流代理", security = @SecurityRequirement(name = JwtUtils.HEADER))
@ -277,4 +279,18 @@ public class StreamProxyController {
}); });
return result; return result;
} }
@GetMapping(value = "/stream")
@ResponseBody
@Operation(summary = "获取代理播放地址", security = @SecurityRequirement(name = JwtUtils.HEADER))
@Parameter(name = "id", description = "ID", required = true)
public DeferredResult<WVPResult<StreamContent>> getStream(Integer id){
logger.info("获取代理播放地址: " + id );
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
streamProxyService.getStreamProxyById(id, (code, msg, data) -> {
WVPResult<StreamContent> wvpResult = new WVPResult<>(code, msg, new StreamContent(data));
result.setResult(wvpResult);
});
return result;
}
} }