liusuyi
2025-09-30 e0e99fad10f6c8dedf4c11c065b10469cd47a1e8
优化流媒体接口实现机场和相机业务
11 files modified
2 files deleted
2 files renamed
696 ■■■■■ changed files
ard-admin/src/main/java/com/ard/web/controller/vtdu/MediaMTXController.java 8 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/core/config/SwaggerConfig.java 19 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/resources/logback.xml 2 ●●●●● patch | view | raw | blame | history
ard-device/src/main/java/com/ard/device/camera/service/impl/ArdCameraServiceImpl.java 31 ●●●●● patch | view | raw | blame | history
ard-device/src/main/java/com/ard/device/component/sdk/hik/service/impl/HikVisionSDK.java 2 ●●●●● patch | view | raw | blame | history
ard-device/src/main/java/com/ard/device/component/sdk/service/CameraSDK.java 5 ●●●●● patch | view | raw | blame | history
ard-device/src/main/java/com/ard/device/component/sdk/service/CameraSDKService.java 12 ●●●●● patch | view | raw | blame | history
ard-sample/src/main/java/com/ard/sample/manage/service/impl/LiveStreamServiceImpl.java 9 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/domain/StreamInfo.java 11 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/service/IArdMediaMTXService.java 70 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/service/IArdMediaService.java 2 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdArdMediaServiceImpl.java 17 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdMediaMTXServiceImpl.java 501 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdVtduServiceImpl.java 5 ●●●●● patch | view | raw | blame | history
ard-vtdu/src/main/resources/mapper/ArdVtduMapper.xml 2 ●●●●● patch | view | raw | blame | history
ard-admin/src/main/java/com/ard/web/controller/vtdu/MediaMTXController.java
@@ -5,7 +5,7 @@
import com.ard.common.core.page.TableDataInfo;
import com.ard.vtdu.domain.ArdVtdu;
import com.ard.vtdu.domain.Conf;
import com.ard.vtdu.service.IArdMediaMTXService;
import com.ard.vtdu.service.IArdMediaService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -27,14 +27,14 @@
public class MediaMTXController extends BaseController {
    @Resource
    private IArdMediaMTXService mediaService;
    private IArdMediaService mediaService;
    /**
     * 增加通道
     */
    @PostMapping()
    @ApiOperation("增加通道")
    @ApiOperationSupport(includeParameters = {"ardVtdu.name", "ardVtdu.rtspSource", "ardVtdu.mode", "ardVtdu.isCode", "ardVtdu.isRecord"}, order = 1)
    @ApiOperationSupport(includeParameters = {"ardVtdu.name", "ardVtdu.rtspSource"}, order = 1)
    public AjaxResult addPath(@RequestBody ArdVtdu ardVtdu) {
        if (StringUtils.isEmpty(ardVtdu.getName())) {
            return AjaxResult.error("通道名称不能为空");
@@ -50,7 +50,7 @@
     * 修改通道
     */
    @ApiOperation("修改通道")
    @ApiOperationSupport(includeParameters = {"ardVtdu.name", "ardVtdu.rtspSource", "ardVtdu.mode", "ardVtdu.isCode", "ardVtdu.isRecord"}, order = 2)
    @ApiOperationSupport(includeParameters = {"ardVtdu.name", "ardVtdu.rtspSource"}, order = 2)
    @PutMapping
    public AjaxResult edit(@RequestBody ArdVtdu ardVtdu) {
        return AjaxResult.success(mediaService.editPath(ardVtdu));
ard-admin/src/main/java/com/ard/web/core/config/SwaggerConfig.java
@@ -91,6 +91,25 @@
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }
    @Bean
    public Docket mediaMTXApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .enable(true)
                .groupName("流媒体接口")   // 分组名
                .apiInfo(apiInfo("流媒体管理接口"))
                .select()
                // 扫描指定包下,但只扫描加了 @ApiOperation 注解的方法
                .apis(requestHandler ->
                        requestHandler.declaringClass().getPackage().getName().startsWith("com.ard.web.controller" +
                                ".vtdu") &&
                                requestHandler.isAnnotatedWith(io.swagger.annotations.ApiOperation.class)
                )
                .paths(PathSelectors.any())
                .build()
                /* 设置安全模式,swagger可以设置访问token */
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts());
    }
    /**
     * 安全模式,这里指定token通过Authorization头请求头传递
     */
ard-admin/src/main/resources/logback.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 日志存放路径 -->
    <property name="log.path" value="/home/ruoyi/logs" />
    <property name="log.path" value="/home/ard/jar/logs" />
    <!-- 日志输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
ard-device/src/main/java/com/ard/device/camera/service/impl/ArdCameraServiceImpl.java
@@ -25,6 +25,7 @@
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.validation.Validator;
@@ -54,6 +55,7 @@
    @Resource
    protected Validator validator;
    @Override
    public void run(ApplicationArguments args) {
@@ -353,5 +355,32 @@
        // SDK 登录成功后写入 Redis
        redisService.setCacheObject(getCacheKey(camera.getId()), camera);
    }
    /**
     * 同步设备通道与本地通道库信息
     *
     * @author 刘苏义
     * @date 2024/8/22 14:37
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void syncChannel() {
        try {
            log.info("定时执行同步通道任务");
            List<ArdCamera> ardCameraList = this.selectArdCameraList(new ArdCamera());
            if (!ardCameraList.isEmpty()) {
                ardCameraList
                        .forEach(ardCamera -> {
                            //SDK获取实际通道
                            List<ArdChannel> ardChannelListSDK = cameraSDKService.getChannels(ardCamera);
                            //数据库获取通道
                            ArdChannel ardChannel = new ArdChannel();
                            ardChannel.setDeviceId(ardCamera.getId());
                            List<ArdChannel> ardChannelListDb = ardChannelService.selectArdChannelList(ardChannel);
                            //同步通道
                            asyncChannel(ardChannelListDb, ardChannelListSDK);
                        });
            }
        } catch (Exception ex) {
            log.error("定时执行同步通道任务异常:{}", ex.getMessage());
        }
    }
}
ard-device/src/main/java/com/ard/device/component/sdk/hik/service/impl/HikVisionSDK.java
@@ -111,7 +111,7 @@
                        SdkErrorCodeEnum.getDescByCode(errorCode), errorCode);
                return AjaxResult.warn("设备[" + camera.getIp() + ":" + camera.getPort() + "]登录失败: " + SdkErrorCodeEnum.getDescByCode(errorCode) + "(" + errorCode + ")");
            }
            log.debug("Login Success 【 {}:{} 】", camera.getIp(), camera.getPort());
            log.info("Login Success 【 {}:{} 】", camera.getIp(), camera.getPort());
            GlobalVariable.loginMap.put(camera.getId(), loginId);
            GlobalVariable.hikLoginMap.put(loginId, camera);
ard-device/src/main/java/com/ard/device/component/sdk/service/CameraSDK.java
@@ -3,7 +3,10 @@
import com.ard.common.core.domain.AjaxResult;
import com.ard.device.camera.domain.ArdCamera;
import com.ard.device.camera.domain.CameraCmd;
import com.ard.device.channel.domain.ArdChannel;
import com.ard.device.channel.domain.VideoCompressionCfg;
import java.util.List;
/**
@@ -25,4 +28,6 @@
    //获取码流压缩参数
    VideoCompressionCfg getVideoCompressionCfg(CameraCmd cmd);
    //获取相机通道信息
    public List<ArdChannel> getChannels(ArdCamera camera);
}
ard-device/src/main/java/com/ard/device/component/sdk/service/CameraSDKService.java
@@ -5,6 +5,7 @@
import com.ard.common.core.redis.RedisCache;
import com.ard.device.camera.domain.ArdCamera;
import com.ard.device.camera.domain.CameraCmd;
import com.ard.device.channel.domain.ArdChannel;
import com.ard.device.channel.domain.VideoCompressionCfg;
import com.ard.device.component.sdk.common.GlobalVariable;
import com.ard.device.component.sdk.factory.CameraSDKFactory;
@@ -105,5 +106,14 @@
        }
    }
    //获取通道列表
    public List<ArdChannel> getChannels(ArdCamera camera) {
        try {
            CameraSDK cameraSDK = cameraSDKFactory.createCameraSDK(camera.getFactory());
            return cameraSDK.getChannels(camera);
        } catch (Exception ex) {
            log.error("获取相机通道异常:{}", ex.getMessage());
            return null;
        }
    }
}
ard-sample/src/main/java/com/ard/sample/manage/service/impl/LiveStreamServiceImpl.java
@@ -20,7 +20,7 @@
import com.ard.sample.manage.service.ILiveStreamService;
import com.ard.vtdu.config.MediamtxConfig;
import com.ard.vtdu.domain.ArdVtdu;
import com.ard.vtdu.service.IArdMediaMTXService;
import com.ard.vtdu.service.IArdMediaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -52,7 +52,7 @@
    private IMessageSenderService messageSender;
    @Resource
    private IArdMediaMTXService mediaService;
    private IArdMediaService ardMediaService;
    @Resource
    private MediamtxConfig mediamtxConfig;
@@ -118,7 +118,8 @@
            case RTMP:
                ArdVtdu vtdu = new ArdVtdu();
                vtdu.setName(liveParam.getVideoId());
                vtdu = mediaService.addPath(vtdu);
                vtdu.setRtspSource("publisher");
                vtdu = ardMediaService.addPath(vtdu);
                live.setRtmpUrl(vtdu.getRtmpUrl());
                live.setRtspUrl(vtdu.getRtspUrl());
                live.setWebrtcUrl(vtdu.getWebrtcUrl());
@@ -147,7 +148,7 @@
        if (receiveReply.getResult() != 0) {
            return ResponseResult.error(LiveErrorEnum.find(receiveReply.getResult()));
        }
        mediaService.removePath(videoId);
        ardMediaService.removePath(videoId);
        return ResponseResult.success();
    }
ard-vtdu/src/main/java/com/ard/vtdu/domain/StreamInfo.java
@@ -67,17 +67,6 @@
    String remoteAddr;
    /**
     * 解码模式
     * 0-gpu硬解码 1-cpu软解码
     */
    Integer mode;
    /**
     * 是否转码
     * 0-不转码 1-转码
     */
    Integer isCode;
    /**
     * 媒体类型(webRTCSession/rtspSession)
     */
    String sessionType;
ard-vtdu/src/main/java/com/ard/vtdu/service/IArdMediaMTXService.java
File was deleted
ard-vtdu/src/main/java/com/ard/vtdu/service/IArdMediaService.java
File was renamed from ard-vtdu/src/main/java/com/ard/vtdu/service/IMediaService.java
@@ -5,7 +5,7 @@
import java.util.List;
public interface IMediaService {
public interface IArdMediaService {
    /**
     * 增加路径
     */
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdArdMediaServiceImpl.java
File was renamed from ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdMediaServiceImpl.java
@@ -5,7 +5,7 @@
import com.ard.vtdu.client.MediaClient;
import com.ard.vtdu.config.MediamtxConfig;
import com.ard.vtdu.domain.*;
import com.ard.vtdu.service.IMediaService;
import com.ard.vtdu.service.IArdMediaService;
import com.ard.vtdu.util.ArdTool;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import lombok.extern.slf4j.Slf4j;
@@ -29,7 +29,7 @@
 **/
@Service
@Slf4j
public class ArdMediaServiceImpl implements IMediaService {
public class ArdArdMediaServiceImpl implements IArdMediaService {
    @Resource
    MediaClient mediaClient;
@@ -88,8 +88,8 @@
            String webrtcUrl = protocol + mediamtxConfig.getPlayHost() + ":8889/" + ardVtdu.getName();
            Conf conf = new Conf();
            conf.setName(ardVtdu.getName());
            conf.setSource(ardVtdu.getRtspSource());
            conf.setName(ardVtdu.getName());
            conf.setRunOnDemand("");
            conf.setRunOnDemandRestart(false);
            conf.setRunOnDemandCloseAfter("5s");
@@ -148,17 +148,8 @@
            if (StringUtils.isNotEmpty(conf.getRunOnDemand())) {
                runOn = conf.getRunOnDemand();
            }
            //RTSP源地址
            Matcher matcher = Pattern.compile("rtsp://[^\\s\"]+").matcher(runOn);
            if (matcher.find()) {
                info.setRtspSource(matcher.group());
                info.setIsCode(1);
            } else {
                info.setRtspSource(conf.getSource());
                info.setIsCode(0);
            }
            //传输协议
            matcher = Pattern.compile("-rtsp_transport\\s+(\\w+)").matcher(runOn);
            Matcher matcher = Pattern.compile("-rtsp_transport\\s+(\\w+)").matcher(runOn);
            if (matcher.find()) {
                info.setProtocol(matcher.group(1));
            }
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdMediaMTXServiceImpl.java
File was deleted
ard-vtdu/src/main/java/com/ard/vtdu/service/impl/ArdVtduServiceImpl.java
@@ -1,12 +1,11 @@
package com.ard.vtdu.service.impl;
import com.ard.common.utils.DateUtils;
import com.ard.vtdu.config.MediamtxConfig;
import com.ard.vtdu.domain.ArdVtdu;
import com.ard.vtdu.domain.Conf;
import com.ard.vtdu.mapper.ArdVtduMapper;
import com.ard.vtdu.service.IArdVtduService;
import com.ard.vtdu.service.IMediaService;
import com.ard.vtdu.service.IArdMediaService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@@ -29,7 +28,7 @@
    @Resource
    private ArdVtduMapper ardVtduMapper;
    @Resource
    private IMediaService mediaService;
    private IArdMediaService mediaService;
ard-vtdu/src/main/resources/mapper/ArdVtduMapper.xml
@@ -4,7 +4,7 @@
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ard.vtdu.mapper.ArdVtduMapper">
    <resultMap type="com.ard.vtdu.mapper.ArdVtduMapper" id="ArdVtduResult">
    <resultMap type="ArdVtdu" id="ArdVtduResult">
        <result property="name" column="name"/>
        <result property="rtspSource" column="rtsp_source"/>
        <result property="rtspUrl" column="rtsp_url"/>