package com.ard.work.sdk.zlxd.record; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.SmartLifecycle; import org.springframework.stereotype.Component; import java.io.File; import java.util.HashMap; import java.util.Map; /** * 录制管理器(Spring 单例 Bean) */ @Slf4j @Component // 声明为 Spring 组件,默认单例 public class RecorderManager implements SmartLifecycle { private String saveDir; // 存储摄像头ID -> 录制器的映射 private final Map recorderMap1 = new HashMap<>(); private final Map recorderMap = new HashMap<>(); // Spring 生命周期标记 private boolean isRunning = false; // 启动单个摄像头录制 public boolean startRecorder(String uniqueCamId, String rtspUrl,String saveDir) { this.saveDir=saveDir; try { // 检查是否已在录制 if (recorderMap.containsKey(uniqueCamId)) { log.warn("摄像头 {} 已在录制中,无需重复启动", uniqueCamId); return true; } // 构建录制目录 // 创建录制器并启动 // RtspRecorder recorder = new RtspRecorder(uniqueCamId, rtspUrl, tempDir); // recorder.start(); RtspToMP4 recorder = new RtspToMP4(); File dir = new File(saveDir); if (!dir.exists()) { boolean mkdirs = dir.mkdirs(); if (!mkdirs) { log.error("[{}] 创建保存目录失败:{}", uniqueCamId, saveDir); } } // ⭐ 可配置参数 Long maxSize = 1073741824L; // 1GB Integer maxDuration = null; // 不限制时间 String filePath = saveDir + File.separator + uniqueCamId + ".mp4"; recorder.start(rtspUrl, filePath, maxSize, maxDuration); recorderMap.put(uniqueCamId, recorder); log.info("摄像头 {} 录制启动成功,存储路径:{}", uniqueCamId, saveDir); return true; } catch (Exception e) { log.error("摄像头 {} 录制启动失败", uniqueCamId, e); return false; } } // 停止单个摄像头录制 public String stopRecorder(String uniqueCamId) { try { //RtspRecorder recorder = recorderMap.get(uniqueCamId); RtspToMP4 recorder = recorderMap.get(uniqueCamId); if (recorder == null) { log.warn("摄像头 {} 未在录制中,无需停止", uniqueCamId); return "摄像头未在录制"; } // 停止录制 recorder.stop(); recorderMap.remove(uniqueCamId); // 返回录制文件路径(根据实际生成的文件名调整) String recordPath = saveDir + File.separator + uniqueCamId + ".mp4"; log.info("摄像头 {} 录制停止成功,文件路径:{}", uniqueCamId, recordPath); return recordPath; } catch (Exception e) { log.error("摄像头 {} 录制停止失败", uniqueCamId, e); return "停止失败:" + e.getMessage(); } } // 停止所有录制 public void stopAllRecorders() { log.info("开始停止所有摄像头录制..."); for (String camId : recorderMap.keySet()) { stopRecorder(camId); } recorderMap.clear(); log.info("所有摄像头录制已停止"); } // 检查摄像头是否在录制 public boolean isRecording(String uniqueCamId) { //RtspRecorder recorder = recorderMap.get(uniqueCamId); RtspToMP4 recorder = recorderMap.get(uniqueCamId); return recorder != null && recorder.isRunning(); } // ====================== Spring 生命周期方法 ====================== @Override public void start() { isRunning = true; } @Override public void stop() { // Spring 关闭时,自动停止所有录制 stopAllRecorders(); isRunning = false; log.info("RecorderManager 已销毁"); } @Override public boolean isRunning() { return isRunning; } // 优先级:数字越小,越先启动、越后销毁 @Override public int getPhase() { return 0; } public static void main(String[] args) throws InterruptedException { RecorderManager recorder = new RecorderManager(); recorder.startRecorder("cam1", "rtsp://admin:admin@112.98.104.134:8237/000100","D:\\home\\temp\\record"); // 录制30秒 log.info("开始录制,持续30秒..."); Thread.sleep(30000); // 停止录制 recorder.stop(); log.info("录制已停止,文件可正常操作"); // 验证文件是否可用 File videoFile = new File("D:\\home\\temp\\cam1.mp4"); if (videoFile.exists()) { log.info("录制文件已生成,大小:{} KB", videoFile.length() / 1024); } else { log.error("录制文件未生成"); } } }