|
|
@@ -0,0 +1,794 @@
|
|
|
+package com.chuanghai.video.controller;
|
|
|
+
|
|
|
+import com.alibaba.fastjson2.JSONArray;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.chuanghai.video.core.ResponseResult;
|
|
|
+import com.chuanghai.video.entity.Camera;
|
|
|
+import com.chuanghai.video.entity.Config;
|
|
|
+import com.chuanghai.video.entity.Player;
|
|
|
+import com.chuanghai.video.entity.Spot;
|
|
|
+import com.chuanghai.video.mapper.CameraMapper;
|
|
|
+import com.chuanghai.video.mapper.VideoMapper;
|
|
|
+import com.chuanghai.video.util.OkHttpUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/stream")
|
|
|
+public class VideoController {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CameraMapper cameraMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private VideoMapper videoMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 使用Stream推拉流
|
|
|
+ *
|
|
|
+ * @param camera 监控对象
|
|
|
+ * @return 响应对象
|
|
|
+ */
|
|
|
+ @PostMapping("/addStreamSource")
|
|
|
+ public ResponseResult requestAddStreamSource(@RequestBody Camera camera) {
|
|
|
+ // 检测参数
|
|
|
+ String d = camera.getD();
|
|
|
+ String tNowLine = camera.getNowLine();
|
|
|
+ if (d == null || tNowLine == null)
|
|
|
+ return ResponseResult.failed("【通道】或【当前线路】参数为空!");
|
|
|
+
|
|
|
+ List<Camera> list = cameraMapper.list(camera);
|
|
|
+ if (list.size() < 1)
|
|
|
+ return ResponseResult.failed("没有【通道】对应的监控!");
|
|
|
+
|
|
|
+ if (list.get(0).getChannel() == null || list.get(0).getChannel().equals(""))
|
|
|
+ return ResponseResult.failed("【频道】不存在!");
|
|
|
+
|
|
|
+ int nowLine = Integer.parseInt(tNowLine);
|
|
|
+ if (nowLine != 1 && nowLine != 2)
|
|
|
+ return ResponseResult.failed("【当前线路】只能为1或2!");
|
|
|
+
|
|
|
+ String vendor = list.get(0).getVendor();
|
|
|
+ String streamId = list.get(0).getChannel().toLowerCase() + "_" + nowLine;
|
|
|
+
|
|
|
+ String baseUrl = "", baseUrl_ws = "", secret = "", vhost = "", port = "";
|
|
|
+ String urlMp4, urlMp4_ws, urlFlv, urlFlv_ws, urlHls, urlTs, urlTs_ws;
|
|
|
+ StringBuilder videoLinks = new StringBuilder();
|
|
|
+ List<Config> return_config = videoMapper.getConfig();
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ if (return_config.size() > 0) {
|
|
|
+ for (Config cfg : return_config) {
|
|
|
+ // 监控视频拉流的基础url:baseUrl
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "baseUrl".equals(cfg.getCfgName())) {
|
|
|
+ baseUrl = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流需要的秘钥
|
|
|
+ if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
|
|
|
+ secret = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
|
|
|
+ vhost = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机端口
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
|
|
|
+ port = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ if ("protocol".equals(cfg.getCfgClass()) && "enable_hls".equals(cfg.getCfgName())) {
|
|
|
+ if ("1".equals(cfg.getCfgValue())) {
|
|
|
+ urlHls = "/live/" + streamId + "/hls.m3u8";
|
|
|
+ map.put("hls", urlHls);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 是否开启转换为rtmp/flv
|
|
|
+ if ("protocol".equals(cfg.getCfgClass()) && "enable_rtmp".equals(cfg.getCfgName())) {
|
|
|
+ if ("1".equals(cfg.getCfgValue())) {
|
|
|
+ urlFlv = "/live/" + streamId + ".live.flv";
|
|
|
+ urlFlv_ws = "/live/" + streamId + ".live.flv";
|
|
|
+ map.put("flv", urlFlv);
|
|
|
+ map.put("flv_ws", urlFlv_ws);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 是否开启转换为http-ts/ws-ts
|
|
|
+ if ("protocol".equals(cfg.getCfgClass()) && "enable_ts".equals(cfg.getCfgName())) {
|
|
|
+ if ("1".equals(cfg.getCfgValue())) {
|
|
|
+ urlTs = "/live/" + streamId + ".live.ts";
|
|
|
+ urlTs_ws = "/live/" + streamId + ".live.ts";
|
|
|
+ map.put("ts", urlTs);
|
|
|
+ map.put("ts_ws", urlTs_ws);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 是否开启转换为http-fmp4/ws-fmp4
|
|
|
+ if ("protocol".equals(cfg.getCfgClass()) && "enable_fmp4".equals(cfg.getCfgName())) {
|
|
|
+ if ("1".equals(cfg.getCfgValue())) {
|
|
|
+ urlMp4 = "/live/" + streamId + ".live.mp4";
|
|
|
+ urlMp4_ws = "/live/" + streamId + ".live.mp4";
|
|
|
+ map.put("mp4", urlMp4);
|
|
|
+ map.put("mp4_ws", urlMp4_ws);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 是否开启转换为hls(mpegts)
|
|
|
+ if (baseUrl == null || "".equals(baseUrl.trim())) {
|
|
|
+ baseUrl = "http://" + vhost + ":" + port;
|
|
|
+ baseUrl_ws = "ws://" + vhost + ":" + port;
|
|
|
+ } else {
|
|
|
+ if (baseUrl.startsWith("https")) {
|
|
|
+ baseUrl_ws = "wss://" + baseUrl.substring(8);
|
|
|
+ } else {
|
|
|
+ baseUrl_ws = "ws://" + baseUrl.substring(8);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历map,并根据条件更新每个值
|
|
|
+ for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ String newValue;
|
|
|
+ if (key.contains("ws")) {
|
|
|
+ newValue = baseUrl_ws + entry.getValue();
|
|
|
+ } else {
|
|
|
+ newValue = baseUrl + entry.getValue();
|
|
|
+ }
|
|
|
+ entry.setValue(newValue);
|
|
|
+ videoLinks.append(key).append(":").append(newValue).append(",");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!"".contentEquals(videoLinks)) {
|
|
|
+ videoLinks.setLength(videoLinks.length() - 1);
|
|
|
+ //map.put("videoLinks", videoLinks);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取nvr的ip和账号密码
|
|
|
+ int spot = Integer.parseInt(list.get(0).getSpot());
|
|
|
+ List<Spot> return_spot = cameraMapper.getSpotInfo(spot);
|
|
|
+ String nvr_ip = return_spot.get(0).getNvrIp();
|
|
|
+ // 监控账号密码
|
|
|
+ String ipPassword = return_spot.get(0).getIpPassword();
|
|
|
+
|
|
|
+// if ("".equals(baseUrl)) return ResponseResult.failed("配置表中没有配置基础URL:baseUrl");
|
|
|
+ if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
|
|
|
+ if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
|
|
|
+ if ("".equals(nvr_ip)) return ResponseResult.failed("配置表中没有配置nvr主机:nvr_ip");
|
|
|
+ if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
|
|
|
+
|
|
|
+ //视频推拉流服务
|
|
|
+ String url;
|
|
|
+ if ("华为".equals(vendor)) {
|
|
|
+ url = "rtsp://" + ipPassword + "@" + nvr_ip + "/LiveMedia/ch1/Media" + nowLine;
|
|
|
+ } else {
|
|
|
+ url = "rtsp://" + ipPassword + "@" + nvr_ip + "/Streaming/Channels/" + list.get(0).getChannel().substring(1) +
|
|
|
+ "0" + nowLine + "?transportmode=unicast";
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 拉流接口
|
|
|
+ String uri = "http://" + vhost + ":" + port + "/index/api/addStreamProxy"
|
|
|
+ + "?secret=" + secret
|
|
|
+ + "&vhost=" + vhost
|
|
|
+ + "&app=live"
|
|
|
+ + "&stream=" + streamId
|
|
|
+ + "&enable_audio=1"
|
|
|
+ + "&add_mute_audio=1"
|
|
|
+ + "&url=" + url;
|
|
|
+
|
|
|
+ // 发送http get请求
|
|
|
+ OkHttpUtils okHttpUtils = new OkHttpUtils();
|
|
|
+ String s = okHttpUtils.get(uri);
|
|
|
+ JSONObject return_json = JSONObject.parse(s);
|
|
|
+ // System.out.println(return_json);
|
|
|
+
|
|
|
+ int code = return_json.getIntValue("code");
|
|
|
+ if (code == 0) {
|
|
|
+ JSONObject data = return_json.getJSONObject("data");
|
|
|
+ // 推流成功产生的唯一key
|
|
|
+ String key = data.getString("key");
|
|
|
+
|
|
|
+ // 保存ip:ip
|
|
|
+ // 推流成功产生的唯一key:key
|
|
|
+ // 线路:nowLine
|
|
|
+ // 如果之前有拉流,则更新:playerCount + 1,否则之间插入:playerCount
|
|
|
+ // 监控厂商:vendor
|
|
|
+ // 保存播放链接:videoLinks
|
|
|
+ Player player = new Player();
|
|
|
+ player.setIp(list.get(0).getIp());
|
|
|
+ player.setChannel(list.get(0).getChannel());
|
|
|
+ player.setD(list.get(0).getD());
|
|
|
+ player.setPlayerkey(key);
|
|
|
+ player.setVendor(list.get(0).getVendor());
|
|
|
+ player.setNowLine(String.valueOf(nowLine));
|
|
|
+ player.setVideoLinks(videoLinks.toString());
|
|
|
+
|
|
|
+ List<Player> players = videoMapper.queryPlayer(player);
|
|
|
+ if (players.size() > 0) {
|
|
|
+ player.setId(players.get(0).getId());
|
|
|
+ player.setPlayerCount(players.get(0).getPlayerCount() + 1);
|
|
|
+ int i = videoMapper.updatePlayer(player);
|
|
|
+ if (i == 1) {
|
|
|
+ return ResponseResult.success("拉流成功,更新播放表成功!", map);
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("拉流成功,更新播放表失败!", map);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ player.setPlayerCount(1);
|
|
|
+ int i = videoMapper.add(player);
|
|
|
+ if (i == 1) {
|
|
|
+ return ResponseResult.success("拉流成功,插入播放表成功!", map);
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("拉流成功,插入播放表失败!", map);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if ("This stream already exists".equals(return_json.getString("msg"))) {
|
|
|
+ return ResponseResult.success("视频流已存在!", map);
|
|
|
+ } else {
|
|
|
+ return ResponseResult.failed("拉流失败:" + return_json.getString("msg"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ return ResponseResult.failed("拉流异常:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭Stream推拉流
|
|
|
+ *
|
|
|
+ * @param player 传入player对象
|
|
|
+ * @return 响应对象
|
|
|
+ */
|
|
|
+ @PostMapping("/delStreamSource")
|
|
|
+ public ResponseResult requestDelStreamSource(@RequestBody Player player) {
|
|
|
+ // 检测参数
|
|
|
+ String d = player.getD();
|
|
|
+ String tNowLine = player.getNowLine();
|
|
|
+ if (d == null || tNowLine == null) return ResponseResult.failed("【通道】或【当前线路】参数为空!");
|
|
|
+
|
|
|
+ String secret = "", vhost = "", port = "";
|
|
|
+ List<Config> return_config = videoMapper.getConfig();
|
|
|
+ if (return_config.size() > 0) {
|
|
|
+ for (Config cfg : return_config) {
|
|
|
+ // 拉流需要的秘钥
|
|
|
+ if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
|
|
|
+ secret = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
|
|
|
+ vhost = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机端口
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
|
|
|
+ port = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
|
|
|
+ if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
|
|
|
+ if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
|
|
|
+
|
|
|
+ String key = "";
|
|
|
+ // 查询是否存在对应ip的流
|
|
|
+ List<Player> players = videoMapper.queryPlayer(player);
|
|
|
+ if (players.size() == 0) {
|
|
|
+ Camera camera = new Camera();
|
|
|
+ camera.setD(player.getD());
|
|
|
+ List<Camera> cameras = cameraMapper.queryChannel(camera);
|
|
|
+ key = vhost + "/live/" + cameras.get(0).getChannel() + "_" + tNowLine;
|
|
|
+ } else {
|
|
|
+ key = players.get(0).getPlayerkey();
|
|
|
+ }
|
|
|
+ int playerCount = players.get(0).getPlayerCount();
|
|
|
+
|
|
|
+ try {
|
|
|
+ String uri = "http://" + vhost + ":" + port + "/index/api/delStreamProxy"
|
|
|
+ + "?secret=" + secret
|
|
|
+ + "&key=" + key;
|
|
|
+ // 发送http get请求
|
|
|
+ OkHttpUtils okHttpUtils = new OkHttpUtils();
|
|
|
+ String s = okHttpUtils.get(uri);
|
|
|
+ JSONObject return_json = JSONObject.parse(s);
|
|
|
+ // System.out.println(return_json);
|
|
|
+
|
|
|
+ int code = return_json.getIntValue("code");
|
|
|
+ if (code == 0) {
|
|
|
+ JSONObject data = return_json.getJSONObject("data");
|
|
|
+ // 成功与否
|
|
|
+ boolean flag = data.getBooleanValue("flag");
|
|
|
+ if (flag) {
|
|
|
+ Player updatePlayer = new Player();
|
|
|
+ updatePlayer.setId(players.get(0).getId());
|
|
|
+ if (playerCount == 1) {
|
|
|
+ // 删除
|
|
|
+ int i = videoMapper.delete(String.valueOf(players.get(0).getId()));
|
|
|
+ if (i > 0)
|
|
|
+ return ResponseResult.success("关闭流成功,删除数据表成功!");
|
|
|
+ else
|
|
|
+ return ResponseResult.success("关闭流成功,删除数据表失败!");
|
|
|
+ } else {
|
|
|
+ updatePlayer.setPlayerCount(playerCount - 1);
|
|
|
+ // 更新
|
|
|
+ int i = videoMapper.updatePlayer(updatePlayer);
|
|
|
+ if (i > 0)
|
|
|
+ return ResponseResult.success("关闭流成功,更新数据表成功!");
|
|
|
+ else
|
|
|
+ return ResponseResult.success("关闭流成功,更新数据表失败!");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("关闭流失败!视频流已经不存在!");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("关闭流失败!code=" + code);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ return ResponseResult.failed("关闭流异常:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 使用Stream推拉playback流
|
|
|
+// *
|
|
|
+// * @param rtsp_url
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// @PostMapping("/addPbStreamSource")
|
|
|
+// public ResponseResult requestAddPbStreamSource(@RequestBody String rtsp_url) {
|
|
|
+// // 检测参数
|
|
|
+// if (rtsp_url == null || rtsp_url.isEmpty())
|
|
|
+// return ResponseResult.failed("请传参数!");
|
|
|
+//
|
|
|
+// JSONObject urlObj = JSONObject.parseObject(rtsp_url);
|
|
|
+// String url = urlObj.getString("url");
|
|
|
+// if (url == null || url.isEmpty())
|
|
|
+// return ResponseResult.failed("【rtsp_url】参数为空!");
|
|
|
+//
|
|
|
+// String[] parts = url.split("/");
|
|
|
+// String bValue = "";
|
|
|
+// String eValue = "";
|
|
|
+// int firstIndex = rtsp_url.indexOf('@');
|
|
|
+// int secondIndex = rtsp_url.indexOf('@', firstIndex + 1);
|
|
|
+// int colonIndex = rtsp_url.indexOf(':', secondIndex);
|
|
|
+// String ip = rtsp_url.substring(secondIndex + 1, colonIndex);
|
|
|
+//
|
|
|
+// for (int i = 0; i < parts.length; i++) {
|
|
|
+// if (parts[i].startsWith("b")) {
|
|
|
+// bValue = parts[i];
|
|
|
+// } else if (parts[i].startsWith("e")) {
|
|
|
+// eValue = parts[i];
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// Date bdate = new Date(Long.parseLong(bValue.substring(1)) * 1000L);
|
|
|
+// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+// String formattedbDate = sdf.format(bdate);
|
|
|
+// Date edate = new Date(Long.parseLong(eValue.substring(1)) * 1000L);
|
|
|
+// String formattedeDate = sdf.format(edate);
|
|
|
+//
|
|
|
+// String streamId = "pb" + formattedbDate.replaceAll("[- :]", "") + "_"
|
|
|
+// + formattedeDate.replaceAll("[- :]", "");
|
|
|
+//
|
|
|
+// String baseUrl = "", secret = "", vhost = "", port = "";
|
|
|
+// String urlMp4, urlFlv, urlHls, urlTs;
|
|
|
+// StringBuilder videoLinks = new StringBuilder();
|
|
|
+// List<Config> return_config = videoMapper.getConfig();
|
|
|
+// Map<String, String> map = new HashMap<>();
|
|
|
+// if (return_config.size() > 0) {
|
|
|
+// for (Config cfg : return_config) {
|
|
|
+// // 监控视频拉流的基础url:baseUrl
|
|
|
+// if ("system".equals(cfg.getCfgClass()) && "baseUrl".equals(cfg.getCfgName())) {
|
|
|
+// baseUrl = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 拉流需要的秘钥
|
|
|
+// if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
|
|
|
+// secret = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 拉流主机
|
|
|
+// if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
|
|
|
+// vhost = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 拉流主机端口
|
|
|
+// if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
|
|
|
+// port = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 是否开启转换为hls(mpegts)
|
|
|
+// if ("protocol".equals(cfg.getCfgClass()) && "enable_hls".equals(cfg.getCfgName())) {
|
|
|
+// if ("1".equals(cfg.getCfgValue())) {
|
|
|
+// urlHls = baseUrl + "/live/" + streamId + "/hls.m3u8";
|
|
|
+// videoLinks.append(urlHls).append(",");
|
|
|
+// map.put("hls", urlHls);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// // 是否开启转换为rtmp/flv
|
|
|
+// if ("protocol".equals(cfg.getCfgClass()) && "enable_rtmp".equals(cfg.getCfgName())) {
|
|
|
+// if ("1".equals(cfg.getCfgValue())) {
|
|
|
+// urlFlv = baseUrl + "/live/" + streamId + ".live.flv";
|
|
|
+// videoLinks.append(urlFlv).append(",");
|
|
|
+// map.put("flv", urlFlv);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// // 是否开启转换为http-ts/ws-ts
|
|
|
+// if ("protocol".equals(cfg.getCfgClass()) && "enable_ts".equals(cfg.getCfgName())) {
|
|
|
+// if ("1".equals(cfg.getCfgValue())) {
|
|
|
+// urlTs = baseUrl + "/link/live/" + streamId + ".live.ts";
|
|
|
+// videoLinks.append(urlTs).append(",");
|
|
|
+// map.put("ts", urlTs);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// // 是否开启转换为http-fmp4/ws-fmp4
|
|
|
+// if ("protocol".equals(cfg.getCfgClass()) && "enable_fmp4".equals(cfg.getCfgName())) {
|
|
|
+// if ("1".equals(cfg.getCfgValue())) {
|
|
|
+// urlMp4 = baseUrl + "/live/" + streamId + ".live.mp4";
|
|
|
+// videoLinks.append(urlMp4).append(",");
|
|
|
+// map.put("mp4", urlMp4);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (!"".contentEquals(videoLinks)) {
|
|
|
+// videoLinks.setLength(videoLinks.length() - 1);
|
|
|
+// //map.put("videoLinks", videoLinks);
|
|
|
+// }
|
|
|
+//
|
|
|
+// if ("".equals(baseUrl)) return ResponseResult.failed("配置表中没有配置基础URL:baseUrl");
|
|
|
+// if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
|
|
|
+// if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
|
|
|
+// if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
|
|
|
+//
|
|
|
+// try {
|
|
|
+// // 拉流接口
|
|
|
+// String uri = "http://" + vhost + ":" + port + "/index/api/addStreamProxy"
|
|
|
+// + "?secret=" + secret
|
|
|
+// + "&vhost=" + vhost
|
|
|
+// + "&app=live"
|
|
|
+// + "&stream=" + streamId
|
|
|
+// + "&enable_audio=1"
|
|
|
+// + "&add_mute_audio=1"
|
|
|
+// + "&url=" + url;
|
|
|
+// // 发送http get请求
|
|
|
+// OkHttpUtils okHttpUtils = new OkHttpUtils();
|
|
|
+// String s = okHttpUtils.get(uri);
|
|
|
+// JSONObject return_json = JSONObject.parse(s);
|
|
|
+//
|
|
|
+// int code = return_json.getIntValue("code");
|
|
|
+// if (code == 0) {
|
|
|
+// JSONObject data = return_json.getJSONObject("data");
|
|
|
+// // 推流成功产生的唯一key
|
|
|
+// String key = data.getString("key");
|
|
|
+//
|
|
|
+// // 保存ip:ip
|
|
|
+// // 推流成功产生的唯一key:key
|
|
|
+// // 线路:nowLine
|
|
|
+// // 如果之前有拉流,则更新:playerCount + 1,否则之间插入:playerCount
|
|
|
+// // 监控厂商:vendor
|
|
|
+// // 保存播放链接:videoLinks
|
|
|
+// Player player = new Player();
|
|
|
+// player.setIp(ip);
|
|
|
+// player.setPlayerkey(key);
|
|
|
+// player.setVideoLinks(videoLinks.toString());
|
|
|
+//
|
|
|
+// List<Player> players = videoMapper.queryPlayer(player);
|
|
|
+// if (players.size() > 0) {
|
|
|
+// player.setId(players.get(0).getId());
|
|
|
+// player.setPlayerCount(players.get(0).getPlayerCount() + 1);
|
|
|
+// int i = videoMapper.updatePlayer(player);
|
|
|
+// if (i == 1) {
|
|
|
+// return ResponseResult.success("拉流成功+1!", map);
|
|
|
+// } else {
|
|
|
+// return ResponseResult.success("拉流成功,更新播放表失败!", map);
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// player.setPlayerCount(1);
|
|
|
+// int i = videoMapper.add(player);
|
|
|
+// if (i == 1) {
|
|
|
+// return ResponseResult.success("拉流成功,插入播放表成功!", map);
|
|
|
+// } else {
|
|
|
+// return ResponseResult.success("拉流成功,插入播放表失败!", map);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// return ResponseResult.failed("拉流失败:" + return_json.getString("msg"));
|
|
|
+// }
|
|
|
+// } catch (Exception e) {
|
|
|
+// return ResponseResult.failed("拉流异常:" + e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 关闭Stream推拉playback流
|
|
|
+// *
|
|
|
+// * @param json
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// @PostMapping("/delPbStreamSource")
|
|
|
+// public ResponseResult requestDelPbStreamSource(@RequestBody String json) {
|
|
|
+// // 检测参数
|
|
|
+// if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
|
|
|
+//
|
|
|
+// JSONObject urlObj = JSONObject.parseObject(json);
|
|
|
+// String paramkey = urlObj.getString("key");
|
|
|
+// if (paramkey == null || paramkey.isEmpty())
|
|
|
+// return ResponseResult.failed("【key】参数为空!");
|
|
|
+//
|
|
|
+// Player player = new Player();
|
|
|
+// player.setPlayerkey(paramkey);
|
|
|
+//
|
|
|
+// // 查询是否存在对应ip的流
|
|
|
+// List<Player> players = videoMapper.queryPlayer(player);
|
|
|
+// if (players.size() < 1)
|
|
|
+// return ResponseResult.failed("没有对应【IP】的视频流,或许已经关闭!");
|
|
|
+//
|
|
|
+// String key = players.get(0).getPlayerkey();
|
|
|
+// int playerCount = players.get(0).getPlayerCount();
|
|
|
+//
|
|
|
+// String secret = "", vhost = "", port = "";
|
|
|
+// List<Config> return_config = videoMapper.getConfig();
|
|
|
+// if (return_config.size() > 0) {
|
|
|
+// for (Config cfg : return_config) {
|
|
|
+// // 拉流需要的秘钥
|
|
|
+// if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
|
|
|
+// secret = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 拉流主机
|
|
|
+// if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
|
|
|
+// vhost = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// // 拉流主机端口
|
|
|
+// if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
|
|
|
+// port = cfg.getCfgValue();
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
|
|
|
+// if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
|
|
|
+// if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
|
|
|
+//
|
|
|
+// try {
|
|
|
+// String uri = "http://" + vhost + ":" + port + "/index/api/delStreamProxy"
|
|
|
+// + "?secret=" + secret
|
|
|
+// + "&key=" + key;
|
|
|
+// // 发送http get请求
|
|
|
+// OkHttpUtils okHttpUtils = new OkHttpUtils();
|
|
|
+// String s = okHttpUtils.get(uri);
|
|
|
+// JSONObject return_json = JSONObject.parse(s);
|
|
|
+//
|
|
|
+// int code = return_json.getIntValue("code");
|
|
|
+// if (code == 0) {
|
|
|
+// JSONObject data = return_json.getJSONObject("data");
|
|
|
+// // 成功与否
|
|
|
+// boolean flag = data.getBooleanValue("flag");
|
|
|
+// if (flag) {
|
|
|
+// Player updatePlayer = new Player();
|
|
|
+// updatePlayer.setId(players.get(0).getId());
|
|
|
+// if (playerCount == 1) {
|
|
|
+// // 删除
|
|
|
+// int i = videoMapper.delete(String.valueOf(players.get(0).getId()));
|
|
|
+// if (i > 0)
|
|
|
+// return ResponseResult.success("关闭流成功-1,更新数据表成功!");
|
|
|
+// else
|
|
|
+// return ResponseResult.success("关闭流成功,数据表不存在流信息!");
|
|
|
+// } else {
|
|
|
+// updatePlayer.setPlayerCount(playerCount - 1);
|
|
|
+// // 更新
|
|
|
+// int i = videoMapper.updatePlayer(updatePlayer);
|
|
|
+// if (i > 0)
|
|
|
+// return ResponseResult.success("关闭流成功-1,更新数据表成功!");
|
|
|
+// else
|
|
|
+// return ResponseResult.success("关闭流成功,更新数据表失败!");
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// // 视频流已经不存在,删除对应的记录
|
|
|
+// int i = videoMapper.deleteByKey(key);
|
|
|
+// if (i > 0)
|
|
|
+// return ResponseResult.success("关闭流失败!视频流已经不存在!更新数据表成功!");
|
|
|
+// else
|
|
|
+// return ResponseResult.success("关闭流失败!视频流已经不存在!更新数据表失败!");
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// return ResponseResult.success("关闭流失败!code=" + code);
|
|
|
+// }
|
|
|
+// } catch (Exception e) {
|
|
|
+// return ResponseResult.failed("关闭流异常:" + e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 指定的流是否在线
|
|
|
+ *
|
|
|
+ * @param json
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("/isOnline")
|
|
|
+ public ResponseResult getMediaList(@RequestBody String json) {
|
|
|
+ // 检测参数
|
|
|
+ if (json == null || json.isEmpty()) return ResponseResult.failed("请传参数!");
|
|
|
+
|
|
|
+ JSONObject urlObj = JSONObject.parseObject(json);
|
|
|
+ String stream = urlObj.getString("stream");
|
|
|
+ if (stream == null || stream.isEmpty())
|
|
|
+ return ResponseResult.failed("【stream】参数为空!");
|
|
|
+
|
|
|
+ String secret = "", vhost = "", port = "";
|
|
|
+ List<Config> return_config = videoMapper.getConfig();
|
|
|
+ if (return_config.size() > 0) {
|
|
|
+ for (Config cfg : return_config) {
|
|
|
+ // 拉流需要的秘钥
|
|
|
+ if ("api".equals(cfg.getCfgClass()) && "secret".equals(cfg.getCfgName())) {
|
|
|
+ secret = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "vhost".equals(cfg.getCfgName())) {
|
|
|
+ vhost = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ // 拉流主机端口
|
|
|
+ if ("system".equals(cfg.getCfgClass()) && "port".equals(cfg.getCfgName())) {
|
|
|
+ port = cfg.getCfgValue();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ("".equals(secret)) return ResponseResult.failed("配置表中没有配置秘钥:secret");
|
|
|
+ if ("".equals(vhost)) return ResponseResult.failed("配置表中没有配置主机:vhost");
|
|
|
+ if ("".equals(port)) return ResponseResult.failed("配置表中没有配置拉流主机端口:port");
|
|
|
+
|
|
|
+ try {
|
|
|
+ String base_uri = "http://" + vhost + ":" + port + "/index/api/getMediaList"
|
|
|
+ + "?secret=" + secret
|
|
|
+ + "&app=live"
|
|
|
+ + "&stream=" + stream;
|
|
|
+ String local_uri = base_uri + "&vhost=__defaultVhost__";
|
|
|
+ // 发送http get请求
|
|
|
+ OkHttpUtils okHttpUtils = new OkHttpUtils();
|
|
|
+ String s = okHttpUtils.get(local_uri);
|
|
|
+ JSONObject return_json = JSONObject.parse(s);
|
|
|
+
|
|
|
+ int code = return_json.getIntValue("code");
|
|
|
+ if (code == 0) {
|
|
|
+ JSONArray data = return_json.getJSONArray("data");
|
|
|
+ if (data == null) {
|
|
|
+ String remote_uri = base_uri + "&vhost=" + vhost;
|
|
|
+ // 发送http get请求
|
|
|
+ okHttpUtils = new OkHttpUtils();
|
|
|
+ s = okHttpUtils.get(remote_uri);
|
|
|
+ return_json = JSONObject.parse(s);
|
|
|
+ code = return_json.getIntValue("code");
|
|
|
+ if (code == 0) {
|
|
|
+ data = return_json.getJSONArray("data");
|
|
|
+ if (data == null) {
|
|
|
+ // 视频流已经不存在,删除对应的记录
|
|
|
+ int i = videoMapper.deleteByKey(stream);
|
|
|
+ if (i > 0)
|
|
|
+ return ResponseResult.success("本地、远程都不存在指定的流!更新数据表成功!");
|
|
|
+ else
|
|
|
+ return ResponseResult.success("本地、远程都不存在指定的流!数据表不存在流信息!");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.size() > 0) {
|
|
|
+ StringBuilder stringBuilder = new StringBuilder();
|
|
|
+ int num = 0;
|
|
|
+ for (int i = 0; i < data.size(); i++) {
|
|
|
+ JSONObject jsonObject = data.getJSONObject(i);
|
|
|
+ String schema = jsonObject.getString("schema");
|
|
|
+ stringBuilder.append(schema).append(",");
|
|
|
+ num++;
|
|
|
+ }
|
|
|
+ stringBuilder.setLength(stringBuilder.length() - 1);
|
|
|
+ return ResponseResult.success("远程存在指定的流,有" + num + "协议", stringBuilder);
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("远程不存在指定的流");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success(return_json);
|
|
|
+ }
|
|
|
+ } else if (data.size() > 0) {
|
|
|
+ StringBuilder stringBuilder = new StringBuilder();
|
|
|
+ int num = 0;
|
|
|
+ for (int i = 0; i < data.size(); i++) {
|
|
|
+ JSONObject jsonObject = data.getJSONObject(i);
|
|
|
+ String schema = jsonObject.getString("schema");
|
|
|
+ stringBuilder.append(schema).append(",");
|
|
|
+ num++;
|
|
|
+ }
|
|
|
+ stringBuilder.setLength(stringBuilder.length() - 1);
|
|
|
+ return ResponseResult.success("本地存在指定的流,有" + num + "协议", stringBuilder);
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success("本地不存在指定的流");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ResponseResult.success(return_json);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ return ResponseResult.failed("查询指定流异常:" + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 使用FFmpeg推拉流
|
|
|
+// * 没有使用
|
|
|
+// *
|
|
|
+// * @param videoRequest
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// @ParamCheck
|
|
|
+// @PostMapping("addFFmpegSource")
|
|
|
+// public CommonResult requestAddFFmpegSource(@RequestBody VideoRequest videoRequest) {
|
|
|
+// List videoDTOList = videoRequest.getVideoList();
|
|
|
+// List<VideoVO> videoVOList = new ArrayList<>();
|
|
|
+//
|
|
|
+// for (int i = 0; i < videoDTOList.size(); i++) {
|
|
|
+// VideoVO videoVO = new VideoVO();
|
|
|
+// VideoDTO videoDTO = (VideoDTO) videoDTOList.get(i);
|
|
|
+// String uri = "http://172.16.20.75:8081/index/api/addFFmpegSource" +
|
|
|
+// "?secret=035c73f7-bb6b-4889-a715-d9eb2d1925ca" +
|
|
|
+// "&src_url=rtsp://adnin:123456@" + videoDTO.getIp() + "/media/video" + videoDTO.getNowLine() +
|
|
|
+// "&dst_url=rtmp://172.16.20.75/live/stream" + i +
|
|
|
+// "&timeout_ms=10000" +
|
|
|
+// "&ffmpeg_cmd_key=ffmpeg.cmd";
|
|
|
+//
|
|
|
+// RestTemplate restTemplate = new RestTemplate();
|
|
|
+// ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
|
|
|
+// ObjectMapper mapper = new ObjectMapper();
|
|
|
+// try {
|
|
|
+// Map<String, Object> jsonMap = mapper.readValue(forEntity.getBody(), new TypeReference<Map<String, Object>>() {
|
|
|
+// });
|
|
|
+// String data = jsonMap.get("data").toString();
|
|
|
+// String substring = data.substring(5);
|
|
|
+// String key = substring.substring(0, substring.length() - 1);
|
|
|
+// videoVO.setKey(key);
|
|
|
+// } catch (Exception e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// }
|
|
|
+// String flv = "http://172.16.20.75:8081/live/stream" + i + ".live.flv";
|
|
|
+// videoVO.setUrlFlv(flv);
|
|
|
+// videoVOList.add(videoVO);
|
|
|
+// }
|
|
|
+//
|
|
|
+// return CommonResult.ok().setResult(videoVOList);
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 关闭FFmpeg推拉流
|
|
|
+// *
|
|
|
+// * @param KeyRequest
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// @ParamCheck
|
|
|
+// @PostMapping("delFFmpegSource")
|
|
|
+// public CommonResult requestDelFFmpegSource(@RequestBody KeyRequest KeyRequest) {
|
|
|
+// String flag = "";
|
|
|
+// List<KeyDTO> keyList = KeyRequest.getKeyList();
|
|
|
+// for (int i = 0; i < keyList.size(); i++) {
|
|
|
+// KeyDTO keyDTO = keyList.get(i);
|
|
|
+// String cameraKey = this.queryCameraByIp(keyDTO.getIp()).getCameraKey();
|
|
|
+// String uri = "http://172.16.20.75:8081/index/api/delFFmpegSource" +
|
|
|
+// "?secret=035c73f7-bb6b-4889-a715-d9eb2d1925ca" +
|
|
|
+// "&key=" + cameraKey;
|
|
|
+//
|
|
|
+// RestTemplate restTemplate = new RestTemplate();
|
|
|
+// ResponseEntity<String> forEntity = restTemplate.getForEntity(uri, String.class);
|
|
|
+// ObjectMapper mapper = new ObjectMapper();
|
|
|
+// try {
|
|
|
+// Map<String, Object> jsonMap = mapper.readValue(forEntity.getBody(), new TypeReference<Map<String, Object>>() {
|
|
|
+// });
|
|
|
+// String data = jsonMap.get("data").toString();
|
|
|
+// String substring = data.substring(6);
|
|
|
+// flag = substring.substring(0, substring.length() - 1);
|
|
|
+//
|
|
|
+// } catch (Exception e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// return CommonResult.ok().setResult(flag);
|
|
|
+// }
|
|
|
+}
|