gpt4 book ai didi

java - 无法将一系列 JPEG 图像编码为 MPEG 视频

转载 作者:行者123 更新时间:2023-12-02 05:04:06 26 4
gpt4 key购买 nike

我需要将 JPEG 图像转换为 MPEG 视频,并且能够轻松设置每帧显示的持续时间。

我尝试过 JMF、Xuggler 和 JCodec,但都有各自的问题。

我将感谢任何对 JMF 、 Xuggler 、 JCode 甚至 JavaCV 都有很好解释的解决方案(还没有尝试过)。

以下是我的编码尝试。

我的测试菜单和主菜单,用于测试 Xuggler 方法或 JCodec:

package com.conuretech.video_assembler;

import com.xuggle.xuggler.IContainerFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
*
* @author ANaim
*/
public class TestVideo {

public static void main (String [] args)
{
if (args[0].equalsIgnoreCase("1"))
{
System.out.println("Testing Xuggler ...");
Iterator<IContainerFormat> iterator = IContainerFormat.getInstalledOutputFormats().iterator();
while (iterator.hasNext())
{
System.out.println(iterator.next().toString());
}
System.out.println("Testing xuggler...");
//C:\Users\Public\Pictures\Sample_Pictures_2\1.jpg
XugglerJpegImagesToMpegVideo newjpegImagesToMpegVideo = new XugglerJpegImagesToMpegVideo();
newjpegImagesToMpegVideo.setFrameRate(25);
newjpegImagesToMpegVideo.setOutputFilenamePath("C:/Users/Public/Pictures/Sample_Pictures_2/video.mpg");
List<String> jpegImages = new ArrayList<String>();
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/1.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/2.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/3.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/4.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/5.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/6.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/7.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/8.jpg");
newjpegImagesToMpegVideo.setJpegFilePathList(jpegImages);
newjpegImagesToMpegVideo.convertJpegFramesToMpegVideo();
}
else if (args[0].equalsIgnoreCase("2"))

{
System.out.println("Testing JCodec...");
jCodecJpegImagesToMpegVideo newJCodecJpegImagesToMpegVideo = new jCodecJpegImagesToMpegVideo();
List<String> jpegImages = new ArrayList<String>();
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/1.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/2.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/3.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/4.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/5.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/6.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/7.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/8.jpg");
newJCodecJpegImagesToMpegVideo.setJpegFilePathList(jpegImages);
newJCodecJpegImagesToMpegVideo.convertJpegFramesToMpegVideo();

}
else
{

}

System.exit(0);
}

}

我的 pom.xml(包括 Xuggler 和 JCodec 依赖项):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.conuretech</groupId>
<artifactId>Video_Assembler</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Video_Assembler</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--<mainClass>com.conuretech.video_assembler.TestVideo</mainClass>-->
<mainClass>com.conuretech.video_assembler.MainApp</mainClass>
</properties>
<organization>
<!-- Used as the 'Vendor' for JNLP generation -->
<name>conuretech</name>
</organization>
<repositories>
<repository>
<id>xuggle repo</id>
<url>http://xuggle.googlecode.com/svn/trunk/repo/share/java/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId>
<version>0.1.9</version>
</dependency>
<dependency>
<groupId>xuggle</groupId>
<artifactId>xuggle-xuggler</artifactId>
<version>5.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>xuggle</groupId>
<artifactId>xuggle-utils</artifactId>
<version>1.22</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeScope>system</excludeScope>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/../bin/javafxpackager</executable>
<arguments>
<argument>-createjar</argument>
<argument>-nocss2bin</argument>
<argument>-appclass</argument>
<argument>${mainClass}</argument>
<argument>-srcdir</argument>
<argument>${project.build.directory}/classes</argument>
<argument>-outdir</argument>
<argument>${project.build.directory}</argument>
<argument>-outfile</argument>
<argument>${project.build.finalName}.jar</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>default-cli</id>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>${runfx.args}</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArguments>
<bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${java.home}/lib/jfxrt.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>

</project>

