Search code examples
javaandroidrecordingmp4parser

Merging two clips with & without audio causes the audio to start from beginning in the generated video


I am trying to merge two videos(mp4 files), one with audio and one without audio, to a single video using MP4Parser. The final video that gets generated always has the audio from start. e.g. 1st video is of 20 sec length and has no audio. 2nd video is of 10 sec length and has audio. The final video generated is of 30 secs length but the audio will be played at the starting of the video for 10 secs (rest 20 secs won't have any audio), whereas it should have starting 20 seconds without audio and end 10 secs with audio.

Movie[] clips = new Movie[2];

//location of the movie clip storage
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES), "TestMerge");

//Build the two clips into movies
Movie firstClip = MovieCreator.build(first);
Movie secondClip = MovieCreator.build(second);

//Add both movie clips
clips[0] = firstClip;
clips[1] = secondClip;

//List for audio and video tracks
List<Track> videoTracks = new LinkedList<Track>();
List<Track> audioTracks = new LinkedList<Track>();

//Iterate all the movie clips and find the audio and videos
for (Movie movie: clips) {
    for (Track track : movie.getTracks()) {
        if (track.getHandler().equals("soun")) 
            audioTracks.add(track);                
        if (track.getHandler().equals("vide"))
            videoTracks.add(track);
    }
}

//Result movie from putting the audio and video together from the two clips
Movie result = new Movie();

//Append all audio and video
if (videoTracks.size() > 0)
    result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));

if (audioTracks.size() > 0) 
    result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));

}

I tried adding silence tracks by changing few line as below

//List for audio and video tracks
List<Track> videoTracks = new LinkedList<Track>();
List<Track> audioTracks = new LinkedList<Track>();
Track audioSourceTrack = null;

    for (final Movie movie : inMovies) {
        for (final Track t : movie.getTracks()) {
            if (isAudioTrack(t)) {
                audioSourceTrack = t;
                break;
            }
        }
        if (audioSourceTrack != null) break;
    }

    //Iterate all the movie clips and find the audio and videos
for (Movie movie: clips) {
        if (movie.getTracks().size() == 1) {
            videoTracks.add(movie.getTracks().get(0));
            audioTracks.add(new SilenceTrackImpl(audioSourceTrack, movie.getTracks().get(0).getDuration() / 2));
        } else {
            for (final Track t : movie.getTracks()) {
                if (isAudioTrack(t)) {
                    audioTracks.add(t);
                }
                if (isVideoTrack(t)) {
                    videoTracks.add(t);
                }
            }
        }
    }

Solution

  • I was able to do this by appending the muted clip with silence tracks. The problem was that the react-native-video was not playing the silence track properly so as the Q player. I had to transcode the video to see the appending silence was working correctly.