I have multiple mp4 files which are parts of a whole mp4 file. They have been just split up to smaller files.
I want to combine those files programmatically into one mp4 file using jcodec in Java. Currently, I'm using the following code to do this:
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();
}
}
Unfortunately, it does not work as the video generated does not contain audio files nor correct frames. For example, all visual frames I get are like one below:
What is the problem and how can I fix it? Thank you very much.
I don't really know
jcodec
, but I've usedMP4parser
in the past. If you need to merge mp4 files, regardless of the library, then I suggest you this one. I'm just pitching it to you because I don't know if you're having problems in merging the files due to the complexity of the library. It might be worth giving it a shot. MP4Parser is quite easy and straightforward. I'll also leave you the link to the maven repository.https://search.maven.org/artifact/com.googlecode.mp4parser/isoparser/1.1.22/jar
Here there's an implementation I've done to show you how to merge 2 files from the same original video (to replicate your exact case). Basically, you have a
Movie
class, which represents your mp4 file, containing aList
ofTrack
(only 2); one representing the video while the other the audio.First, I've collected from the movies all the video and audio tracks in two separate arrays.
Then, I've created a
List
with the merged audioTrack
and the merged videoTrack
in order to set it to the output file.Finally, I've built the
Movie
inside aContainer
and saved it with aFileOutputStream
.Here, I'll also leave you a link to my GitHub repository with the test mp4 files so that you can test the merging sample.
https://github.com/daniele-aveta/StackOverflow-MP4Merger