diff --git a/src/main/java/com/petstore/controller/FileController.java b/src/main/java/com/petstore/controller/FileController.java index d9195f8..cdccfb9 100644 --- a/src/main/java/com/petstore/controller/FileController.java +++ b/src/main/java/com/petstore/controller/FileController.java @@ -75,6 +75,9 @@ public class FileController { } String contentType = Files.probeContentType(file.toPath()); if (contentType == null) contentType = "image/jpeg"; + // 去掉可能的 charset 参数,避免 video Content-Type 被设为 "video/mp4;charset=UTF-8" + int semi = contentType.indexOf(';'); + if (semi >= 0) contentType = contentType.substring(0, semi).trim(); return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .body(new FileSystemResource(file)); @@ -91,6 +94,9 @@ public class FileController { } String contentType = Files.probeContentType(file.toPath()); if (contentType == null) contentType = "image/jpeg"; + // 去掉可能的 charset 参数,避免 video Content-Type 被设为 "video/mp4;charset=UTF-8" + int semi = contentType.indexOf(';'); + if (semi >= 0) contentType = contentType.substring(0, semi).trim(); return ResponseEntity.ok() .contentType(MediaType.parseMediaType(contentType)) .body(new FileSystemResource(file)); diff --git a/src/main/java/com/petstore/service/ReportHighlightVideoService.java b/src/main/java/com/petstore/service/ReportHighlightVideoService.java index 1a37ebc..9eeb4b8 100644 --- a/src/main/java/com/petstore/service/ReportHighlightVideoService.java +++ b/src/main/java/com/petstore/service/ReportHighlightVideoService.java @@ -203,7 +203,24 @@ public class ReportHighlightVideoService { "-c:a", "aac", "-b:a", "96k", merged.toString() )); if (c2 != 0) { - throw new IllegalStateException("ffmpeg 拼接失败(退出码 " + c2 + ")"); + throw new IllegalStateException("ffmpeg 转码失败(退出码 " + c2 + ")"); + } + + // 验证输出文件(确保可播放) + Path verified = workDir.resolve("verified.mp4"); + int c3 = runFfmpeg(List.of( + ffmpegBinary, "-y", "-i", merged.toString(), + "-vf", "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2", + "-c:v", "libx264", "-preset", "fast", "-crf", "22", + "-profile:v", "baseline", "-level", "3.0", // 最高兼容 WeChat/Android + "-c:a", "aac", "-b:a", "128k", + "-movflags", "+faststart", // MP4 streaming优化,微信要求 + "-t", String.valueOf(durationSec), + verified.toString() + )); + if (c3 != 0) { + // 转码验证失败,降级为copy + verified = merged; } } @@ -213,7 +230,8 @@ public class ReportHighlightVideoService { Files.createDirectories(outDir); String filename = "highlight_" + reportId + "_" + UUID.randomUUID().toString().replace("-", "") + ".mp4"; Path finalPath = outDir.resolve(filename); - Files.copy(merged, finalPath, StandardCopyOption.REPLACE_EXISTING); + Path sourceToSave = Files.exists(verified) ? verified : merged; + Files.copy(sourceToSave, finalPath, StandardCopyOption.REPLACE_EXISTING); String url = "/api/upload/image/" + datePath + "/" + filename;