JMF 尝试 - 根据他们的数据格式网站,他们不支持 MPEG“写入”或仅编码“读取”解码,请参阅其格式 ( http://www.oracle.com/technetwork/java/javase/formats-138492.html )。

Xuggler 尝试 (XugglerJpegImagesToMpegVideo.java) –

package com.conuretech.video_assembler;

import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IContainerFormat;
import java.util.ArrayList;
import java.util.List;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;


/**
*
* @author ANaim
*/
public class XugglerJpegImagesToMpegVideo {


//how many frames will be displayed per minute
private int frameRate = 1;
//total number of frames to be assembled into a video file
private int numberOfFrames = 0;
//path to output mpeg video
private String outputFilenamePath = "";
//list of JPEG pictures to be converted
private List<String> jpegFilePathList = new ArrayList<String>();
private List<BufferedImage> jpegFileList = new ArrayList<BufferedImage>();

public void convertJpegFramesToMpegVideo() {
System.out.println("convertJpegFramesToMpegVideo");
// BufferedImage to store JPEG data from file
BufferedImage img = null;

IContainer container = IContainer.make();
IMediaWriter writer = null;
long startTime = 0;
//ISSUE - container.open() fails to open
if (container.open(getOutputFilenamePath(), IContainer.Type.WRITE, null) > 0)
{
writer = ToolFactory.makeWriter(getOutputFilenamePath(),container);

this.setNumberOfFrames(getJpegFilePathList().size());
}
else
{
throw new RuntimeException("class jpegImagesToMpegVideo,convertJpegFramesToMpegVideo(), failed to open");
}

File imgFile = null;
//loop to load data from paths to BufferedImage objects
for (int i = 0; i < jpegFilePathList.size(); i++)
{
imgFile = new File(getJpegFilePathList().get(i));
if (imgFile.exists())
{
//System.out.println("convertJpegFramesToMpegVideo, file path: "+imgFile.getPath()+" exists");
try
{

img = ImageIO.read(imgFile);

jpegFileList.add(img);
}
catch (IOException e) {
e.printStackTrace();
}
}
else
{
System.out.println("convertJpegFramesToMpegVideo, file path: "+imgFile.getPath()+" does not exist!");
}
}//end for to load path to images

long nextEncodeTime = 0L;
startTime = System.nanoTime();
//for loop to encode each BufferedImage
for (int i = 0; i < jpegFileList.size(); i++) {
System.out.println("convertJpegFramesToMpegVideo encode counter: "+i);

img = jpegFileList.get(i);
nextEncodeTime = System.nanoTime() - startTime;
//encode
writer.encodeVideo(0, img,nextEncodeTime, TimeUnit.NANOSECONDS);

try {
/*Duration of each image - sleep 1000 millisecs (1 sec)
in order to shift outcome of the next nextEncodeTime = System.nanoTime() - startTime calcultation
by 1 second in order to have each frame displayed for 1 sec*/
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(XugglerJpegImagesToMpegVideo.class.getName()).log(Level.SEVERE, null, ex);
}
}//end loop
// after encoding all BufferedImages close
writer.close();

}//end

public int getFrameRate() {
return frameRate;
}

public void setFrameRate(int frameRate) {
this.frameRate = frameRate;
}

public int getNumberOfFrames() {
return numberOfFrames;
}

public void setNumberOfFrames(int numberOfFrames) {
this.numberOfFrames = numberOfFrames;
}

public String getOutputFilenamePath() {
return outputFilenamePath;
}

public void setOutputFilenamePath(String outputFilenamePath) {
this.outputFilenamePath = outputFilenamePath;
}

public List<String> getJpegFilePathList() {
return jpegFilePathList;
}

public void setJpegFilePathList(List<String> jpegFilePathList) {
this.jpegFilePathList = jpegFilePathList;
}

}

问题-容器无法打开,以下是确切的代码片段:

//ISSUE - container.open() fails to open 
if (container.open(getOutputFilenamePath(), IContainer.Type.WRITE, null) > 0)
{
writer = ToolFactory.makeWriter(getOutputFilenamePath(),container);

this.setNumberOfFrames(getJpegFilePathList().size());
}

JCodec 尝试 (jCodecJpegImagesToMpegVideo.java):

对于jCodec,我有两种方法,首先使用内置的org.jcodec.api.SequenceEncoder,然后根据网上的其他帖子创建我自己的SequenceEncoder类,名为MySequenceEncoder,因为org.jcodec.api.SequenceEncoder没有任何方法设置每帧的持续时间。

package com.conuretech.video_assembler;

import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.jcodec.api.SequenceEncoder;
import org.jcodec.codecs.h264.H264Encoder;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;

/**
*
* @author ANaim
*/
public class jCodecJpegImagesToMpegVideo {

//list of JPEG pictures to be converted
private List<String> jpegFilePathList = new ArrayList<String>();
private List<BufferedImage> jpegFileList = new ArrayList<BufferedImage>();

public void convertJpegFramesToMpegVideo() {
System.out.println("convertJpegFramesToMpegVideo");
//TODO: make dimensions dynanmic

BufferedImage img = null;
File imgFile = null;
for (int i = 0; i < jpegFilePathList.size(); i++)
{
imgFile = new File(getJpegFilePathList().get(i));
if (imgFile.exists())
{
//System.out.println("convertJpegFramesToMpegVideo, file path: "+imgFile.getPath()+" exists");
try
{

img = ImageIO.read(imgFile);

jpegFileList.add(img);
}
catch (IOException e) {
e.printStackTrace();
}
}
else
{
System.out.println("convertJpegFramesToMpegVideo, file path: "+imgFile.getPath()+" does not exist!");
}
}//end for to load path to images


File outVideoFile = new File("C:/Users/Public/Pictures/Sample_Pictures_2/video.mp4");
//Class that encodes images to a video
try
{

/*Attempt # 1 using org.jcodec.api.SequenceEncoder - SequenceEncoder class does not have method to specify duration,fps,etc..
SequenceEncoder newSequenceEncoder = new SequenceEncoder(outVideoFile);*/

/*Attempt # 2 - MySequenceEncoder is based on JCodec SequenceEncoder class src from GitHub,
were on can have finer access regarding duration & fps via " outTrack.addFrame(new MP4Packet(result,25,1,1,frameNo,true,null,1,0));"
however there is no official documentation describing how to set outTrack.addFrame(new MP4Packet(result,25,1,1,frameNo,true,null,1,0));*/
MySequenceEncoder newSequenceEncoder = new MySequenceEncoder(outVideoFile);
//H264 (aka mpeg) encoder
H264Encoder encoder = new H264Encoder();

//JCode class that holds media data before final processing
Picture toEncode = null;
//for loop to convert images to mpeg video
System.out.println("SupportedColorSpaces: "+encoder.getSupportedColorSpaces()[0]);
for (int i=0; i<jpegFileList.size(); i++)
{
img = jpegFileList.get(i);

toEncode = makeFrame(img, encoder.getSupportedColorSpaces()[0]);
//encode
newSequenceEncoder.encodeNativeFrame(toEncode);


}//end loop
//end encoding close sequence
newSequenceEncoder.finish();
}
catch (IOException exc)
{
exc.printStackTrace();
}

}//end
//I took this code from Stackoverflow because JCodecs AWTUtil was deprecated and this method converts BufferedImage to Picture class
private Picture makeFrame(BufferedImage bi, ColorSpace cs)
{
DataBuffer imgdata = bi.getRaster().getDataBuffer();
int[] ypix = new int[imgdata.getSize()];
int[] upix = new int[ imgdata.getSize() >> 2 ];
int[] vpix = new int[ imgdata.getSize() >> 2 ];
int ipx = 0, uvoff = 0;

for (int h = 0; h < bi.getHeight(); h++) {
for (int w = 0; w < bi.getWidth(); w++) {
int elem = imgdata.getElem(ipx);
int r = 0x0ff & (elem >>> 16);
int g = 0x0ff & (elem >>> 8);
int b = 0x0ff & elem;
ypix[ipx] = ((66 * r + 129 * g + 25 * b) >> 8) + 16;
if ((0 != w % 2) && (0 != h % 2)) {
upix[uvoff] = (( -38 * r + -74 * g + 112 * b) >> 8) + 128;
vpix[uvoff] = (( 112 * r + -94 * g + -18 * b) >> 8) + 128;
uvoff++;
}
ipx++;
}
}
int[][] pix = { ypix, upix, vpix, null };
return new Picture(bi.getWidth(), bi.getHeight(), pix, cs);
}

public List<String> getJpegFilePathList() {
return jpegFilePathList;
}

public void setJpegFilePathList(List<String> jpegFilePathList) {
this.jpegFilePathList = jpegFilePathList;
}

public List<BufferedImage> getJpegFileList() {
return jpegFileList;
}

public void setJpegFileList(List<BufferedImage> jpegFileList) {
this.jpegFileList = jpegFileList;
}


}//end class

这是我的序列编码器(MySequenceEncoder.java),我从 JCodec 的 github 获取源代码:

package com.conuretech.video_assembler;

import org.jcodec.api.SequenceEncoder;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;

import org.jcodec.codecs.h264.H264Encoder;
import org.jcodec.codecs.h264.H264Utils;
import org.jcodec.common.NIOUtils;
import org.jcodec.common.SeekableByteChannel;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;
import org.jcodec.containers.mp4.Brand;
import org.jcodec.containers.mp4.MP4Packet;
import org.jcodec.containers.mp4.TrackType;
import org.jcodec.containers.mp4.muxer.FramesMP4MuxerTrack;
import org.jcodec.containers.mp4.muxer.MP4Muxer;
import org.jcodec.scale.ColorUtil;
import org.jcodec.scale.Transform;

public class MySequenceEncoder {


/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* @author The JCodec project
*
*/

private SeekableByteChannel ch;
private Picture toEncode;
private Transform transform;
private H264Encoder encoder;
private ArrayList<ByteBuffer> spsList;
private ArrayList<ByteBuffer> ppsList;
private FramesMP4MuxerTrack outTrack;
private ByteBuffer _out;
private int frameNo;
private MP4Muxer muxer;

public MySequenceEncoder(File out) throws IOException {
this.ch = NIOUtils.writableFileChannel(out);

// Muxer that will store the encoded frames
muxer = new MP4Muxer(ch, Brand.MP4);

// Add video track to muxer
outTrack = muxer.addTrack(TrackType.VIDEO, 25);

// Allocate a buffer big enough to hold output frames
_out = ByteBuffer.allocate(1920 * 1080 * 6);

// Create an instance of encoder
encoder = new H264Encoder();

// Transform to convert between RGB and YUV
transform = ColorUtil.getTransform(ColorSpace.RGB, encoder.getSupportedColorSpaces()[0]);

// Encoder extra data ( SPS, PPS ) to be stored in a special place of
// MP4
spsList = new ArrayList<ByteBuffer>();
ppsList = new ArrayList<ByteBuffer>();

}

public void encodeNativeFrame(Picture pic) throws IOException {
if (toEncode == null) {
toEncode = Picture.create(pic.getWidth(), pic.getHeight(), encoder.getSupportedColorSpaces()[0]);
}

// Perform conversion
transform.transform(pic, toEncode);

// Encode image into H.264 frame, the result is stored in '_out' buffer
_out.clear();
ByteBuffer result = encoder.encodeFrame(toEncode, _out);

// Based on the frame above form correct MP4 packet
spsList.clear();
ppsList.clear();
H264Utils.wipePS(result, spsList, ppsList);
H264Utils.encodeMOVPacket(result);

//ISSUE - Im not sure what values to supply to MP4Packet() in order to control the duration of each frame to 1 sec
outTrack.addFrame(new MP4Packet(result,25,1,1,frameNo,true,null,1,0));

frameNo++;
}

public void finish() throws IOException {
// Push saved SPS/PPS to a special storage in MP4
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList, 4));

// Write MP4 header and finalize recording
muxer.writeHeader();
NIOUtils.closeQuietly(ch);
}
}//end class

