sannies / mp4parser

A Java API to read, write and create MP4 files
Apache License 2.0
2.74k stars 563 forks source link

Can not merge Visual Sample Entry when attempting to append more than 2 videos #414

Closed vaporbolt closed 4 years ago

vaporbolt commented 4 years ago

Hi! I have a list of mp4 videos which by using the FFmpegbuilder api, changes the resolution and encryption to be uniform. Here's a list of these commands .setFormat("mp4") // Format is inferred from filename, or can be set //.setTargetSize(250_000) // Aim for a 250KB file

                  //.disableSubtitle()       // No subtiles

                  .setAudioChannels(1)         // Mono audio
                  .setAudioCodec("aac")        // using the aac codec
                  .setAudioSampleRate(48_000)  // at 48KHz
                  .setAudioBitRate(163000)      // at 32 kbit/s
                  .setVideoCodec("mpeg4") // Video using x264
                  .setVideoFrameRate(60, 1)     // at 24 frames per second
                  .setVideoResolution(1920, 1080) // at 640x480 resolution

                  .setVideoBitRate(12000000)
                  //.setComplexVideoFilter("scale=320:trunc(ow/a/2)*2")

                  .setStrict(FFmpegBuilder.Strict.EXPERIMENTAL) // Allow FFmpeg to use experimental specs
                  .done();

and then I execute the following code to attempt to append all 3 mp4 files together

public static void mergenew(File file, File newFile) throws IOException {

        String[] videoUris = new String[3];
        File[] directory = file.listFiles();

        for(int i = 0; i < directory.length; i++)
        {
          videoUris[i] = directory[i].getAbsolutePath();
        }

        List<Movie> inMovies = new ArrayList<Movie>();
        for (String videoUri : videoUris) {
            inMovies.add(MovieCreator.build(videoUri));
        }

        List<Track> videoTracks = new LinkedList<Track>();
        List<Track> audioTracks = new LinkedList<Track>();

        for (Movie m : inMovies) {
            for (Track t : m.getTracks()) {
                if (t.getHandler().equals("soun")) {
                    audioTracks.add(t);
                }
                if (t.getHandler().equals("vide")) {
                    videoTracks.add(t);
                }
            }
        }

        Movie result = new Movie();

        if (!audioTracks.isEmpty()) {
            result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
        }
        if (!videoTracks.isEmpty()) {
            result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
        }

        Container out = new DefaultMp4Builder().build(result);

        FileChannel fc = new RandomAccessFile(String.format(newFile.getAbsolutePath()), "rw").getChannel();
        out.writeContainer(fc);
        fc.close();

    }

I keep getting the following error:java.io.IOException: Cannot merge VisualSampleEntry[com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox@a52110d1] and VisualSampleEntry[com.googlecode.mp4parser.boxes.mp4.ESDescriptorBox@a8c2d873] at com.googlecode.mp4parser.authoring.tracks.AppendTrack.mergeStsds(AppendTrack.java:116) at com.googlecode.mp4parser.authoring.tracks.AppendTrack.(AppendTrack.java:59)

any ideas?

vaporbolt commented 4 years ago

Something else important to note is when I don't set the video codec at all, I concatenate all the videos but it only plays audio

vaporbolt commented 4 years ago

Hey guys so I guess I solved it for anyone else wondering. Unless I am mistaken, concatenating more than one video through mp4 parser really messes with the video codec. I couldn't get it to work but I solved this issue by using an ffmpeg wrapper, which ended up working quite nicely. See here https://github.com/bramp/ffmpeg-cli-wrapper/issues/147