diff --git a/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java b/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java index 4f622c52..fe102c61 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java +++ b/mall-common/src/main/java/com/suisung/mall/common/feignService/ShopService.java @@ -311,6 +311,12 @@ public interface ShopService { boolean lklPayNotifyUpdateShopOrderLkl(@RequestBody JSONObject lklPayNotifyDataJson); + /** + * 终端cos上传文件 + * + * @param file + * @return + */ @PostMapping(value = "/mobile/shop/oss/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) CommonResult uploadFile(@RequestPart(name = "upfile") MultipartFile file); diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/VideoUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/VideoUtil.java index 2abd92fc..a1cad4c5 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/VideoUtil.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/VideoUtil.java @@ -6,12 +6,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; public class VideoUtil { + private static final Logger logger = LoggerFactory.getLogger(VideoUtil.class); public static List videoAllowFiles = new ArrayList() {{ add("flv"); add("swf"); @@ -31,7 +33,6 @@ public class VideoUtil { add("wav"); add("mid"); }}; - private static Logger logger = LoggerFactory.getLogger(VideoUtil.class); /** * 得到语音或视频文件时长,单位秒 并格式化 @@ -51,11 +52,43 @@ public class VideoUtil { * @return 单位为毫秒 */ public static long getMp4Duration(String videoPath) throws IOException { - IsoFile isoFile = new IsoFile(videoPath); - long lengthInSeconds = - isoFile.getMovieBox().getMovieHeaderBox().getDuration() / - isoFile.getMovieBox().getMovieHeaderBox().getTimescale(); - return lengthInSeconds; + try { + IsoFile isoFile = new IsoFile(videoPath); + long lengthInSeconds = + isoFile.getMovieBox().getMovieHeaderBox().getDuration() / + isoFile.getMovieBox().getMovieHeaderBox().getTimescale(); + return lengthInSeconds; + } catch (Exception e) { + // 处理 MOV 文件可能存在的解析问题,尝试使用 FFmpeg 获取时长 + logger.warn("无法通过 IsoFile 解析视频文件时长: {}, 尝试使用 FFmpeg", videoPath); + try { + return getDurationWithFFmpeg(videoPath); + } catch (Exception ffmpegException) { + logger.error("FFmpeg 也无法解析视频文件时长: {}", videoPath); + throw new IOException("无法解析视频文件: " + videoPath, e); + } + } + } + + /** + * 使用 FFmpeg 获取视频时长(备用方法) + * + * @param videoPath + * @return 单位为毫秒 + * @throws IOException + * @throws InterruptedException + */ + private static long getDurationWithFFmpeg(String videoPath) throws IOException, InterruptedException { + String command = "ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 " + videoPath; + Process process = Runtime.getRuntime().exec(command); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String result = reader.readLine(); + process.waitFor(); + if (result != null) { + // ffprobe 返回的是秒数,需要转换为毫秒 + return (long) (Double.parseDouble(result) * 1000); + } + throw new IOException("无法获取视频时长"); } @@ -194,8 +227,7 @@ public class VideoUtil { int mm = (temp % 3600) / 60; int ss = (temp % 3600) % 60; - return hh != 0 ? ((hh < 10 ? ("0" + hh) : hh) + ":") : "" + - (mm < 10 ? ("0" + mm) : mm) + ":" + + return hh != 0 ? ((hh < 10 ? ("0" + hh) : hh) + ":") : (mm < 10 ? ("0" + mm) : mm) + ":" + (ss < 10 ? ("0" + ss) : ss); } } @@ -206,7 +238,7 @@ class InputStreamRunnable extends Thread { public InputStreamRunnable(InputStream is, String _type) { try { - bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), "UTF-8")); + bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), StandardCharsets.UTF_8)); type = _type; } catch (Exception ex) { ex.printStackTrace(); diff --git a/mall-shop/pom.xml b/mall-shop/pom.xml index 9247fd05..93decd70 100644 --- a/mall-shop/pom.xml +++ b/mall-shop/pom.xml @@ -138,18 +138,39 @@ 1.5.6 + + org.bytedeco - ffmpeg - 4.4-1.5.6 - windows-x86_64 + javacv-platform + 1.5.6 + org.bytedeco - ffmpeg + ffmpeg-platform 4.4-1.5.6 - linux-x86_64 + + + + + + + + + + + + + + + + + + + + org.springframework.boot diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java index 75682bac..a8e90b22 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/service/impl/OssServiceImpl.java @@ -212,7 +212,12 @@ public class OssServiceImpl implements OssService { String cover_upname = uploadName.replace("." + VideoUtil.getVideoFormat(uploadName), ".jpg"); String floder = ALIYUN_OSS_DIR_PREFIX.concat("/") + dir + "/video/frame1/"; - thumb_file_url = videoUtil.getVideoCoverV2(ossUrl, floder, cover_upname); + try { + thumb_file_url = videoUtil.getVideoCoverV2(ossUrl, floder, cover_upname); + } catch (Exception e) { + logger.error("获取视频封面失败: ", e); + thumb_file_url = ""; + } /*if (VideoUtil.getVideoCover(uploadPath, cover_path, 1, "375*667")) { try { thumb_file_url = uploadObject2OSS(new File(cover_path), ALIYUN_OSS_DIR_PREFIX.concat("/").concat(dir).concat(cover_upname), null, null, null); @@ -580,7 +585,7 @@ public class OssServiceImpl implements OssService { ObjectListing objectListing = ossCli.listObjects(listObjectsRequest); List commonPrefixes = objectListing.getCommonPrefixes(); logger.info(JSONUtil.toJsonStr(commonPrefixes)); - return commonPrefixes; + return commonPrefixes; } @Override @@ -632,8 +637,7 @@ public class OssServiceImpl implements OssService { } /** - * - * @param ossFolder 如folder/example.txt + * @param ossFolder 如folder/example.txt * @param localFolder 如/path/to/local/example.txt * @return */ diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/page/utis/VideoUtil.java b/mall-shop/src/main/java/com/suisung/mall/shop/page/utis/VideoUtil.java index fdd310ba..9e73a93a 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/page/utis/VideoUtil.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/page/utis/VideoUtil.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Component; import java.awt.image.BufferedImage; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -24,14 +25,7 @@ import java.util.concurrent.TimeUnit; @Component public class VideoUtil { - private static Logger logger = LoggerFactory.getLogger(VideoUtil.class); - - @Value("${aliyun.oss.dir.prefix}") - private String ALIYUN_OSS_DIR_PREFIX; - - @Autowired - private OssService ossService; - + private static final Logger logger = LoggerFactory.getLogger(VideoUtil.class); public static List videoAllowFiles = new ArrayList() {{ add("flv"); add("swf"); @@ -51,6 +45,10 @@ public class VideoUtil { // add("wav"); // add("mid"); }}; + @Value("${aliyun.oss.dir.prefix}") + private String ALIYUN_OSS_DIR_PREFIX; + @Autowired + private OssService ossService; /** * 得到语音或视频文件时长,单位秒 并格式化 @@ -213,8 +211,7 @@ public class VideoUtil { int mm = (temp % 3600) / 60; int ss = (temp % 3600) % 60; - return hh != 0 ? ((hh < 10 ? ("0" + hh) : hh) + ":") : "" + - (mm < 10 ? ("0" + mm) : mm) + ":" + + return hh != 0 ? ((hh < 10 ? ("0" + hh) : hh) + ":") : (mm < 10 ? ("0" + mm) : mm) + ":" + (ss < 10 ? ("0" + ss) : ss); } @@ -227,24 +224,40 @@ public class VideoUtil { * @return */ public String getVideoCoverV2(String video, String dir, String uploadName) { - InputStream inputStream = OssUtils.urlToInputSteam(video); - FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream); try { - grabber.start(); - Frame frame = grabber.grabImage(); - Java2DFrameConverter converter = new Java2DFrameConverter(); - BufferedImage bufferedImage = converter.convert(frame); - Map map = OssUtils.toStreamMap(bufferedImage); - grabber.stop(); - InputStream stream = (InputStream) map.get("stream"); - Long file_size = Convert.toLong(map.get("file_size")); + InputStream inputStream = OssUtils.urlToInputSteam(video); + FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream); + try { + grabber.start(); + Frame frame = grabber.grabImage(); + Java2DFrameConverter converter = new Java2DFrameConverter(); + BufferedImage bufferedImage = converter.convert(frame); + Map map = OssUtils.toStreamMap(bufferedImage); + grabber.stop(); + InputStream stream = (InputStream) map.get("stream"); + Long file_size = Convert.toLong(map.get("file_size")); - // 上传至oos,返回文件地址 - return ossService.uploadObject2OSS(null, ALIYUN_OSS_DIR_PREFIX.concat("/").concat(dir).concat(uploadName), stream, uploadName, file_size); - } catch (IOException e) { - logger.error("失败原因:", e); + // 上传至oos,返回文件地址 + return ossService.uploadObject2OSS(null, ALIYUN_OSS_DIR_PREFIX.concat("/").concat(dir).concat(uploadName), stream, uploadName, file_size); + } catch (IOException e) { + logger.error("处理视频封面失败:", e); + } finally { + try { + if (grabber != null) { + grabber.stop(); + } + } catch (Exception e) { + logger.warn("关闭视频抓取器失败:", e); + } + } + } catch (UnsatisfiedLinkError e) { + logger.error("JavaCV本地库加载失败,请检查平台依赖配置:", e); + } catch (NoClassDefFoundError e) { + logger.error("JavaCV类初始化失败,请检查依赖配置:", e); + } catch (Exception e) { + logger.error("获取视频封面时发生未知异常:", e); } - return null; + return ""; } } @@ -255,7 +268,7 @@ class InputStreamRunnable extends Thread { public InputStreamRunnable(InputStream is, String _type) { try { - bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), "UTF-8")); + bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), StandardCharsets.UTF_8)); type = _type; } catch (Exception ex) { ex.printStackTrace();