Bläddra i källkod

媒体相关工具类

reghao 2 år sedan
förälder
incheckning
298b4008d5

+ 13 - 0
media/pom.xml

@@ -23,6 +23,19 @@
             <version>1.0.0-SNAPSHOT</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.6</version>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.sejda.imageio</groupId>
+            <artifactId>webp-imageio</artifactId>
+            <version>0.1.6</version>
+        </dependency>
+
         <dependency>
             <groupId>org.bytedeco</groupId>
             <artifactId>javacv</artifactId>

+ 33 - 13
media/src/main/java/cn/reghao/jutil/media/image/ImageOps.java

@@ -20,17 +20,26 @@ import java.util.List;
  * @date 2021-08-04 16:26:13
  */
 public class ImageOps {
-    public static byte[] convert(File srcFile, String destFormat) {
-        String srcFormat = getFormat(srcFile);
-        if (srcFormat != null && srcFormat.equals(destFormat)) {
-            return new byte[0];
+    public static String getFormat(File file) {
+        try (ImageInputStream iis = ImageIO.createImageInputStream(file);) {
+            Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
+            if ((iterator.hasNext())) {
+                ImageReader ir = iterator.next();
+                return ir.getFormatName();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
         }
 
+        return null;
+    }
+
+    public static byte[] convert2jpg(File srcFile) {
         try (ImageInputStream iis = ImageIO.createImageInputStream(srcFile)) {
             BufferedImage image = ImageIO.read(iis);
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
-            ImageIO.write(image, destFormat, ios);
+            ImageIO.write(image, "jpg", ios);
             return baos.toByteArray();
         } catch (Exception e) {
             e.printStackTrace();
@@ -38,18 +47,29 @@ public class ImageOps {
         return new byte[0];
     }
 
-    public static String getFormat(File file) {
-        try (ImageInputStream iis = ImageIO.createImageInputStream(file);) {
-            Iterator<ImageReader> iterator = ImageIO.getImageReaders(iis);
-            if ((iterator.hasNext())) {
-                ImageReader ir = iterator.next();
-                return ir.getFormatName();
-            }
+    public static byte[] png2jpg(File srcFile) {
+        try {
+            BufferedImage image = ImageIO.read(srcFile);
+            BufferedImage result = new BufferedImage(
+                    image.getWidth(),
+                    image.getHeight(),
+                    BufferedImage.TYPE_INT_RGB);
+            result.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ImageIO.write(result, "jpg", baos);
+            return baos.toByteArray();
         } catch (Exception e) {
             e.printStackTrace();
         }
+        return new byte[0];
+    }
 
-        return null;
+    public static byte[] jpg2webp(byte[] bytes) throws IOException {
+        BufferedImage bi = ImageIO.read(new ByteArrayInputStream(bytes));
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ImageIO.write(bi, "webp", baos);
+        return baos.toByteArray();
     }
 
     public static Size info(File file) throws IOException {

+ 17 - 0
media/src/main/java/cn/reghao/jutil/media/po/AudioInfo.java

@@ -0,0 +1,17 @@
+package cn.reghao.jutil.media.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2023-03-28 10:07:48
+ */
+@AllArgsConstructor
+@Getter
+public class AudioInfo {
+    private String codecName;
+    private String codecTagString;
+    private double bitRate;
+    private double duration;
+}

+ 23 - 0
media/src/main/java/cn/reghao/jutil/media/po/MediaInfo.java

@@ -0,0 +1,23 @@
+package cn.reghao.jutil.media.po;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author reghao
+ * @date 2023-03-28 10:07:59
+ */
+@Getter
+@Setter
+public class MediaInfo {
+    private AudioInfo audioInfo;
+    private VideoInfo videoInfo;
+    private LocalDateTime createTime;
+
+    public MediaInfo(AudioInfo audioInfo, VideoInfo videoInfo) {
+        this.audioInfo = audioInfo;
+        this.videoInfo = videoInfo;
+    }
+}

+ 19 - 0
media/src/main/java/cn/reghao/jutil/media/po/VideoInfo.java

@@ -0,0 +1,19 @@
+package cn.reghao.jutil.media.po;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2023-03-28 10:07:53
+ */
+@AllArgsConstructor
+@Getter
+public class VideoInfo {
+    private String codecName;
+    private String codecTagString;
+    private double bitRate;
+    private double duration;
+    private double codedWidth;
+    private double codedHeight;
+}

+ 3 - 1
media/src/main/java/cn/reghao/jutil/media/video/VideoOps.java

@@ -22,6 +22,9 @@ import java.util.*;
  * @date 2021-08-04 09:51:30
  */
 public class VideoOps {
+    static String bash = "/bin/bash";
+    static String ffprobe = "/usr/bin/ffprobe";
+    static String ffmpeg = "/usr/bin/ffmpeg";
     static {
         avutil.av_log_set_level(avutil.AV_LOG_QUIET);
     }
@@ -36,7 +39,6 @@ public class VideoOps {
      * @date 2023-02-06 5:55 AM
      */
     public static Map<String, String> getMetadata(String filePath) throws IOException {
-        VideoOps.videoProps(new File(filePath));
         Map<String, String> metadata = new HashMap<>();
         AVFormatContext fmt_ctx = new AVFormatContext(null);
         AVDictionaryEntry tag = new AVDictionaryEntry(null);

+ 250 - 5
media/src/test/java/ImageTest.java

@@ -1,14 +1,259 @@
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.jutil.jdk.serializer.JsonConverter;
+import cn.reghao.jutil.media.image.ImageOps;
+import cn.reghao.jutil.media.po.AudioInfo;
+import cn.reghao.jutil.media.po.MediaInfo;
+import cn.reghao.jutil.media.po.VideoInfo;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
 import javax.imageio.ImageIO;
-import javax.imageio.ImageReader;
-import javax.imageio.stream.ImageInputStream;
-import javax.imageio.stream.ImageOutputStream;
-import java.awt.image.BufferedImage;
 import java.io.*;
-import java.util.Iterator;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @author reghao
  * @date 2023-02-21 21:09:37
  */
 public class ImageTest {
+    static String bash = "/bin/bash";
+    static String file = "/bin/file";
+    static String ffprobe = "/usr/bin/ffprobe";
+    static String ffmpeg = "/usr/bin/ffmpeg";
+
+    static String fileInfo(String src) {
+        return String.format("%s -b \"%s\"", file, src);
+        //return String.format("%s -b -i \"%s\"", file, src);
+    }
+
+    static String probe(String src) {
+        return String.format("%s -v quiet -print_format json -show_format -show_streams -i \"%s\"", ffprobe, src);
+    }
+
+    static String covert(String src, String dest) {
+        return String.format("%s -y -i %s -c:a aac -c:v libx264 %s", ffmpeg, src, dest);
+    }
+
+    static String covert1(String src, int width, int height, String dest) {
+        String audioBitRate = "128k";
+        String videoBitRate = "1500k";
+        return String.format("%s -i %s -s %sx%s -c:a aac -b:a %s -c:v libx264 -b:v %s -g 90 %s",
+                ffmpeg, src, width, height, audioBitRate, videoBitRate, dest);
+    }
+
+    static String split(String src, String start, String duration, String dest) {
+        return String.format("%s -i %s -ss %s -t %s -vcodec copy -acodec copy %s", ffmpeg, src, start, duration, dest);
+    }
+
+    static void exec(String cmd) {
+        Runtime runtime = Runtime.getRuntime();
+        try {
+            Process proc = runtime.exec(new String[]{bash, "-c", cmd});
+            new Thread(new Output(proc)).start();
+            int status = proc.waitFor();
+            if (status != 0) {
+                System.out.println("失败");
+            }
+
+            proc.getOutputStream().close();
+            proc.getInputStream().close();
+            proc.getErrorStream().close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            runtime.freeMemory();
+        }
+    }
+
+    static String execWithResult(String cmd) {
+        Runtime runtime = Runtime.getRuntime();
+        try {
+            Process proc = runtime.exec(new String[]{bash, "-c", cmd});
+            int status = proc.waitFor();
+            if (status != 0) {
+                return null;
+            }
+
+            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
+            StringBuilder sb = new StringBuilder();
+            try {
+                String line;
+                while((line = br.readLine()) != null){
+                    sb.append(line);
+                }
+                br.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+            proc.getOutputStream().close();
+            proc.getInputStream().close();
+            proc.getErrorStream().close();
+            return sb.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            runtime.freeMemory();
+        }
+        return null;
+    }
+
+    static Map<File, MediaInfo> map = new HashMap<>();
+    static void walkDir(String dirPath) throws IOException {
+        Path path = Path.of(dirPath);
+        Files.walkFileTree(path, new FileVisitor<>() {
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                File file1 = file.toFile();
+                String format = ImageOps.getFormat(file1);
+                if (format == null) {
+                    System.out.println("文件格式未知");
+                } else if (format.equalsIgnoreCase("jpg") || format.equalsIgnoreCase("jpeg")) {
+
+                } else {
+                    if (format.equalsIgnoreCase("png")) {
+                        System.out.printf("%s covert to jpg\n", format);
+                        byte[] bytes = ImageOps.png2jpg(file1);
+                        System.out.println();
+                    }
+                }
+
+                /*MediaInfo mediaInfo = getMediaInfo(file1);
+                map.put(file1, mediaInfo);*/
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                return FileVisitResult.CONTINUE;
+            }
+        });
+    }
+
+    static MediaInfo getMediaInfo(File file) {
+        String cmd = probe(file.getAbsolutePath());
+        String result = execWithResult(cmd);
+        if (result != null) {
+            JsonObject jsonObject = JsonConverter.jsonToJsonElement(result).getAsJsonObject();
+            JsonArray streams = jsonObject.get("streams").getAsJsonArray();
+            AudioInfo audioInfo = null;
+            VideoInfo videoInfo = null;
+            for (JsonElement jsonElement : streams) {
+                JsonObject jsonObject1 = jsonElement.getAsJsonObject();
+                String codecType = jsonObject1.get("codec_type").getAsString();
+                if (codecType.equals("audio")) {
+                    String codecName = jsonObject1.get("codec_name").getAsString();
+                    String codecTagString = jsonObject1.get("codec_tag_string").getAsString();
+                    double bitRate = jsonObject1.get("bit_rate").getAsDouble();
+                    double duration = jsonObject1.get("duration").getAsDouble();
+                    audioInfo = new AudioInfo(codecName, codecTagString, bitRate, duration);
+                } else if (codecType.equals("video")) {
+                    String codecName = jsonObject1.get("codec_name").getAsString();
+                    String codecTagString = jsonObject1.get("codec_tag_string").getAsString();
+                    double bitRate = jsonObject1.get("bit_rate").getAsDouble();
+                    double duration = jsonObject1.get("duration").getAsDouble();
+                    double codedWidth = jsonObject1.get("coded_width").getAsDouble();
+                    double codedHeight = jsonObject1.get("coded_height").getAsDouble();
+                    videoInfo = new VideoInfo(codecName, codecTagString, bitRate, duration, codedWidth, codedHeight);
+                }
+            }
+
+            JsonObject format = jsonObject.get("format").getAsJsonObject();
+            double duration = format.get("duration").getAsDouble();
+            double size = format.get("size").getAsDouble();
+            double bitRate = format.get("bit_rate").getAsDouble();
+
+            MediaInfo mediaInfo = new MediaInfo(audioInfo, videoInfo);
+            JsonObject tags = format.get("tags").getAsJsonObject();
+            JsonElement jsonElement = tags.get("creation_time");
+            if (jsonElement != null) {
+                String creationTime = jsonElement.getAsString();
+                LocalDateTime localDateTime = DateTimeConverter.localDateTime(creationTime);
+                mediaInfo.setCreateTime(localDateTime);
+            }
+
+            return mediaInfo;
+        }
+        return null;
+    }
+
+    static void test() throws IOException {
+        String readFormats[] = ImageIO.getReaderFormatNames();
+        String writeFormats[] = ImageIO.getWriterFormatNames();
+        //walkDir("/home/reghao/data/video/");
+        walkDir("/home/reghao/data/picture/");
+
+        /*String filePath1 = "/home/reghao/data/picture/2.png";
+        File file1 = new File(filePath1);
+        String format = ImageOps.getFormat(file1);
+        System.out.println();*/
+
+        map.forEach((file, mediaInfo) -> {
+            if (mediaInfo == null) {
+                return;
+            }
+
+            String audioCodec = mediaInfo.getAudioInfo().getCodecName();
+            String videoCodec = mediaInfo.getVideoInfo().getCodecName();
+            if (audioCodec.equals("aac") && videoCodec.equals("h264")) {
+                String result = execWithResult(fileInfo(file.getAbsolutePath()));
+                System.out.println();
+            } else {
+                String filePath = file.getAbsolutePath();
+                String filename = file.getName();
+                String cmd = covert(filePath, "/home/reghao/Downloads/0/" + filename);
+                exec(cmd);
+            }
+        });
+    }
+
+    public static void main(String[] args) throws IOException {
+        String src = "/home/reghao/Downloads/sxd.mp4";
+        String start = "00:00:00";
+        String duration = "00:02:00";
+        String dest = "/home/reghao/Downloads/sxd-1.mp4";
+
+        String cmd = split(src, start, duration, dest);
+        exec(cmd);
+    }
+
+    static class Output implements Runnable {
+        private final Process proc;
+
+        public Output(Process proc) {
+            this.proc = proc;
+        }
+
+        @Override
+        public void run() {
+            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
+            try {
+                String line;
+                while((line = br.readLine()) != null){
+                    System.out.println(line);
+                }
+                br.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
 }