From f652169cc5d6501511eece5df57b7b396fd7a7ab Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Tue, 02 Jun 2026 09:51:34 +0800
Subject: [PATCH] 优化

---
 ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java |  606 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 511 insertions(+), 95 deletions(-)

diff --git a/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java b/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java
index e6c636f..0956186 100644
--- a/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java
+++ b/ard-modules/ard-modules-zlm/src/main/java/com/ard/zlm/service/impl/MediaServerServiceImpl.java
@@ -8,10 +8,14 @@
 import com.ard.common.core.domain.RtpServerParam;
 import com.ard.common.core.enums.LiveStreamType;
 import com.ard.common.core.utils.DateUtils;
+import com.ard.common.core.utils.file.FileMultipartFile;
 import com.ard.gb28181.api.RemoteGb28181Service;
 import com.ard.gb28181.api.domain.Device;
-import com.ard.qs.api.RemoteQsDeviceService;
-import com.ard.qs.api.domain.QsDevice;
+import com.ard.zlm.domain.StreamChannel;
+import com.ard.zlm.service.ZlmStreamService;
+import com.ard.zlm.domain.StreamChannel;
+import com.ard.system.api.RemoteFileService;
+import com.ard.system.api.domain.SysFile;
 import com.ard.work.api.RemoteCameraService;
 import com.ard.work.api.RemoteChannelService;
 import com.ard.work.api.domian.ArdChannel;
@@ -50,7 +54,12 @@
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 import org.springframework.util.DigestUtils;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.*;
 
 /**
@@ -64,7 +73,8 @@
 @Slf4j
 @Service
 public class MediaServerServiceImpl implements IMediaServerService {
-
+    @Resource
+    private RemoteFileService remoteFileService;
     @Resource
     private MediaServerMapper mediaServerMapper;
 
@@ -96,7 +106,7 @@
     private HookSubscribe subscribe;
 
     @Resource
-    private RemoteQsDeviceService remoteQsDeviceService;
+    private ZlmStreamService zlmStreamService;
 
     @Resource
     private RemoteChannelService remoteChannelService;
@@ -175,7 +185,7 @@
         }
         redisCatchStorage.updateStreamAuthorityInfo(event.getApp(), event.getStream(), streamAuthorityInfo);
 
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
+        R<StreamChannel> r = zlmStreamService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
                 SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             log.error("获取设备信息失败,stream:{}", event.getStream());
@@ -183,7 +193,7 @@
         }
 
         if (r.getData() == null) {
-            r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
+            r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
             if (r.getCode() != Constants.SUCCESS) {
                 log.error("获取设备信息失败,stream:{}", event.getStream());
                 return;
@@ -191,10 +201,9 @@
         }
 
         if (r.getData() == null) {
-            QsDevice device = new QsDevice();
-            device.setDeviceStatus("ON");
+            StreamChannel device = new StreamChannel();
             device.setMediaServerId(mediaInfo.getMediaServer().getId());
-            device.setDeviceName("推流设备_" + event.getApp() + "_" + event.getStream());
+            device.setChannelName("推流设备_" + event.getApp() + "_" + event.getStream());
             device.setType(LiveStreamType.PUSH.getCode());
             device.setStatus("ENABLE");
             device.setStreamStatus("1");
@@ -204,7 +213,7 @@
             String filePath = snapOnPlay(mediaInfo.getMediaServer(), event.getApp(), event.getStream());
             device.setSnap(filePath);
 
-            R<Boolean> addR = remoteQsDeviceService.addQsDevice(device, SecurityConstants.INNER);
+            R<Boolean> addR = zlmStreamService.addQsDevice(device, SecurityConstants.INNER);
             if (addR.getCode() != Constants.SUCCESS) {
                 throw new RuntimeException("添加推流设备设备失败" + event.getApp() + "_" + event.getStream());
             }
@@ -213,15 +222,14 @@
                 throw new RuntimeException("添加推流设备设备失败" + event.getApp() + "_" + event.getStream());
             }
         } else {
-            QsDevice device = new QsDevice();
-            device.setDeviceStatus("ON");
+            StreamChannel device = new StreamChannel();
             device.setMediaServerId(mediaInfo.getMediaServer().getId());
             device.setStreamKey(r.getData().getDeviceCode());
             device.setStreamStatus("1");
             device.setId(r.getData().getId());
             String filePath = snapOnPlay(mediaInfo.getMediaServer(), event.getApp(), event.getStream());
             device.setSnap(filePath);
-            R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(device, SecurityConstants.INNER);
+            R<Boolean> updateR = zlmStreamService.updateQsDevice(device, SecurityConstants.INNER);
             if (updateR.getCode() != Constants.SUCCESS) {
                 throw new RuntimeException("修改推流设备设备失败" + event.getApp() + "_" + event.getStream());
             }
@@ -259,7 +267,7 @@
             if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) {
                 inviteStreamService.removeInviteInfo(inviteInfo);
 
-                R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(Long.valueOf(inviteInfo.getDeviceId()),
+                R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(Long.valueOf(inviteInfo.getDeviceId()),
                         SecurityConstants.INNER);
                 if (r.getCode() != Constants.SUCCESS) {
                     return;
@@ -291,7 +299,7 @@
         }
 
         if ("video_file".equals(event.getApp())) {
-            R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
+            R<StreamChannel> r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
             if (r.getCode() != Constants.SUCCESS) {
                 return;
             }
@@ -300,12 +308,12 @@
                 return;
             }
 
-            QsDevice qsDevice = new QsDevice();
-            qsDevice.setId(r.getData().getId());
-            qsDevice.setStreamKey("");
-            qsDevice.setMediaServerId("");
-            qsDevice.setStreamStatus("0");
-            R<Boolean> qsDevicer = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+            StreamChannel streamChannel = new StreamChannel();
+            streamChannel.setId(r.getData().getId());
+            streamChannel.setStreamKey("");
+            streamChannel.setMediaServerId("");
+            streamChannel.setStreamStatus("0");
+            R<Boolean> qsDevicer = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
             if (qsDevicer.getCode() != Constants.SUCCESS) {
                 log.error("更新设备失败");
             }
@@ -333,7 +341,7 @@
             redisCatchStorage.removePushListItem(event.getApp(), event.getStream(), event.getMediaServer().getId());
         }
 
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
+        R<StreamChannel> r = zlmStreamService.getQsDeviceStream("pull_" + event.getApp() + "_" + event.getStream(),
                 SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             log.error("获取设备信息失败,stream:{}", event.getStream());
@@ -341,7 +349,7 @@
         }
 
         if (r.getData() == null) {
-            r = remoteQsDeviceService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
+            r = zlmStreamService.getQsDeviceStream(event.getStream(), SecurityConstants.INNER);
             if (r.getCode() != Constants.SUCCESS) {
                 log.error("获取设备信息失败,stream:{}", event.getStream());
                 return;
@@ -351,13 +359,12 @@
         if (r.getData() == null) {
             return;
         }
-        QsDevice device = new QsDevice();
-        device.setDeviceStatus("OFFLINE");
+        StreamChannel device = new StreamChannel();
         device.setMediaServerId("");
         device.setStreamKey("");
         device.setStreamStatus("0");
         device.setId(r.getData().getId());
-        R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(device, SecurityConstants.INNER);
+        R<Boolean> updateR = zlmStreamService.updateQsDevice(device, SecurityConstants.INNER);
         if (updateR.getCode() != Constants.SUCCESS) {
             throw new RuntimeException("修改推流设备设备失败" + event.getApp() + "_" + event.getStream());
         }
@@ -787,6 +794,28 @@
      * @param app         app
      * @param stream      流id
      */
