From 7e9972d25b3d035201331d401c8e1a74d8f2d8e8 Mon Sep 17 00:00:00 2001 From: zxl <763096477@qq.com> Date: 星期二, 12 八月 2025 17:11:23 +0800 Subject: [PATCH] 分享适配 --- framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java | 26 ++++++++ framework/pom.xml | 10 +++ framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java | 2 framework/src/main/java/cn/lili/utils/COSUtil.java | 99 +++++++++++++++++++++++++++++++++ common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java | 5 + 5 files changed, 142 insertions(+), 0 deletions(-) diff --git a/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java b/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java index 501a4ea..1ab33ec 100644 --- a/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java +++ b/common-api/src/main/java/cn/lili/controller/lmk/LmkFileController.java @@ -43,6 +43,11 @@ return lmkFileService.uploadObject(file); } + @GetMapping("/generateVideoCoverUrl/{id}") + public Result generateVideoCoverUrl(@PathVariable("id") String videoId){ + return lmkFileService.generateVideoCoverUrl(videoId,null,null,null); + } + /** * 澶氭枃浠朵笂浼� diff --git a/framework/pom.xml b/framework/pom.xml index fbe9bf9..c746ce1 100644 --- a/framework/pom.xml +++ b/framework/pom.xml @@ -15,6 +15,16 @@ <packaging>jar</packaging> <dependencies> + <dependency> + <groupId>org.bytedeco</groupId> + <artifactId>javacv-platform</artifactId> + <version>1.5.9</version> + </dependency> + <dependency> + <groupId>org.bytedeco</groupId> + <artifactId>ffmpeg-platform</artifactId> + <version>6.0-1.5.9</version> + </dependency> <!-- cos sts --> <dependency> <groupId>com.qcloud</groupId> diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java b/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java index bdc3b61..e2ea3ea 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/LmkFileService.java @@ -18,6 +18,8 @@ */ public interface LmkFileService extends IService<LmkFile> { + Result generateVideoCoverUrl(String videoId, Long snapshotTime, Integer width, Integer height); + /** * 涓婁紶鍗曚釜鏂囦欢 * diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java index 4076c84..8b2c67e 100644 --- a/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/LmkFileServiceImpl.java @@ -2,11 +2,14 @@ import cn.lili.base.Result; import cn.lili.common.exception.ServiceException; +import cn.lili.common.utils.StringUtils; import cn.lili.cos.CosSTS; import cn.lili.modules.lmk.domain.entity.LmkFile; +import cn.lili.modules.lmk.domain.entity.Video; import cn.lili.modules.lmk.domain.form.FileInfoForm; import cn.lili.modules.lmk.domain.vo.LmkFileVO; import cn.lili.modules.lmk.mapper.LmkFileMapper; +import cn.lili.modules.lmk.mapper.VideoMapper; import cn.lili.modules.lmk.service.LmkFileService; import cn.lili.utils.COSUtil; import cn.lili.utils.FileUtil; @@ -35,6 +38,29 @@ private final LmkFileMapper lmkFileMapper; private final COSUtil cosUtil; + private final VideoMapper videoMapper; + @Override + public Result generateVideoCoverUrl(String videoId, Long snapshotTime, Integer width, Integer height){ + Video video = videoMapper.selectById(videoId); + if (video != null){ + if (StringUtils.isNotBlank(video.getCoverUrl())){ + return Result.ok().data(cosUtil.getPreviewUrl(video.getCoverUrl())); + } + //鑾峰緱videoKey + try { + System.out.println(video.getVideoFileKey()); + MultipartFile file =cosUtil.captureVideoCoverAsMultipart(cosUtil.getPreviewUrl(video.getVideoFileKey()), width, height); + LmkFileVO fileVo = (LmkFileVO) this.uploadObject(file).get("data"); + video.setCoverUrl(fileVo.getFileKey()); + videoMapper.updateById(video); + return Result.ok().data(fileVo.getUrl()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + return Result.ok(); + } @Override public Result uploadObject(MultipartFile file) { diff --git a/framework/src/main/java/cn/lili/utils/COSUtil.java b/framework/src/main/java/cn/lili/utils/COSUtil.java index c6b5731..6c19fa4 100644 --- a/framework/src/main/java/cn/lili/utils/COSUtil.java +++ b/framework/src/main/java/cn/lili/utils/COSUtil.java @@ -18,9 +18,15 @@ import com.tencent.cloud.cos.util.Jackson; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.CollectionUtils; +import org.bytedeco.javacv.*; +import org.bytedeco.opencv.global.opencv_imgproc; +import org.bytedeco.opencv.opencv_core.Mat; +import org.bytedeco.opencv.opencv_core.Size; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URL; @@ -39,6 +45,99 @@ private final COSConfigProperty cosConfigProperty; /** + * 浠庣綉缁滆棰慤RL鎴彇绗竴绉掔敾闈紝杩斿洖MultipartFile绫诲瀷 + * @param videoUrl 缃戠粶瑙嗛鍦板潃 + * @param width 灏侀潰瀹藉害 + * @param height 灏侀潰楂樺害 + * @return 灏侀潰鍥剧墖鐨凪ultipartFile瀵硅薄 + * @throws Exception 澶勭悊寮傚父 + */ + public MultipartFile captureVideoCoverAsMultipart(String videoUrl, Integer width, Integer height) throws Exception { + // 璁剧疆榛樿瀹介珮 + int targetWidth = width != null && width > 0 ? width : 800; + int targetHeight = height != null && height > 0 ? height : 600; + + // 鐢熸垚鍞竴鏂囦欢鍚嶏紙鐢ㄤ簬MultipartFile鐨勫師濮嬫枃浠跺悕锛� + String fileName = UUID.randomUUID().toString() + ".jpg"; + + // 浣跨敤鍐呭瓨娴佸鐞嗗浘鐗囷紝閬垮厤涓存椂鏂囦欢 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + FFmpegFrameGrabber grabber = null; + + try { + // 鍒濆鍖栬棰戞姄鍙栧櫒 + grabber = new FFmpegFrameGrabber(videoUrl); + grabber.start(); + + // 瀹氫綅鍒扮涓�绉� + grabber.setTimestamp(1000000); // 1绉� = 1,000,000寰 + + // 鑾峰彇瑙嗛甯� + Frame frame = grabber.grabImage(); + if (frame == null) { + throw new RuntimeException("鏃犳硶鑾峰彇瑙嗛甯э紝鍙兘瑙嗛鏍煎紡涓嶆敮鎸佹垨URL鏃犳晥"); + } + + // 杞崲涓篗at骞惰皟鏁村昂瀵� + OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat(); + Mat mat = converter.convert(frame); + Mat resizedMat = new Mat(); + opencv_imgproc.resize(mat, resizedMat, new Size(targetWidth, targetHeight)); + + // 灏嗗鐞嗗悗鐨勫抚鍐欏叆鍐呭瓨娴� + Java2DFrameConverter java2dConverter = new Java2DFrameConverter(); + ImageIO.write( + java2dConverter.getBufferedImage(converter.convert(resizedMat)), + "jpg", + outputStream + ); + + // 灏嗗唴瀛樻祦杞崲涓篗ultipartFile + ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); + return new MockMultipartFile( + "file", // 琛ㄥ崟瀛楁鍚嶏紙鍙嚜瀹氫箟锛� + fileName, // 鍘熷鏂囦欢鍚� + "image/jpeg", // 鏂囦欢绫诲瀷 + inputStream // 鏂囦欢娴� + ); + } finally { + // 閲婃斁璧勬簮 + if (grabber != null) { + try { + grabber.stop(); + grabber.release(); + } catch (Exception e) { + e.printStackTrace(); + } + } + outputStream.close(); + } + } + + + + + /** + * 浠庡畬鏁碪RL涓彁鍙朇OS鏂囦欢key + * @param fullUrl 瀹屾暣URL + * @return COS鏂囦欢key + */ + public String extractFileKeyFromUrl(String fullUrl) { + // 鍘婚櫎鍗忚鍜屽煙鍚嶉儴鍒� + String endpoint = cosConfigProperty.getEndpoint(); + if (fullUrl.startsWith(endpoint)) { + return fullUrl.substring(endpoint.length() + 1); + } + // 濡傛灉URL鍖呭惈bucket鍚嶇О + String bucketUrl = "https://" + cosConfigProperty.getBucket() + "." + endpoint; + if (fullUrl.startsWith(bucketUrl)) { + return fullUrl.substring(bucketUrl.length() + 1); + } + // 濡傛灉宸茬粡鏄浉瀵硅矾寰勶紝鐩存帴杩斿洖 + return fullUrl; + } + + /** * 鑾峰彇sts涓存椂璁块棶鍑瘉 * * @return -- Gitblit v1.8.0