package org.sxkj.common.utils; import org.sxkj.common.model.SubtitleFrame; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * srt 文件解析工具类 */ public class SrtParserUtils { private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss,SSS"); private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); /** * srt 文件解析 * @param filePath * @return * @throws IOException */ public static List parseSrtFile(String filePath) throws IOException { List frames = new ArrayList<>(); String content = new String(Files.readAllBytes(Paths.get(filePath))); String[] blocks = content.split("\\n\\n+"); for (String block : blocks) { if (block.trim().isEmpty()) { continue; } String[] lines = block.split("\\n"); if (lines.length < 3) { continue; } try { int index = Integer.parseInt(lines[0].trim()); String[] timeRange = lines[1].trim().split(" --> "); String startTime = timeRange[0].trim(); String endTime = timeRange[1].trim(); StringBuilder contentBuilder = new StringBuilder(); for (int i = 2; i < lines.length; i++) { contentBuilder.append(lines[i].trim()).append(" "); } String contentText = contentBuilder.toString().trim(); // 解析帧计数和时间戳 Pattern framePattern = Pattern.compile("FrameCnt:\\s*(\\d+)\\s+(\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}\\.\\d{3})"); Matcher frameMatcher = framePattern.matcher(contentText); if (!frameMatcher.find()) { continue; } int frameCount = Integer.parseInt(frameMatcher.group(1)); LocalDateTime timestamp = LocalDateTime.parse(frameMatcher.group(2), TIMESTAMP_FORMATTER); // 解析元数据 Map metadata = parseMetadata(contentText); // 构建相机参数 Map cameraParams = new HashMap<>(); cameraParams.put("iso", metadata.get("iso")); cameraParams.put("shutter", metadata.get("shutter")); cameraParams.put("fnum", metadata.get("fnum")); cameraParams.put("ev", metadata.get("ev")); cameraParams.put("color_md", metadata.get("color_md")); cameraParams.put("ae_meter_md", metadata.get("ae_meter_md")); cameraParams.put("focal_len", metadata.get("focal_len")); cameraParams.put("dzoom_ratio", metadata.get("dzoom_ratio")); cameraParams.put("dehaze_level", metadata.get("dehaze_level")); cameraParams.put("dehaze_mode", metadata.get("dehaze_mode")); // 构建GPS数据 Map gpsData = new HashMap<>(); gpsData.put("latitude", Double.parseDouble(metadata.getOrDefault("latitude", "0"))); gpsData.put("longitude", Double.parseDouble(metadata.getOrDefault("longitude", "0"))); gpsData.put("rel_alt", Double.parseDouble(metadata.getOrDefault("rel_alt", "0"))); gpsData.put("abs_alt", Double.parseDouble(metadata.getOrDefault("abs_alt", "0"))); // 构建方向数据 Map orientation = new HashMap<>(); orientation.put("yaw", Double.parseDouble(metadata.getOrDefault("gb_yaw", "0"))); orientation.put("pitch", Double.parseDouble(metadata.getOrDefault("gb_pitch", "0"))); orientation.put("roll", Double.parseDouble(metadata.getOrDefault("gb_roll", "0"))); // 其他数据 Map otherData = new HashMap<>(); for (Map.Entry entry : metadata.entrySet()) { if (!cameraParams.containsKey(entry.getKey()) && !gpsData.containsKey(entry.getKey()) && !orientation.containsKey(entry.getKey())) { otherData.put(entry.getKey(), entry.getValue()); } } SubtitleFrame frame = new SubtitleFrame( index, startTime, endTime, frameCount, timestamp, cameraParams, gpsData, orientation, otherData ); frames.add(frame); } catch (Exception e) { System.err.println("Error parsing block: " + e.getMessage()); continue; } } return frames; } private static LocalTime parseSrtTime(String timeStr) { // 处理SRT时间格式,如 00:00:00,000 timeStr = timeStr.replace(',', '.'); return LocalTime.parse(timeStr, TIME_FORMATTER); } private static Map parseMetadata(String text) { // 先处理特殊字段 text = text.replaceAll("\\[rel_alt:\\s*([-\\d.]+)\\s*abs_alt:\\s*([-\\d.]+)\\]", "[rel_alt: $1] [abs_alt: $2]"); text = text.replaceAll("\\[gb_yaw:\\s*([-\\d.]+)\\s*gb_pitch:\\s*([-\\d.]+)\\s*gb_roll:\\s*([-\\d.]+)\\]", "[gb_yaw: $1] [gb_pitch: $2] [gb_roll: $3]"); // 解析所有键值对 Map metadata = new HashMap<>(); Pattern pattern = Pattern.compile("\\[([^:]+):\\s*([^\\]]+)\\]"); Matcher matcher = pattern.matcher(text); while (matcher.find()) { metadata.put(matcher.group(1).trim(), matcher.group(2).trim()); } return metadata; } // public static void main(String[] args) { // try { // String srtPath = "C:\\Users\\Administrator\\Desktop\\temp\\视频\\倾斜视频\\DJI_20250527181054_0002_V\\out.srt"; // List frames = SrtParserUtils.parseSrtFile(srtPath); // // for (SubtitleFrame frame : frames) { // System.out.println("Frame #" + frame.getIndex()); // System.out.println("Time: " + frame.getStartTime() + " - " + frame.getEndTime()); // System.out.println("Frame count: " + frame.getFrameCount()); // System.out.println("Timestamp: " + frame.getTimestamp()); // System.out.println("GPS: " + frame.getGpsData()); // System.out.println("Orientation: " + frame.getOrientation()); // System.out.println("----------------------"); // } // } catch (IOException e) { // e.printStackTrace(); // } // } }