+    //@Override
+//    public String snapOnPlay1(ZlmMediaServer mediaServer, String app, String stream) {
+//        String fileName = app + "-" + stream + ".jpg";
+//        // 请求截图
+//        log.info("[请求截图]: " + fileName);
+//
+//        IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
+//        if (mediaNodeServerService == null) {
+//            log.info("[getSnap] 失败, mediaServer的类型: {},未找到对应的实现类", mediaServer.getType());
+//            throw new RuntimeException("[getSnap] 失败, mediaServer的类型: " + mediaServer.getType() + ",未找到对应的实现类");
+//        }
+//        String filePath = fileDomain + filePrefix + "/snap/" + fileName;
+//        mediaNodeServerService.getSnap(mediaServer, app, stream, 30, 300, this.filePath + "/snap", fileName);
+//        return filePath;
+//    }
+    /**
+     * 点播成功时调用截图
+     *
+     * @param mediaServer media
+     * @param app         app
+     * @param stream      流id
+     */
     @Override
     public String snapOnPlay(ZlmMediaServer mediaServer, String app, String stream) {
         String fileName = app + "-" + stream + ".jpg";
@@ -798,11 +827,53 @@
             log.info("[getSnap] 失败, mediaServer的类型: {},未找到对应的实现类", mediaServer.getType());
             throw new RuntimeException("[getSnap] 失败, mediaServer的类型: " + mediaServer.getType() + ",未找到对应的实现类");
         }
-        String filePath = fileDomain + filePrefix + "/snap/" + fileName;
-        mediaNodeServerService.getSnap(mediaServer, app, stream, 30, 300, this.filePath + "/snap", fileName);
-        return filePath;
-    }
 
+        // 生成临时文件路径(用于 FFmpeg 截图)
+        String tempDir = System.getProperty("java.io.tmpdir") + "/snap_temp/";
+        File tempDirFile = new File(tempDir);
+        if (!tempDirFile.exists()) {
+            tempDirFile.mkdirs();
+        }
+        String tempFilePath = tempDir + fileName;
+
+        try {
+            // 1. 获取截图到临时文件
+            mediaNodeServerService.getSnap(mediaServer, app, stream, 30, 300, tempDir, fileName);
+            // 2. 检查临时文件是否存在
+            File tempFile = new File(tempFilePath);
+            if (!tempFile.exists()) {
+                log.error("[截图失败] 临时文件不存在: {}", tempFilePath);
+                return null;
+            }
+
+            // 3. 使用 FileMultipartFile 转换为 MultipartFile
+            MultipartFile multipartFile = new FileMultipartFile(
+                    tempFile,
+                    fileName,
+                    "image/jpeg"
+            );
+
+            // 3. 调用文件上传接口,上传到 MinIO(bucketName 可以固定为 "snap" 或动态传入)
+            R<SysFile> result = remoteFileService.upload(multipartFile, "snap");
+
+            // 4. 清理临时文件
+            Files.deleteIfExists(Paths.get(tempFilePath));
+
+            // 5. 返回 URL
+            if (result.getCode() == Constants.SUCCESS && result.getData() != null) {
+                String url = result.getData().getUrl();
+                log.info("[截图上传成功] URL: {}", url);
+                return url;
+            } else {
+                log.error("[截图上传失败] {}", result.getMsg());
+                return null;
+            }
+
+        } catch (Exception e) {
+            log.error("[截图失败] ", e);
+            return null;
+        }
+    }
     /**
      * 获取截图
      *
@@ -917,7 +988,7 @@
             return;
         }
 
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败" + rtpServerParam.getId(), null);
             return;
@@ -927,7 +998,7 @@
             return;
         }
 
-        if ("OFFLINE".equals(r.getData().getDeviceStatus())) {
+        if (!Boolean.TRUE.equals(Boolean.TRUE.equals(r.getData().getDeviceOnLine()))) {
             callback.run(InviteErrorCode.FAIL.getCode(), "设备不在线" + rtpServerParam.getId(), null);
             return;
         }
@@ -950,7 +1021,7 @@
      * @param callback       回调
      * @return
      */
