有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用xuggler将BuffereImage组合成视频的java

我正在尝试使用xuggler从BuffereImage列表中制作视频。我遵循了this教程,代码运行得非常完美

但是,当我将示例中的工作代码合并到我的代码中时,我得到一个RuntimeException:

java.lang.RuntimeException: failed to write packet: com.xuggle.xuggler.IPacket@46575264[complete:true;dts:67915;pts:67915;size:24201;key:false;flags:0;stream index:0;duration:1;position:-1;time base:1/65535;] at 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);

我需要输出电影FPS为1,但奇怪的是,当它为5时,视频创建没有异常,当它为2时,“视频”只是第一帧(没有其他帧),当它为1时,我得到这个异常

有什么想法吗?我真的很感激能得到的所有帮助


共 (1) 个答案

  1. # 1 楼答案

    我在我的一个多媒体课上教Xuggler,我的一些学生报告说,在制作定格动画或制作图片幻灯片的视频时出现了类似的问题

    我们求助于至少创造2甚至10 FPS。有趣的是,你很可能不会使用太多的内存来存储视频。MPG4编码器足够聪明,只在视频文件中插入基本为空的预测帧,因为在插入全新帧之前,帧之间没有差异

    这种方法的唯一缺点是会导致更多的编码开销。显然,在视频流中插入任何帧都会导致CPU负载,即使最终解码器决定只能插入空的预测帧

    编辑:事实证明,我们实际上是以每秒25帧的速度在视频中插入帧。尽管存在上述所有不利因素。然而,出于好奇,我做了一个测试,帧速率在10fps到25fps之间,结果发现文件的大小没有显著变化。有趣的是,10fps的测试文件是最大的

    静止图像的5秒全高清视频在450kb到580kb的范围内。因此,我建议您尝试一下帧速率,然后选择ffmpeg/Xugler能够为H264处理的最低帧速率(实际上这应该在文档中的某个地方,但我现在找不到)

    为了进行测试,我使用了下面的代码再次插入相同的BuffereImage

        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();
    

    专业提示:在实际应用中,我们使用一个线程提供图像帧,一个线程执行编码(writer.encodeVideo),这样我们就可以确保达到25 fps的准确帧速率。在您的示例中(以及在我的测试代码中),添加了Xugler/ffmpeg的编码时间