首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Java中的jcodec将多个mp4视频组合成一个视频?

如何使用Java中的jcodec将多个mp4视频组合成一个视频?
EN

Stack Overflow用户
提问于 2022-05-05 19:52:17
回答 2查看 678关注 0票数 1

我有多个mp4文件,它们是整个mp4文件的一部分。他们只是被分割成更小的文件。

我希望使用Java中的mp4,以编程方式将这些文件组合成一个jcodec文件。目前,我正在使用以下代码来执行此操作:

代码语言:javascript
运行
复制
import org.jcodec.common.DemuxerTrack;
import org.jcodec.common.MuxerTrack;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.model.Packet;
import org.jcodec.containers.mp4.Brand;
import org.jcodec.containers.mp4.demuxer.MP4Demuxer;
import org.jcodec.containers.mp4.muxer.MP4Muxer;

import java.io.File;
import java.util.List;

import static org.jcodec.common.io.NIOUtils.readableChannel;
import static org.jcodec.common.io.NIOUtils.writableChannel;

public class Main {

    public static void main(String[] args) throws Exception {
        File outputFile = new File("file_path_output.mp4");
        outputFile.mkdirs();
        outputFile.delete();

        File[] inputFiles = new File[]{
                new File("file_path_1.mp4"),
                new File("file_path_2.mp4"),
                new File("file_path_3.mp4"),
        };

        SeekableByteChannel output = writableChannel(outputFile);
        MP4Muxer mp4Muxer = MP4Muxer.createMP4Muxer(output, Brand.MP4);

        MuxerTrack mixedVideoTrack = null;
        MuxerTrack mixedAudioTrack = null;
        for (File input : inputFiles) {
            SeekableByteChannel byteChannel = readableChannel(input);
            MP4Demuxer demuxer = MP4Demuxer.createMP4Demuxer(byteChannel);
            List<DemuxerTrack> videoTracks = demuxer.getVideoTracks();
            List<DemuxerTrack> audioTracks = demuxer.getAudioTracks();
            if (mixedVideoTrack == null) {
                mixedVideoTrack = mp4Muxer.addVideoTrack(videoTracks.get(0).getMeta().getCodec(), videoTracks.get(0).getMeta().getVideoCodecMeta());
            }
            if (mixedAudioTrack == null) {
                mixedAudioTrack = mp4Muxer.addAudioTrack(audioTracks.get(0).getMeta().getCodec(), audioTracks.get(0).getMeta().getAudioCodecMeta());
            }
            for (DemuxerTrack videoTrack : videoTracks) {
                Packet packet;
                while ((packet = videoTrack.nextFrame()) != null) {
                    mixedVideoTrack.addFrame(packet);
                }
            }
            for (DemuxerTrack audioTrack : audioTracks) {
                Packet packet;
                while ((packet = audioTrack.nextFrame()) != null) {
                    mixedAudioTrack.addFrame(packet);
                }
            }
            demuxer.close();
        }

        mp4Muxer.finish();
        output.close();
    }
}

不幸的是,它不能工作,因为生成的视频不包含音频文件或正确的帧。例如,我得到的所有视觉框架如下所示:

有什么问题,我怎么解决呢?非常感谢。

EN

回答 2

Stack Overflow用户

发布于 2022-05-14 19:16:52

您可以使用ffmpeg来完成这一任务。

  1. 首先,需要将文件路径写入txt文件。

txt文件,具有:

  • 文件‘/sdcard/视频/视频1.mp4’
  • 文件‘/sdcard/视频/视频2.mp4’
  • 文件‘/sdcard/视频/视频3.mp4’
  • 文件‘/sdcard/视频/视频4.mp4’

您可以使用以下命令。

代码语言:javascript
运行
复制
ffmpeg -f concat -i mp4list.txt -c:v copy -c:a copy merging.mp4
  1. 您可以在Java代码上编写包装器。此外,您还可以使用下面的代码。

要帮助的资源:链接

代码语言:javascript
运行
复制
String[] cmd = new String[]{"-f", "concat", "-safe", "0", "-i", "mp4list.txt", "-c", "copy", "-preset", "ultrafast", outFile};

ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler(){
    
        @Override
        public void onFailure(String message){
        }
        @Override
        public void onSuccess(String message){
        }
        @Override
        public void onProgress(String message){
        }
    
        @Override
        public void onStart(){
        }
    
        @Override
        public void onFinish(){
        }
    }
票数 2
EN

Stack Overflow用户

发布于 2022-05-08 15:10:58

我不太懂jcodec,但我以前使用过MP4parser。如果您需要合并mp4文件,不管库是什么,那么我建议您使用这个库。我只是向您介绍它,因为我不知道您在合并文件方面是否有问题,因为库的复杂性。也许值得试一试。MP4Parser是非常简单和简单的。我还将留给您到maven存储库的链接。

https://search.maven.org/artifact/com.googlecode.mp4parser/isoparser/1.1.22/jar

下面是我所做的一个实现,向您展示如何从同一个原始视频中合并2个文件(以复制您的确切案例)。基本上,您有一个Movie类,它代表您的mp4文件,包含一个List of Track (只有2);一个代表视频,另一个代表音频。

  1. 首先,我从电影中收集了两个不同的数组中的所有视频和音频曲目。
  2. 然后,我使用合并的音频Track和合并的视频Track创建了一个Track,以便将其设置为输出文件。
  3. 最后,我在一个Movie中构建了Container并使用FileOutputStream保存了它。
代码语言:javascript
运行
复制
public class Main {

    public static void main(String[] args) throws IOException {
        MovieCreator mc = new MovieCreator();
        Movie movie1 = mc.build("./test1.mp4");
        Movie movie2 = mc.build("./test2.mp4");

        //Fetching the video tracks from the movies and storing them into an array
        Track[] vetTrackVideo = new Track[0];
        vetTrackVideo = Stream.of(movie1, movie2)
                .flatMap(movie -> movie.getTracks().stream())
                .filter(movie -> movie.getHandler().equals("vide"))
                .collect(Collectors.toList())
                .toArray(vetTrackVideo);

        //Fetching the audio tracks from the movies and storing them into an array
        Track[] vetTrackAudio = new Track[0];
        vetTrackAudio = Stream.of(movie1, movie2)
                .flatMap(movie -> movie.getTracks().stream())
                .filter(movie -> movie.getHandler().equals("soun"))
                .collect(Collectors.toList())
                .toArray(vetTrackAudio);

        //Creating the output movie by setting a list with both video and audio tracks
        Movie movieOutput = new Movie();
        List<Track> listTracks = new ArrayList<>(List.of(new AppendTrack(vetTrackVideo), new AppendTrack(vetTrackAudio)));
        movieOutput.setTracks(listTracks);

        //Building the output movie and storing it into a Container
        DefaultMp4Builder mp4Builder = new DefaultMp4Builder();
        Container c = mp4Builder.build(movieOutput);

        //Writing the output file
        FileOutputStream fos = new FileOutputStream("output.mp4");
        c.writeContainer(fos.getChannel());
        fos.close();
    }
}

在这里,我还将给您留下一个指向我的github存储库和测试mp4文件的链接,以便您可以测试合并示例。

https://github.com/daniele-aveta/MP4Merger

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72132908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档