-    private SSRCInfo play(ZlmMediaServer mediaServer, RTPServerParam rtpServerParam, QsDevice device, String ssrc,
+    private SSRCInfo play(ZlmMediaServer mediaServer, RTPServerParam rtpServerParam, StreamChannel device, String ssrc,
                           ErrorCallback<StreamInfo> callback) {
         // 获取点播的状态信息
         InviteInfo inviteInfoInCatch = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY,
@@ -1049,13 +1120,13 @@
 
                     String filePath = snapOnPlay(streamInfo.getMediaServer(), streamInfo.getApp(),
                             streamInfo.getStream());
-                    QsDevice qsDevice = new QsDevice();
-                    qsDevice.setId(rtpServerParam.getId());
-                    qsDevice.setStreamKey(rtpServerParam.getStreamId());
-                    qsDevice.setMediaServerId(mediaServer.getId());
-                    qsDevice.setStreamStatus("1");
-                    qsDevice.setSnap(filePath);
-                    R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+                    StreamChannel streamChannel = new StreamChannel();
+                    streamChannel.setId(rtpServerParam.getId());
+                    streamChannel.setStreamKey(rtpServerParam.getStreamId());
+                    streamChannel.setMediaServerId(mediaServer.getId());
+                    streamChannel.setStreamStatus("1");
+                    streamChannel.setSnap(filePath);
+                    R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                     if (r.getCode() != Constants.SUCCESS) {
                         throw new RuntimeException("更新设备失败");
                     }
@@ -1143,14 +1214,14 @@
      */
     @Override
     public void stopRtpPlay(RTPServerParam rtpServerParam) {
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(rtpServerParam.getId(), SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             throw new RuntimeException("获取设备信息失败");
         }
         if (r.getData() == null) {
             throw new RuntimeException("设备不存在");
         }
-        QsDevice device = r.getData();
+        StreamChannel device = r.getData();
 
         String mediaServerId = device.getMediaServerId();
         ZlmMediaServer mediaServer = getOne(mediaServerId);
@@ -1167,12 +1238,12 @@
             }
         }
 
-        QsDevice qsDevice = new QsDevice();
-        qsDevice.setId(rtpServerParam.getId());
-        qsDevice.setStreamKey("");
-        qsDevice.setMediaServerId("");
-        qsDevice.setStreamStatus("0");
-        R<Boolean> devicer = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+        StreamChannel streamChannel = new StreamChannel();
+        streamChannel.setId(rtpServerParam.getId());
+        streamChannel.setStreamKey("");
+        streamChannel.setMediaServerId("");
+        streamChannel.setStreamStatus("0");
+        R<Boolean> devicer = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
         if (devicer.getCode() != Constants.SUCCESS) {
             throw new RuntimeException("更新设备失败");
         }
@@ -1213,7 +1284,7 @@
             return;
         }
 
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败" + id, null);
             return;
@@ -1223,11 +1294,11 @@
             return;
         }
 
