java截取视频的帧

淩亂°似流年 2022-10-27 05:22 335阅读 0赞

使用javacv获取视频(本地视频文件、视频链接)中的帧,保存成图片或者base64串

POM文件引入依赖

  1. <dependency>
  2. <groupId>org.bytedeco</groupId>
  3. <artifactId>javacv</artifactId>
  4. <version>1.4.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.bytedeco</groupId>
  8. <artifactId>javacpp</artifactId>
  9. <version>1.4.1</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.bytedeco.javacpp-presets</groupId>
  13. <artifactId>opencv-platform</artifactId>
  14. <version>3.4.1-1.4.1</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.bytedeco.javacpp-presets</groupId>
  18. <artifactId>ffmpeg-platform</artifactId>
  19. <version>3.4.2-1.4.1</version>
  20. </dependency>

提取视频帧

  1. package com.mf.video;
  2. import org.bytedeco.javacv.FFmpegFrameGrabber;
  3. import org.bytedeco.javacv.Frame;
  4. import org.bytedeco.javacv.Java2DFrameConverter;
  5. import sun.misc.BASE64Decoder;
  6. import sun.misc.BASE64Encoder;
  7. import javax.imageio.ImageIO;
  8. import java.awt.image.BufferedImage;
  9. import java.io.ByteArrayOutputStream;
  10. import java.io.File;
  11. import java.io.FileOutputStream;
  12. import java.util.*;
  13. import java.util.List;
  14. /**
  15. * @Author KeXin
  16. * @Date 2021/2/1 下午3:07
  17. **/
  18. public class VideoUtil {
  19. /**
  20. * base64字符串转换成图片
  21. * @param imgStr base64字符串
  22. * @param imgFilePath 图片存放路径
  23. */
  24. private static void base64ToImage(String imgStr, String imgFilePath) {
  25. try {
  26. byte[] buffer = new BASE64Decoder().decodeBuffer(imgStr);
  27. FileOutputStream out = new FileOutputStream(imgFilePath);
  28. out.write(buffer);
  29. out.close();
  30. }catch (Exception e){
  31. e.printStackTrace();
  32. }
  33. }
  34. /**
  35. * 将截取的帧生成文件或者生成base64
  36. * @param frame
  37. * @return
  38. */
  39. private static String getBase64FromFrame(Frame frame) {
  40. String imgFormat = "jpg";
  41. Java2DFrameConverter converter = new Java2DFrameConverter();
  42. BufferedImage srcBi = converter.getBufferedImage(frame);
  43. // 可以选择对截取的帧进行等比例缩放
  44. // int owidth = srcBi.getWidth();
  45. // int oheight = srcBi.getHeight();
  46. // int width = 800;
  47. // int height = (int) (((double) width / owidth) * oheight);
  48. // BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
  49. // bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
  50. try {
  51. ByteArrayOutputStream output = new ByteArrayOutputStream();
  52. // ImageIO工具类提供了将图片写成文件或者outputStream中
  53. // ImageIO.write(bi, imgFormat, targetFile);
  54. ImageIO.write(srcBi, imgFormat, output);
  55. // 这里需要获取图片的base64数据串,所以将图片写到流里面
  56. return new BASE64Encoder().encode(output.toByteArray());
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. return null;
  61. }
  62. /**
  63. * 获取指定视频的帧并保存为图片至指定目录
  64. *
  65. * @param fileUrl 源视频文件Url路径
  66. * @param stepSecond 每隔几秒取一帧,默认1200s
  67. * @param count 最多获取几帧
  68. * @return 返回截取的帧的Base64串列表
  69. * @throws Exception
  70. */
  71. public static List<String> fetchPicFromVideo(String fileUrl, Integer stepSecond, Integer count) throws Exception {
  72. List<String> picBase64List = new ArrayList<>();
  73. stepSecond = stepSecond == null ? 1200 : stepSecond;
  74. FFmpegFrameGrabber ff = new FFmpegFrameGrabber(fileUrl);
  75. ff.start();
  76. long timeLength = ff.getLengthInTime();
  77. Frame frame = ff.grabImage();
  78. long startTime = frame.timestamp;
  79. long timestamp = 0;
  80. int second = 0;
  81. int picNum = 0;
  82. while (timestamp <= timeLength) {
  83. timestamp = startTime + second * 1000000L;
  84. ff.setTimestamp(timestamp);
  85. frame = ff.grabImage();
  86. if (frame != null) {
  87. if (frame.image != null) {
  88. picBase64List.add(getBase64FromFrame(frame));
  89. picNum++;
  90. if (count != null && picNum == count) {
  91. break;
  92. }
  93. }
  94. }
  95. second += stepSecond;
  96. }
  97. ff.stop();
  98. return picBase64List;
  99. }
  100. public static void main(String[] args) {
  101. try {
  102. String outputPath = "/Users/kexin/work/projects/learn/MavenUtil/output";
  103. String videoPath = "https:*********165dd278762865.mp4";
  104. List<String> files = VideoUtil.fetchPicFromVideo(videoPath, 600, 8);
  105. // 为了验证base64串的正确性,解码生成图片文件
  106. for (String imgBase64 : files) {
  107. String fileName = String.valueOf(System.currentTimeMillis());
  108. String targetFile = outputPath + File.separator + fileName + ".jpg";
  109. base64ToImage(imgBase64, targetFile);
  110. }
  111. } catch (Exception e) {
  112. e.printStackTrace();
  113. }
  114. }
  115. }

发表评论

表情:
评论列表 (有 0 条评论,335人围观)

还没有评论,来说两句吧...

相关阅读