Генерация видеофайла MP4 по последовательности изображений PNG в Java 8 - PullRequest
0 голосов
/ 19 марта 2019

После тестирования нескольких инструментов для Windows 10, обнаруженных в сети, у меня возникли большие трудности с поиском такого инструмента, который мог бы переносить около 5000 изображений PNG в последовательности и преобразовывать его в видео, которое передавалось со скоростью, которую я хотел.Я потратил много времени на то, что, по-видимому, просто.

Известный ffmpeg был бы хорошей альтернативой, но он не работал на моей Windows 10 (разрешение отклонено).Я тестировал много свободного программного обеспечения, но большая его часть аварийно закрывалась или закрывалась.

Пока другие не предложат здесь хорошее решение, желательно бесплатное, я опубликую свой ответ ниже с решением, построенным на самой Java 8..

1 Ответ

0 голосов
/ 19 марта 2019

Ниже мое простое решение в Java 8 с использованием NIO и JCodec.

  1. JCodec maven зависимости

    <dependency>
        <groupId>org.jcodec</groupId>
        <artifactId>jcodec</artifactId>
        <version>0.2.2</version>
    </dependency>
    <dependency>
        <groupId>org.jcodec</groupId>
        <artifactId>jcodec-javase</artifactId>
        <version>0.2.2</version>
    </dependency>
    
  2. JCodecPNGtoMP4.java source

    /**
     * Using NIO e JCodec to convert multiple sequence png images to mp4 video file
     * Copyright (C) 2019  Leonardo Pereira (www.leonardopereira.com.br)
     *
     * This program is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.nio.file.DirectoryStream;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.List;
    
    import javax.imageio.ImageIO;
    
    import org.jcodec.api.awt.AWTSequenceEncoder;
    import org.jcodec.common.io.NIOUtils;
    import org.jcodec.common.io.SeekableByteChannel;
    import org.jcodec.common.model.Rational;
    
    /**
     * @author Leonardo Pereira
     * 18/03/2019 23:01
     */
    public class JCodecPNGtoMP4 {
    
        private static void sortByNumber(File[] files) {
            Arrays.sort(files, new Comparator<File>() {
                @Override
                public int compare(File o1, File o2) {
                    int n1 = extractNumber(o1.getName());
                    int n2 = extractNumber(o2.getName());
                    return n1 - n2;
                }
                private int extractNumber(String name) {
                    int i = 0;
                    try {
                        int s = name.lastIndexOf('_')+1;
                        int e = name.lastIndexOf('.');
                        String number = name.substring(s, e);
                        i = Integer.parseInt(number);
                    } catch(Exception e) {
                        i = 0; // if filename does not match the format then default to 0
                    }
                    return i;
                }
            });
            /*
            for(File f : files) {
                System.out.println(f.getName());
            }
            */
        }
    
        private static void generateVideoBySequenceImages(String videoFilename, String pathImages, String imageExt) throws Exception {
            SeekableByteChannel out = null;
            try {
                out = NIOUtils.writableFileChannel(videoFilename);
    
                // for Android use: AndroidSequenceEncoder
                AWTSequenceEncoder encoder = new AWTSequenceEncoder(out, Rational.R(25, 1));
    
                Path directoryPath = Paths.get(new File(pathImages).toURI());
    
                if (Files.isDirectory(directoryPath)) {
                    DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath, "*." + imageExt);
    
                    List<File> filesList = new ArrayList<File>();
                    for (Path path : stream) {
                        filesList.add(path.toFile());
                    }
                    File[] files = new File[filesList.size()];
                    filesList.toArray(files);
    
                    sortByNumber(files);
    
                    for (File img : files) {
                        System.err.println("Encoding image " + img.getName());
                        // Generate the image, for Android use Bitmap
                        BufferedImage image = ImageIO.read(img);
                        // Encode the image
                        encoder.encodeImage(image);
                    }
                }
                // Finalize the encoding, i.e. clear the buffers, write the header, etc.
                encoder.finish();
            } finally {
                NIOUtils.closeQuietly(out);
            }
        }
    
        public static void main(String[] args) throws Exception {
            String videoFilename = "C:/outputVideo.mp4";
            String pathImages = "C:/pathImages";
            generateVideoBySequenceImages(videoFilename, pathImages, "png");
        }
    }
    
...