我试着用BufferedImages的列表制作一个视频,用xuggler。我遵循了这教程,代码运行得很好。
但是,当我将示例中的工作代码合并到我的代码中时,我得到了一个RuntimeException:
com.xuggle.xuggler.IPacket@46575264complete:true;dts:67915;pts:67915;size:24201;key:false;flags:0;stream指数:0;持续时间:1;位置:-1;时间基:1/65535;在com.xuggle.mediatool.MediaWriter.writePacket(MediaWriter.java:1215) at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:767) at com.xuggle.mediatool.MediaWriter.encodeVideo(MediaWriter.java:810) at s3.S3CompositeUtil.generateVideo(S3CompositeUtil.java:247) at s3.S3CompositeUtil.main(S3CompositeUtil.java:349)
Xuggler文档提到:调用者必须确保IMediaData.getTimeStamp() (如果指定的话)总是单调增加,否则就会引发RuntimeException。
但是我不认为我在制作视频的时候会在任何时候减少。
private void generateVideo() {
System.out.println("Creating video...");
String outputMoviePath = "";
IMediaWriter writer = null;
if (allLabels) {
outputMoviePath = TEMP_DIR_PATH + "/" + clipName + "/" + clipName + "_" + "all_labels" + ".avi";
}
else {
outputMoviePath = TEMP_DIR_PATH + "/" + clipName + "/" + clipName + "_" + labels[desiredLabelIdx] + ".avi";
}
writer = ToolFactory.makeWriter(outputMoviePath);
// add one video stream, with position 0 and ID 0, and a frame rate of OUTPUT_MOVIE_FPS
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_MPEG4, vidWidth, vidHeight);
long startTime = System.nanoTime();
for (int idxF = 0; idxF < numFrames; idxF++) {
BufferedImage currFrameImg = convertToType(videoBIHolder.get(idxF), BufferedImage.TYPE_3BYTE_BGR);
// BufferedImage currFrameImg = videoBIHolder.get(idxF);
System.out.println("currFrameImg type is " + currFrameImg.getType()); // debug
// encode video to stream at 0
long frameTimeInVideo = System.nanoTime() - startTime;
System.out.println("Time: " + frameTimeInVideo);
writer.encodeVideo(0, currFrameImg, frameTimeInVideo, TimeUnit.NANOSECONDS);
// sleep for millisec. amount of time of the frame rate
try {
Thread.sleep((long) (1000/OUTPUT_MOVIE_FPS)); //OUTPUT_MOVIE_FPS
}
catch (InterruptedException e) {
System.err.println();
}
}(S3CompositeUtil.java:247)是行
writer.encodeVideo(0, currFrameImg, frameTimeInVideo, TimeUnit.NANOSECONDS);我需要OUTPUT_MOVIE_FPS是1,但奇怪的是,当它是5,视频被创建没有例外,当它是2,“视频”只是第一帧(没有其他帧),当它是1,我得到这个异常。
有什么想法吗?我真的很感激我能得到的一切帮助!
发布于 2014-10-12 10:39:47
我在我的一堂多媒体课上教夏格勒,我的一些学生在创建停止动作动画或制作图片幻灯片的视频时也报告了类似的问题。
我们至少创建了2个甚至10个FPS。有趣的是,你很可能不会用更多的内存来存储视频。MPG4编码器足够聪明,只将预测帧插入到视频文件中,该视频文件基本上是空的,因为在插入一个全新的帧之前,帧中没有差别。
这种方法的唯一缺点是会造成更多的编码开销。显然,将任何帧插入视频流将导致CPU负载,即使解码器最终决定只能插入空的预测帧。
编辑:事实证明,我们实际上是以25 fps的速率将帧插入到视频中。上面描述的所有缺点。然而,出于好奇,我做了一个测试,帧速率在10 fps到25 fps之间,结果显示文件的大小没有明显的变化。有趣的是,10 fps测试文件是最大的。
一个静止图像的5秒全高清视频在450 to到580 to之间。因此,我建议您只尝试使用帧率,只需选择ffmpeg / H264可以处理的最低速率(实际上,这应该在文档中,但我现在找不到)。
为了进行测试,我使用了以下代码,它再次插入相同的BufferedImage。
final IMediaWriter writer = ToolFactory.makeWriter(outputFile);
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, img.getSize().width, screenshot.getSize().height);
long startTime = System.nanoTime();
for (int i=0; i<seconds*25; i++) {
BufferedImage bgrScreen = Tools.convertToType(img, BufferedImage.TYPE_3BYTE_BGR);
writer.encodeVideo(0, bgrScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
try {
Thread.sleep((long) (1000 / 25));
} catch (InterruptedException e) {
// ignore
}
}
writer.close();Pro-Tip:在实际应用程序中,我们使用一个线程来提供图像帧,使用一个线程执行编码(writer.encodeVideo),这样我们就可以确保精确的帧速率达到25 fps。在您的示例(以及我的测试代码中)中,添加了Xuggler / ffmpeg的编码时间。
https://stackoverflow.com/questions/26320931
复制相似问题