在Java 8中通过序列PNG图像生成MP4视频文件

问题描述 投票:0回答:1

在为网络上的Windows 10测试了几个工具之后,我很难找到一个可以按顺序传输大约5,000个PNG图像的工具并将其转换为以我想要的速度传输的视频。我浪费了很多时间在一些显然很简单的事情上。

已知的ffmpeg将是一个不错的选择,但它在我的Windows 10上无效(权限被拒绝)。我测试了很多免费软件,但其中大部分突然崩溃或关闭。

直到其他人可以在这里提出一个好的解决方案,最好是免费的,我将在下面发布我的答案,使用基于Java 8本身的解决方案。

java png nio mp4 jcodec
1个回答
0
投票

下面是我在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源码 /** * 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"); } }
© www.soinside.com 2019 - 2024. All rights reserved.