-        if ("OFFLINE".equals(r.getData().getDeviceStatus())) {
+        if (!Boolean.TRUE.equals(Boolean.TRUE.equals(r.getData().getDeviceOnLine()))) {
             throw new RuntimeException("设备不在线" + id);
         }
 
-        QsDevice device = r.getData();
+        StreamChannel device = r.getData();
         String videoPath = convertUrlToPath(device.getLiveAddress(), this.fileDomain, this.filePrefix, this.filePath);
 
         loadMP4File(mediaServer, "video_file", device.getDeviceCode(), id, videoPath, ((code, msg, streamInfo) -> {
@@ -1242,7 +1313,7 @@
      */
     @Override
     public void closeStreams(Long id) {
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             throw new RuntimeException("获取设备信息失败");
         }
@@ -1250,7 +1321,7 @@
             throw new RuntimeException("设备不存在");
         }
 
-        QsDevice device = r.getData();
+        StreamChannel device = r.getData();
         ZlmMediaServer mediaServer = getOne(device.getMediaServerId());
 
         if (mediaServer == null) {
@@ -1536,7 +1607,7 @@
      */
     @Override
     public Map<String, Object> getStreamPushAddress(Long id, String callId) {
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             throw new RuntimeException("获取设备信息失败");
         }
@@ -1566,7 +1637,7 @@
      */
     @Override
     public void streamPullPush(Long id, ErrorCallback<StreamInfo> callback) {
-        R<QsDevice> r = remoteQsDeviceService.getQsDeviceInfo(id, SecurityConstants.INNER);
+        R<StreamChannel> r = zlmStreamService.getQsDeviceInfo(id, SecurityConstants.INNER);
         if (r.getCode() != Constants.SUCCESS) {
             log.info("获取设备信息失败 id:{}", id);
             callback.run(InviteErrorCode.FAIL.getCode(), "获取设备信息失败", null);
@@ -1577,7 +1648,7 @@
             callback.run(InviteErrorCode.FAIL.getCode(), "设备不存在", null);
             return;
         }
-        QsDevice device = r.getData();
+        StreamChannel device = r.getData();
 
         if (!LiveStreamType.PUSH.getCode().equals(device.getType())) {
             log.info("直播流接入类型不对,应当是PUSH id:{}", id);
@@ -1598,10 +1669,10 @@
                 callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(),
                         getStreamInfoByAppAndStream(mediaServer, "push", device.getDeviceCode(), mediaInfo));
                 if ("0".equals(device.getStreamStatus())) {
-                    QsDevice qsDevice = new QsDevice();
-                    qsDevice.setId(id);
-                    qsDevice.setStreamStatus("1");
-                    R<Boolean> updateR = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+                    StreamChannel streamChannel = new StreamChannel();
+                    streamChannel.setId(id);
+                    streamChannel.setStreamStatus("1");
+                    R<Boolean> updateR = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                     if (updateR.getCode() != Constants.SUCCESS) {
                         log.info("修改推流设备设备失败 id:{}", id);
                         throw new RuntimeException("修改推流设备设备失败");
@@ -1620,12 +1691,12 @@
     /**
      * gb28181 播放
      *
-     * @param qsDevice
+     * @param streamChannel
      * @param gbDevice
      * @param callback
      */
     @Override
-    public void startGb28181Play(QsDevice qsDevice, Device gbDevice, ErrorCallback<StreamInfo> callback) {
+    public void startGb28181Play(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback) {
         ZlmMediaServer mediaServer = getMediaServerForMinimumLoad(null);
 
         if (mediaServer == null) {
@@ -1633,18 +1704,18 @@
             return;
         }
 
-        int tcpMode = qsDevice.getStreamMode().equals("TCP-ACTIVE") ? 2 : (qsDevice.getStreamMode().equals("TCP" +
+        int tcpMode = streamChannel.getStreamMode().equals("TCP-ACTIVE") ? 2 : (streamChannel.getStreamMode().equals("TCP" +
                 "-PASSIVE") ? 1 : 0);
 
         RTPServerParam rtpServerParam = new RTPServerParam();
         rtpServerParam.setApp("gb28181");
         rtpServerParam.setMediaServer(mediaServer);
         rtpServerParam.setType(LiveStreamType.GB28181.getCode());
-        rtpServerParam.setStreamId(qsDevice.getDeviceCode());
+        rtpServerParam.setStreamId(streamChannel.getDeviceCode());
         rtpServerParam.setTcpMode(tcpMode);
-        rtpServerParam.setId(qsDevice.getId());
+        rtpServerParam.setId(streamChannel.getId());
 
-        startGb28181PlayFun(mediaServer, qsDevice, gbDevice, rtpServerParam, null, callback);
+        startGb28181PlayFun(mediaServer, streamChannel, gbDevice, rtpServerParam, null, callback);
     }
 
     /**
@@ -1670,21 +1741,21 @@
      * gb28181 停止点播
      *
      * @param type
-     * @param qsDevice
+     * @param streamChannel
      * @param device
      * @param stream
      */
     @Override
-    public void stopGb28181Play(InviteSessionType type, QsDevice qsDevice, Device device, String stream) {
-        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, qsDevice.getId(), stream);
+    public void stopGb28181Play(InviteSessionType type, StreamChannel streamChannel, Device device, String stream) {
+        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, streamChannel.getId(), stream);
         if (inviteInfo == null) {
             if (type == InviteSessionType.PLAY) {
-                QsDevice qsDeviceUpdate = new QsDevice();
-                qsDeviceUpdate.setId(qsDevice.getId());
+                StreamChannel qsDeviceUpdate = new StreamChannel();
+                qsDeviceUpdate.setId(streamChannel.getId());
                 qsDeviceUpdate.setStreamKey("");
                 qsDeviceUpdate.setMediaServerId("");
                 qsDeviceUpdate.setStreamStatus("0");
-                R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
+                R<Boolean> r = zlmStreamService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
                 if (r.getCode() != Constants.SUCCESS) {
                     throw new RuntimeException("更新设备失败");
                 }
@@ -1694,18 +1765,18 @@
         inviteStreamService.removeInviteInfo(inviteInfo);
         if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
             try {
-                log.info("[停止点播/回放/下载] {}/{}", qsDevice.getGbDeviceId(), qsDevice.getGbChannelId());
+                log.info("[停止点播/回放/下载] {}/{}", streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
 
                 RtpServerParam rtpServer = new RtpServerParam();
                 rtpServer.setApp("gb28181");
-                rtpServer.setStream(qsDevice.getDeviceCode());
-                rtpServer.setGbDeviceId(qsDevice.getGbDeviceId());
-                rtpServer.setGbChannelId(qsDevice.getGbChannelId());
+                rtpServer.setStream(streamChannel.getDeviceCode());
+                rtpServer.setGbDeviceId(streamChannel.getGbDeviceId());
+                rtpServer.setGbChannelId(streamChannel.getGbChannelId());
 
                 R<Void> r = remoteGb28181Service.streamByeCmd(rtpServer, SecurityConstants.INNER);
                 if (r.getCode() != Constants.SUCCESS) {
-                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", qsDevice.getGbDeviceId());
-                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + qsDevice.getGbDeviceId());
+                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", streamChannel.getGbDeviceId());
+                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + streamChannel.getGbDeviceId());
                 }
             } catch (Exception e) {
                 log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
@@ -1714,12 +1785,12 @@
         }
 
         if (inviteInfo.getType() == InviteSessionType.PLAY) {
-            QsDevice qsDeviceUpdate = new QsDevice();
-            qsDeviceUpdate.setId(qsDevice.getId());
+            StreamChannel qsDeviceUpdate = new StreamChannel();
+            qsDeviceUpdate.setId(streamChannel.getId());
             qsDeviceUpdate.setStreamKey("");
             qsDeviceUpdate.setMediaServerId("");
             qsDeviceUpdate.setStreamStatus("0");
-            R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
+            R<Boolean> r = zlmStreamService.updateQsDevice(qsDeviceUpdate, SecurityConstants.INNER);
             if (r.getCode() != Constants.SUCCESS) {
                 throw new RuntimeException("更新设备失败");
             }
@@ -1738,6 +1809,160 @@
         }
     }
 
+    /**
+     * gb28181 播放(基于GbDevice,不依赖QS)
+     */
+    @Override
+    public void startGb28181PlayByGbChannel(StreamChannel streamChannel, Device gbDevice, ErrorCallback<StreamInfo> callback) {
+        ZlmMediaServer mediaServer = getMediaServerForMinimumLoad(null);
+
+        if (mediaServer == null) {
+            callback.run(InviteErrorCode.FAIL.getCode(), "无可用的节点", null);
+            return;
+        }
+
+        String streamMode = streamChannel.getStreamMode() != null
+                ? streamChannel.getStreamMode() : gbDevice.getStreamMode();
+        int tcpMode = streamMode.equals("TCP-ACTIVE") ? 2
+                : (streamMode.equals("TCP-PASSIVE") ? 1 : 0);
+
+        RTPServerParam rtpServerParam = new RTPServerParam();
+        rtpServerParam.setApp("gb28181");
+        rtpServerParam.setMediaServer(mediaServer);
+        rtpServerParam.setType(LiveStreamType.GB28181.getCode());
+        rtpServerParam.setStreamId(streamChannel.getDeviceCode());
+        rtpServerParam.setTcpMode(tcpMode);
+        rtpServerParam.setId(streamChannel.getId());
+
+        startGb28181PlayFunByGbChannel(mediaServer, streamChannel, gbDevice, rtpServerParam, null, callback);
+    }
+
+    /**
+     * gb28181 停止点播(基于GbDevice,不依赖QS)
+     */
+    @Override
+    public void stopGb28181PlayByGbChannel(InviteSessionType type, StreamChannel streamChannel, Device device, String stream) {
+        InviteInfo inviteInfo = inviteStreamService.getInviteInfo(type, streamChannel.getId(), stream);
+        if (inviteInfo == null) {
+            if (type == InviteSessionType.PLAY) {
+                StreamChannel update = new StreamChannel();
+                update.setId(streamChannel.getId());
+                update.setStreamKey("");
+                update.setMediaServerId("");
+                update.setStreamStatus("0");
+                R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
+                if (r.getCode() != Constants.SUCCESS) {
+                    throw new RuntimeException("更新GbDevice失败");
+                }
+            }
+            return;
+        }
+        inviteStreamService.removeInviteInfo(inviteInfo);
+        if (InviteSessionStatus.ok == inviteInfo.getStatus()) {
+            try {
+                log.info("[停止点播/回放/下载] {}/{}", streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
+
+                RtpServerParam rtpServer = new RtpServerParam();
+                rtpServer.setApp("gb28181");
+                rtpServer.setStream(streamChannel.getDeviceCode());
+                rtpServer.setGbDeviceId(streamChannel.getGbDeviceId());
+                rtpServer.setGbChannelId(streamChannel.getGbChannelId());
+
+                R<Void> r = remoteGb28181Service.streamByeCmd(rtpServer, SecurityConstants.INNER);
+                if (r.getCode() != Constants.SUCCESS) {
+                    log.error("[命令发送失败] 停止点播/回放/下载, deviceId:{}", streamChannel.getGbDeviceId());
+                    throw new RuntimeException("[命令发送失败] 停止点播/回放/下载, deviceId:" + streamChannel.getGbDeviceId());
+                }
+            } catch (Exception e) {
+                log.error("[命令发送失败] 停止点播/回放/下载, 发送BYE: {}", e.getMessage());
+                throw new RuntimeException("命令发送失败: " + e.getMessage());
+            }
+        }
+
+        if (inviteInfo.getType() == InviteSessionType.PLAY) {
+            StreamChannel update = new StreamChannel();
+            update.setId(streamChannel.getId());
+            update.setStreamKey("");
+            update.setMediaServerId("");
+            update.setStreamStatus("0");
+            R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
+            if (r.getCode() != Constants.SUCCESS) {
+                throw new RuntimeException("更新GbDevice失败");
+            }
+        }
+
+        ZlmMediaServer mediaServer = null;
+        if (inviteInfo.getStreamInfo() != null) {
+            mediaServer = inviteInfo.getStreamInfo().getMediaServer();
+        } else {
+            mediaServer = getOne(inviteInfo.getMediaServerId());
+        }
+
+        if (mediaServer != null && inviteInfo.getSsrcInfo() != null) {
+            closeRTPServer(mediaServer, inviteInfo.getSsrcInfo().getStream());
+            ssrcFactory.releaseSsrc(inviteInfo.getMediaServerId(), inviteInfo.getSsrcInfo().getSsrc());
+        }
+    }
+
+    /**
+     * 通过通道ID拉流代理(简化传参,自动根据通道类型确定app/url等参数)
+     *
+     * @param channelId 通道ID
+     * @param callback  回调
+     */
+    @Override
+    public void streamPullPlayByChannelId(String channelId, ErrorCallback<StreamInfo> callback) {
+        R<ArdChannel> channelR = remoteChannelService.getInfo(channelId, SecurityConstants.INNER);
+        if (channelR.getCode() != Constants.SUCCESS) {
+            callback.run(InviteErrorCode.FAIL.getCode(), "获取通道信息失败 channelId:" + channelId, null);
+            return;
+        }
+        if (channelR.getData() == null) {
+            callback.run(InviteErrorCode.FAIL.getCode(), "通道不存在 channelId:" + channelId, null);
+            return;
+        }
+
+        ArdChannel ardChannel = channelR.getData();
+        StreamPullPlay streamPullPlay = buildStreamPullPlay(ardChannel);
+        streamPullPlay(streamPullPlay, callback);
+    }
+
+    /**
+     * 通过通道ID停止拉流代理
+     *
+     * @param channelId 通道ID
+     */
+    @Override
+    public void stopStreamPullPlayByChannelId(String channelId) {
+        R<ArdChannel> channelR = remoteChannelService.getInfo(channelId, SecurityConstants.INNER);
+        if (channelR.getCode() != Constants.SUCCESS) {
+            throw new RuntimeException("获取通道信息失败 channelId:" + channelId);
+        }
+        if (channelR.getData() == null) {
+            throw new RuntimeException("通道不存在 channelId:" + channelId);
+        }
+
+        ArdChannel ardChannel = channelR.getData();
+        StreamPullPlay streamPullPlay = new StreamPullPlay();
+        streamPullPlay.setChannelId(channelId);
+        streamPullPlay.setMediaServerId(ardChannel.getMediaServerId());
+        streamPullPlay.setStreamKey(ardChannel.getStreamKey());
+        stopStreamPullPlay(streamPullPlay);
+    }
+
+    private StreamPullPlay buildStreamPullPlay(ArdChannel ardChannel) {
+        StreamPullPlay streamPullPlay = new StreamPullPlay();
+        streamPullPlay.setChannelId(ardChannel.getId());
+        streamPullPlay.setStream(ardChannel.getId());
+        streamPullPlay.setUrl(ardChannel.getLiveAddress());
+        streamPullPlay.setApp("ard");
+        streamPullPlay.setEnable_mp4(false);
+        streamPullPlay.setEnable_audio(true);
+        streamPullPlay.setRtp_type("1");
+        streamPullPlay.setTimeOut(10);
+        return streamPullPlay;
+    }
+
 
     /**
      * 开启国标28181播放
@@ -1748,7 +1973,7 @@
      * @param ssrc
      * @param callback
      */
-    private SSRCInfo startGb28181PlayFun(ZlmMediaServer mediaServer, QsDevice device, Device gbDevice,
+    private SSRCInfo startGb28181PlayFun(ZlmMediaServer mediaServer, StreamChannel device, Device gbDevice,
                                          RTPServerParam rtpServerParam, String ssrc,
                                          ErrorCallback<StreamInfo> callback) {
         // 获取点播的状态信息
@@ -1848,13 +2073,13 @@
 
                     String filePath = snapOnPlay(streamInfo.getMediaServer(), streamInfo.getApp(),
                             streamInfo.getStream());
-                    QsDevice qsDevice = new QsDevice();
-                    qsDevice.setId(rtpServerParam.getId());
-                    qsDevice.setStreamKey(rtpServerParam.getStreamId());
-                    qsDevice.setMediaServerId(mediaServer.getId());
-                    qsDevice.setStreamStatus("1");
-                    qsDevice.setSnap(filePath);
-                    R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+                    StreamChannel streamChannel = new StreamChannel();
+                    streamChannel.setId(rtpServerParam.getId());
+                    streamChannel.setStreamKey(rtpServerParam.getStreamId());
+                    streamChannel.setMediaServerId(mediaServer.getId());
+                    streamChannel.setStreamStatus("1");
+                    streamChannel.setSnap(filePath);
+                    R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                     if (r.getCode() != Constants.SUCCESS) {
                         throw new RuntimeException("更新设备失败");
                     }
@@ -1956,6 +2181,197 @@
     }
 
     /**
+     * 开启国标28181播放(基于GbDevice,不依赖QS)
+     */
+    private SSRCInfo startGb28181PlayFunByGbChannel(ZlmMediaServer mediaServer, StreamChannel streamChannel,
+                                                    Device gbDevice, RTPServerParam rtpServerParam,
+                                                    String ssrc, ErrorCallback<StreamInfo> callback) {
+        // 获取点播的状态信息
+        InviteInfo inviteInfoInCatch = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY,
+                streamChannel.getId());
+        if (inviteInfoInCatch != null) {
+            if (inviteInfoInCatch.getStreamInfo() == null) {
+                ssrcFactory.releaseSsrc(mediaServer.getId(), null);
+                inviteStreamService.once(InviteSessionType.PLAY, streamChannel.getId(), null, callback);
+                log.info("[点播开始] 已经请求中,等待结果, deviceId: {}, channel: {}", streamChannel.getId(), streamChannel.getId());
+                return inviteInfoInCatch.getSsrcInfo();
+            } else {
+                StreamInfo streamInfo = inviteInfoInCatch.getStreamInfo();
+                String streamId = streamInfo.getStream();
+                if (streamId == null) {
+                    callback.run(InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "点播失败, redis缓存streamId等于null", null);
+                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                            InviteErrorCode.ERROR_FOR_CATCH_DATA.getCode(), "点播失败, redis缓存streamId等于null", null);
+                    return inviteInfoInCatch.getSsrcInfo();
+                }
+                ZlmMediaServer mediaInfo = streamInfo.getMediaServer();
+                Boolean ready = isStreamReady(mediaInfo, rtpServerParam.getApp(), streamId);
+                if (ready != null && ready) {
+                    if (callback != null) {
+                        callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
+                    }
+                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                            InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
+                    log.info("[点播已存在] 直接返回, 设备编号: {}", streamChannel.getId());
+                    return inviteInfoInCatch.getSsrcInfo();
+                } else {
+                    inviteStreamService.once(InviteSessionType.PLAY, streamChannel.getId(), null, callback);
+                    RTPServerParam stopRtp = new RTPServerParam();
+                    stopRtp.setId(streamChannel.getId());
+                    stopRtp.setType(rtpServerParam.getType());
+                    stopRtp.setStreamId(rtpServerParam.getStreamId());
+                    stopRtpPlay(stopRtp);
+                    inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
+                }
+            }
+        }
+
+        rtpServerParam.setMediaServer(mediaServer);
+        if (rtpServerParam.getPresetSsrc() != null) {
+            ssrc = rtpServerParam.getPresetSsrc();
+        } else {
+            if (rtpServerParam.isPlayback()) {
+                ssrc = ssrcFactory.getPlayBackSsrc(mediaServer.getId());
+            } else {
+                ssrc = ssrcFactory.getPlaySsrc(mediaServer.getId());
+            }
+        }
+        rtpServerParam.setSsrc(ssrc);
+
+        SSRCInfo ssrcInfo = receiveRtpServerService.openRTPServer(rtpServerParam, (code, msg, result) -> {
+            if (code == InviteErrorCode.SUCCESS.getCode() && result != null && result.getHookData() != null) {
+                log.info("[创建RTP服务器] 成功, code: {}, msg: {}, result: {}", code, msg, result);
+                StreamInfo streamInfo = getStreamInfoByAppAndStream(mediaServer, rtpServerParam.getApp(),
+                        rtpServerParam.getStreamId(), result.getHookData().getMediaInfo());
+                if (streamInfo == null) {
+                    if (callback != null) {
+                        callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
+                                InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
+                    }
+                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
+                            InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
+                    if (result != null && result.getSsrcInfo() != null) {
+                        closeRTPServer(mediaServer, result.getSsrcInfo().getStream());
+                        ssrcFactory.releaseSsrc(mediaServer.getId(), result.getSsrcInfo().getSsrc());
+                    }
+                    return;
+                }
+                if (callback != null) {
+                    callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
+                    inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                            InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
+
+                    InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(
+                            InviteSessionType.PLAY, streamChannel.getId());
+                    if (inviteInfo != null) {
+                        inviteInfo.setStatus(InviteSessionStatus.ok);
+                        inviteInfo.setStreamInfo(streamInfo);
+                        inviteStreamService.updateInviteInfo(inviteInfo);
+                    }
+
+                    String filePath = snapOnPlay(streamInfo.getMediaServer(), streamInfo.getApp(),
+                            streamInfo.getStream());
+
+                    // 更新GbDevice流状态
+                    StreamChannel update = new StreamChannel();
+                    update.setId(rtpServerParam.getId());
+                    update.setStreamKey(rtpServerParam.getStreamId());
+                    update.setMediaServerId(mediaServer.getId());
+                    update.setStreamStatus("1");
+                    update.setSnap(filePath);
+                    R<Boolean> r = zlmStreamService.updateQsDevice(update, SecurityConstants.INNER);
+                    if (r.getCode() != Constants.SUCCESS) {
+                        throw new RuntimeException("更新GbDevice失败");
+                    }
+                }
+            } else {
+                log.error("[创建RTP服务器] 失败, code: {}, msg: {}, result: {}", code, msg, result);
+                if (callback != null) {
+                    callback.run(code, msg, null);
+                }
+                inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null, code, msg, null);
+                inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
+                if (result != null && result.getSsrcInfo() != null) {
+                    closeRTPServer(mediaServer, result.getSsrcInfo().getStream());
+                    ssrcFactory.releaseSsrc(mediaServer.getId(), result.getSsrcInfo().getSsrc());
+                }
+            }
+        });
+
+        if (ssrcInfo == null || ssrcInfo.getPort() <= 0) {
+            log.info("[点播端口/SSRC]获取失败,设备编号:{}, 通道编号:{}, ssrcInfo: {}", streamChannel.getId(), streamChannel.getId(), ssrcInfo);
+            if (rtpServerParam.getPresetSsrc() == null) {
+                ssrcFactory.releaseSsrc(mediaServer.getId(), ssrc);
+            }
+            callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "获取端口或者ssrc失败", null);
+            inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                    InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(),
+                    InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null);
+            return null;
+        }
+
+        int port = ssrcInfo.getPort();
+        String ip = mediaServer.getIp();
+        RtpServerParam rtpServer = new RtpServerParam();
+        rtpServer.setPort(port);
+        rtpServer.setIp(ip);
+        rtpServer.setId(rtpServerParam.getId());
+        rtpServer.setSsrc(rtpServerParam.getSsrc());
+        rtpServer.setGbDeviceId(gbDevice.getDeviceId());
+        rtpServer.setGbChannelId(streamChannel.getGbChannelId());
+        rtpServer.setStreamMode(gbDevice.getStreamMode());
+        rtpServer.setMediaServerId(mediaServer.getId());
+        rtpServer.setApp(rtpServerParam.getApp());
+        rtpServer.setStream(rtpServerParam.getStreamId());
+
+        log.info("[国标28181点播开始(基于GbDevice)] ===============================");
+        log.info("[国标28181] GbDeviceId: {}, 设备国标ID: {}, 通道国标ID: {}", streamChannel.getId(),
+                gbDevice.getDeviceId(), streamChannel.getGbChannelId());
+        log.info("[国标28181] 流模式: {}, ZLM tcpMode: {}, ssrcCheck: {}", gbDevice.getStreamMode(),
+                rtpServerParam.getTcpMode(), rtpServerParam.isSsrcCheck());
+        log.info("[国标28181] ZLM媒体服务器IP: {}, 收流端口: {}, 流ID: {}, SSRC: {}", ip, port, ssrcInfo.getStream(),
+                ssrcInfo.getSsrc());
+        log.info("[国标28181] =======================================");
+
+        InviteInfo inviteInfo = InviteInfo.getInviteInfo(streamChannel.getId().toString(), streamChannel.getId(),
+                ssrcInfo.getStream(), ssrcInfo, mediaServer.getId(), mediaServer.getSdpIp(), ssrcInfo.getPort(),
+                gbDevice.getStreamMode(), InviteSessionType.PLAY, InviteSessionStatus.ready,
+                userSetting.getRecordSip());
+
+        if ("1".equals(streamChannel.getEnableMp4())) {
+            inviteInfo.setRecord(true);
+        }
+
+        inviteStreamService.updateInviteInfo(inviteInfo);
+
+        R<Void> r = remoteGb28181Service.playStreamCmd(rtpServer, SecurityConstants.INNER);
+
+        if (r.getCode() != Constants.SUCCESS) {
+            log.info("[点播失败]{}:{} deviceId: {}, channelId:{}", r.getCode(), r.getMsg(),
+                    streamChannel.getGbDeviceId(), streamChannel.getGbChannelId());
+            inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.PLAY, streamChannel.getId(),
+                    rtpServerParam.getStreamId());
+            if (inviteInfo != null) {
+                inviteStreamService.removeInviteInfo(inviteInfo);
+                if (inviteInfo.getSsrcInfo() != null) {
+                    ssrcFactory.releaseSsrc(mediaServer.getId(), inviteInfo.getSsrcInfo().getSsrc());
+                }
+            }
+            closeRTPServer(mediaServer, ssrcInfo.getStream());
+            ssrcFactory.releaseSsrc(mediaServer.getId(), ssrcInfo.getSsrc());
+            if (callback != null) {
+                callback.run(r.getCode(), r.getMsg(), null);
+            }
+            inviteStreamService.call(InviteSessionType.PLAY, streamChannel.getId(), null,
+                    r.getCode(), r.getMsg(), null);
+            inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, streamChannel.getId());
+            return ssrcInfo;
+        }
+        return ssrcInfo;
+    }
+
+    /**
      * 将 WebSocket 协议地址转换为 HTTP 协议地址
      * ws:// -> http://
      * wss:// -> https://
@@ -2000,12 +2416,12 @@
             if (callback != null) {
                 callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo);
 
-                QsDevice qsDevice = new QsDevice();
-                qsDevice.setId(id);
-                qsDevice.setStreamKey(stream);
-                qsDevice.setMediaServerId(mediaServer.getId());
-                qsDevice.setStreamStatus("1");
-                R<Boolean> r = remoteQsDeviceService.updateQsDevice(qsDevice, SecurityConstants.INNER);
+                StreamChannel streamChannel = new StreamChannel();
+                streamChannel.setId(id);
+                streamChannel.setStreamKey(stream);
+                streamChannel.setMediaServerId(mediaServer.getId());
+                streamChannel.setStreamStatus("1");
+                R<Boolean> r = zlmStreamService.updateQsDevice(streamChannel, SecurityConstants.INNER);
                 if (r.getCode() != Constants.SUCCESS) {
                     log.error("更新设备失败");
                     callback.run(InviteErrorCode.FAIL.getCode(), "更新设备失败", null);

--
Gitblit v1.9.3