问题 - 无论使用 SequenceEncoder.java 还是 MySequenceEncoder.java,创建的视频都无法播放,也没有错误,视频打开但没有任何显示。

我也无法弄清楚要传递的正确参数是什么:

 outTrack.addFrame(new MP4Packet(result,25,1,1,frameNo,true,null,1,0));

如果有一个有效的 JMF、Xuggler、JCodec 或 JavaCV 解决方案,以及完整的说明和依赖信息,我们将不胜感激。

提前谢谢大家。

最佳答案

我终于找到了一个可行的解决方案,可以使用 Xuggler 库将 JPEG 图像转换为 MPEG 扩展名“.mp4”视频:

这是我修改后的“XugglerJpegImagesToMpegVideo.java”:

package com.conuretech.video_assembler;
import com.xuggle.mediatool.IMediaWriter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.xuggler.IContainer;
import java.util.ArrayList;
import java.util.List;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IRational;
/**
*
* @author Aryan Naim
* This class converts JPEG images to MPEG (.mp4) extension video using Xuggler library
*/
public class XugglerJpegImagesToMpegVideo {

//fps = how many frames will be displayed per sec, default 24
private int frameRate = 24;
//number of millisecs each frame will be displayed for the viewer , default 1000 millisecs
private long durationPerFrame = 1000;
//path to output mpeg video
private String outputFilenamePath = "";
//list of JPEG pictures to be converted
private List<String> jpegFilePathList = new ArrayList<String>();
//list of actual images in memory to be iterated through & encoded by Xuggler
private List<BufferedImage> jpegFileList = new ArrayList<BufferedImage>();

/* VERY IMPORTANT regarding setDurationPerFrame(), I noticed that fpr 24 fps ,
the expected duration fell short 15% or 150 millisec per 1 second,
therefore I adjusted this by adding 15% to the user specified duration,
For example 3000 millisec duration will be adjusted to 3450 millisecs.
This adjustment was even more severe for lower fps*/

public void setDurationPerFrame(long durationPerFrame) {
this.durationPerFrame = new Double(Math.ceil(durationPerFrame * 1.15)).longValue();
}

public long getDurationPerFrame() {
return durationPerFrame;
}
/*
Actual method that converts JPEG images to MPEG (.mp4) extension video using Xuggler library
*/
public void convertJpegFramesToMpegVideo() {
System.out.println("convertJpegFramesToMpegVideo, start...");
// BufferedImage to store JPEG data from file
BufferedImage img = null;
IContainer container = IContainer.make();
IMediaWriter writer = null;
long nextEncodeTime = getDurationPerFrame();
writer = ToolFactory.makeWriter(getOutputFilenamePath(), container);
//the framerate is set at 24 fps , could be adjusted
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4,IRational.make(frameRate),1024,768);

File imgFile = null;
//loop to load data from paths to BufferedImage objects
for (int i = 0; i < jpegFilePathList.size(); i++) {
imgFile = new File(getJpegFilePathList().get(i));
if (imgFile.exists()) {

try {

img = ImageIO.read(imgFile);

jpegFileList.add(img);
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("convertJpegFramesToMpegVideo, file path: " + imgFile.getPath() + " does not exist!");
}
}//end for to load path to images


//for loop to encode each BufferedImage
for (int i = 0; i <jpegFileList.size(); i++) {
System.out.println("convertJpegFramesToMpegVideo encoded frame counter: " + i);
img = jpegFileList.get(i);
writer.encodeVideo(0, img, nextEncodeTime, TimeUnit.MILLISECONDS);
nextEncodeTime = nextEncodeTime + getDurationPerFrame();
}//end loop
// after encoding all BufferedImages close
writer.close();
System.out.println("convertJpegFramesToMpegVideo, end!");
}//end

public int getFrameRate() {
return frameRate;
}

public void setFrameRate(int frameRate) {
this.frameRate = frameRate;
}
public String getOutputFilenamePath() {
return outputFilenamePath;
}

public void setOutputFilenamePath(String outputFilenamePath) {
this.outputFilenamePath = outputFilenamePath;
}

public List<String> getJpegFilePathList() {
return jpegFilePathList;
}

public void setJpegFilePathList(List<String> jpegFilePathList) {
this.jpegFilePathList = jpegFilePathList;
}

public List<BufferedImage> getJpegFileList() {
return jpegFileList;
}

public void setJpegFileList(List<BufferedImage> jpegFileList) {
this.jpegFileList = jpegFileList;
}

}//end class

