当前位置:   article > 正文

Java实现文件上传截取视频首图 @杨章隐_java截取视频第一帧

java截取视频第一帧

我们在很多项目中实现过上传视频,为了展示视频,我们经常会有获取视频第一帧作为视频封面的操作,以下就是获取视频第一帧的代码实现。

一般情况下,作为服务端的开发者,一个需求有两种大概的实现方向:

  (1、自己实现

(2、甩锅给前端

1、依赖

  1. <!-- 获取视频第一帧依赖 -->
  2. <dependency>
  3. <groupId>org.bytedeco</groupId>
  4. <artifactId>javacpp</artifactId>
  5. <version>1.4.1</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.bytedeco</groupId>
  9. <artifactId>javacv</artifactId>
  10. <version>1.4.1</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.bytedeco.javacpp-presets</groupId>
  14. <artifactId>opencv-platform</artifactId>
  15. <version>3.4.1-1.4.1</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.bytedeco.javacpp-presets</groupId>
  19. <artifactId>ffmpeg-platform</artifactId>
  20. <version>3.4.2-1.4.1</version>
  21. </dependency>

2、实际代码实现(截取第一帧,详情留意代码注释)

  1. /**
  2. *
  3. * @ClassName: FileUtil
  4. * @Description: 文件管理
  5. * @author: Zing
  6. * @date: 2019年12月11日 上午11:55:40
  7. * @Copyright:
  8. */
  9. public class FileUtil {
  10. /**
  11. *
  12. * @Title: getTempPath
  13. * @Description: 生成视频的首帧图片方法
  14. * @author: Zing
  15. * @param: @param tempPath 生成首帧图片的文件地址
  16. * @param: @param filePath 传进来的线上文件
  17. * @param: @return
  18. * @param: @throws Exception
  19. * @return: boolean
  20. * @throws
  21. */
  22. public static boolean getTempPath(String tempPath, String filePath) throws Exception {
  23. File targetFile = new File(tempPath);
  24. if (!targetFile.getParentFile().exists()) {
  25. targetFile.getParentFile().mkdirs();
  26. }
  27. File file2 = new File(filePath);
  28. //判断文件是否为视频
  29. if(FileUtil.isVideo("filePath")) {
  30. if (file2.exists()) {
  31. FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file2);
  32. ff.start();
  33. int ftp = ff.getLengthInFrames();
  34. int flag=0;
  35. Frame frame = null;
  36. while (flag <= ftp) {
  37. //获取帧
  38. frame = ff.grabImage();
  39. //过滤前3帧,避免出现全黑图片
  40. if ((flag>3)&&(frame != null)) {
  41. break;
  42. }
  43. flag++;
  44. }
  45. if(ImageIO.write(FrameToBufferedImage(frame), "jpg", targetFile)) {
  46. ff.close();
  47. ff.stop();
  48. return true;
  49. }else {
  50. ff.close();
  51. ff.stop();
  52. return false;
  53. }
  54. }
  55. }
  56. return false;
  57. }
  58. /***
  59. *
  60. * @Title: FrameToBufferedImage
  61. * @Description: 创建格式化BufferedImage对象
  62. * @author: Zing
  63. * @param: @param frame
  64. * @param: @return
  65. * @return: RenderedImage
  66. * @throws
  67. */
  68. private static RenderedImage FrameToBufferedImage(Frame frame) {
  69. //创建BufferedImage对象
  70. Java2DFrameConverter converter = new Java2DFrameConverter();
  71. BufferedImage bufferedImage = converter.getBufferedImage(frame);
  72. return bufferedImage;
  73. }
  74. /**
  75. *
  76. * @Title: isVideo
  77. * @Description:判断是不是视频
  78. * @author: Zing
  79. * @param: @param path 文件路径
  80. * @param: @return
  81. * @return: boolean true是视频 false非视频
  82. * @throws
  83. */
  84. public static boolean isVideo(String path) {
  85. List<String> typeList = new ArrayList<String>();
  86. typeList.add("mp4");
  87. typeList.add("flv");
  88. typeList.add("avi");
  89. typeList.add("rmvb");
  90. typeList.add("rm");
  91. typeList.add("wmv");
  92. //获取文件名和后缀
  93. String suffix = path.substring(path.lastIndexOf(".") + 1);
  94. for(String type : typeList) {
  95. if(type.toUpperCase().equals(suffix.toUpperCase())) {
  96. return true;
  97. }
  98. }
  99. return false;
  100. }
  101. /**
  102. *
  103. * @Title: isVideo
  104. * @Description: 判断是不是图片
  105. * @author: Zing
  106. * @param: @param path 文件路径
  107. * @param: @return
  108. * @return: boolean true是图片 false非图片
  109. * @throws
  110. */
  111. public static boolean isImage(String path) {
  112. List<String> typeList = new ArrayList<String>();
  113. typeList.add("jpg");
  114. typeList.add("png");
  115. //获取文件名和后缀
  116. String suffix = path.substring(path.lastIndexOf(".") + 1);
  117. for(String type : typeList) {
  118. if(type.toUpperCase().equals(suffix.toUpperCase())) {
  119. return true;
  120. }
  121. }
  122. return false;
  123. }
  124. }

应用场景和架构设计建议:这一部分其实完全可以抽离出来做异步或者MQ消费,把异步执行的结果回传到我们视频结果里面。

例如在MQ场景下,我们可以将视频上传和处理进行结束后发送MQ消息,MQ消费者在接收到对应的MQ消息后,对库表中存在的文件资源地址进行解析参考我的另一篇文章:

网络地址 URL 文件转MultipartFileicon-default.png?t=M85Bhttps://blog.csdn.net/weixin_41719650/article/details/119914300?spm=1001.2014.3001.5501然后再通过该方法进行流处理,获取第一张图片后回写到数据库进行保存。这样可以保证主业务解耦,还有主服务器流对象的内存控制。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/650463
推荐阅读
相关标签
  

闽ICP备14008679号