如何在Java中的新视频文件中连接/合并两个视频?

时间:2016-06-30 12:52:39

标签: java video merge concatenation

我正在使用humble-videoRecordAndEncodeVideo.java制作视频。

我现在想要将两个视频首先合并为录制的视频,第二个是我system上预先存储的具有相同帧速率和分辨率的视频。由于限制,我想通过在java中使用简单视频 apis 来实现这一点。如果有人使用它,请指导我如何做到这一点。

这是我试过的代码:

  public static void combineVideo() throws InterruptedException, IOException {
    final Demuxer demuxer = Demuxer.make();
    demuxer.open("a.mp4", null, false, true, null, null);
    final Muxer muxer = Muxer.make("b.mp4", null, null);
    final MuxerFormat format = muxer.getFormat();
    final MediaPacket packet = MediaPacket.make();
    muxer.open(null, null);
    while (demuxer.read(packet) >= 0) {
        muxer.write(packet, false);
    }
    muxer.close();
    demuxer.close();
}

更新

我想连接两个视频文件并保存为新的视频文件。我知道在之前的问题例如

中已经提到过这个问题
  1. how-to-concat-or-merge-two-or-more-video-files-in-android
  2. merge-multiple-video-file-in-a-file
  3. 但大多数答案链接到不可用的资源或库。任何人都可以指导我一些资源。任何代码段都可能有所帮助。

3 个答案:

答案 0 :(得分:1)

大多数编解码器也不支持连接 - 它不会帮助您将比特流连接在一起。

但是,如果您确定编解码器具有相同的属性,则某些容器格式支持连接。 MPEG-TS就是其中之一。您可以将视频复制到传输流中而无需重新编码,然后使用普通文件操作连接传输流。

答案 1 :(得分:0)

我无法打开现有文件的多路复用器并追加到该文件,但是可以创建一个新的多路复用器,并将来自多个多路分解器的数据写入其中。要做的另一件事是转移数据包的dts / pt,以使它们在生成的文件中递增。

下面是一个有效的代码段,用于将多个avi连接为一个(假设所有源文件中的编解码器,时基等相同):

private static void merge(File aggregate, Collection<File> segments) throws InterruptedException, IOException {

    Muxer muxer = Muxer.make(aggregate.toString(), null, "avi");

    final MediaPacket packet = MediaPacket.make();
    long dts_offset = 0;
    long pts_offset = 0;

    for (File segment : segments) {
        Demuxer demuxer = Demuxer.make();
        demuxer.open(segment.toString(), null, false, true, null, null);
        if (muxer.getState() == State.STATE_INITED) {
            int numStreams = demuxer.getNumStreams();
            for (int s = 0; s < numStreams; s++) {
                DemuxerStream demuxerStream = demuxer.getStream(s);
                Decoder decoder = demuxerStream.getDecoder();
                muxer.addNewStream(decoder);
            }
            muxer.open(null, null);
        }
        long dts_max = 0;
        long pts_max = 0;
        while (demuxer.read(packet) >= 0) {
            if (packet.isComplete()) {
                packet.setDts(packet.getDts() + dts_offset);
                packet.setPts(packet.getPts() + pts_offset);
                dts_max = packet.getDts() + 1;
                pts_max = packet.getPts() + 1;

                muxer.write(packet, false);
            }
        }
        dts_offset = dts_max;
        pts_offset = pts_max;
        demuxer.close();
    }   
    muxer.close();
}

答案 2 :(得分:0)

对视频数据的任何操作通常已在ffmpeg及其库中实现。尽管这不是Java代码库,但它为您提供了有关如何进行常见视频数据转换(例如连接视频数据)的开源参考。

您可能想看看here来阅读ffmpeg实现的内容。

话虽这么说,您可能要考虑不实施ffmpeg中已提供,经过验证和测试的内容。如果跨基础架构的Java代码库的可移植性不是主要问题,那么最好从Java代码库中调用ffmpeg的库来执行需要执行的复杂视频任务。