这里是实例化 XugglerJpegImagesToMpegVideo.java 并设置 JPEG 文件路径、fps 和帧持续时间等参数的主类:

package com.conuretech.video_assembler;
import com.xuggle.xuggler.IContainerFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
*
* @author ANaim
*/
public class TestVideo {

public static void main (String [] args)
{
if (args[0].equalsIgnoreCase("1"))
{


System.out.println("Testing xuggler...");
XugglerJpegImagesToMpegVideo newjpegImagesToMpegVideo = new XugglerJpegImagesToMpegVideo();
newjpegImagesToMpegVideo.setFrameRate(24);
//duration in millisecs, for example 2 secs will be 2000
newjpegImagesToMpegVideo.setDurationPerFrame(2000);
newjpegImagesToMpegVideo.setOutputFilenamePath("C:/Users/Public/Pictures/Sample_Pictures_2/video.mp4");
List<String> jpegImages = new ArrayList<String>();
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/1.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/2.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/3.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/4.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/5.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/6.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/7.jpg");
jpegImages.add("C:/Users/Public/Pictures/Sample_Pictures_2/8.jpg");
newjpegImagesToMpegVideo.setJpegFilePathList(jpegImages);
newjpegImagesToMpegVideo.convertJpegFramesToMpegVideo();

}

else
{

}

System.exit(0);
}

}//end main

这创建了一个 16 秒的 MPEG 视频,每帧持续时间为 2 秒。

这就是大家!

关于java - 无法将一系列 JPEG 图像编码为 MPEG 视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27952257/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com