8

I'm trying to merge mp3 audio files But not successful.

Here is my code.

public static void meargeAudio(List<File> filesToMearge)
{


    while (filesToMearge.size()!=1){

        try {
            FileInputStream fistream1 = new FileInputStream(new File(filesToMearge.get(0).getPath()));  //(/storage/emulated/0/Audio Notes/1455194356500.mp3) first source file
            FileInputStream fistream2 = new FileInputStream(new File(filesToMearge.get(1).getPath()));//second source file

            File file1 = new File(filesToMearge.get(0).getPath());
            boolean deleted = file1.delete();
            File file2 = new File(filesToMearge.get(1).getPath());
            boolean deleted1 = file2.delete();

            SequenceInputStream sistream = new SequenceInputStream(fistream1, fistream2);
            FileOutputStream fostream = new FileOutputStream(new File(filesToMearge.get(0).getPath()),true);//destinationfile

            int temp;

            while ((temp = sistream.read()) != -1) {
                // System.out.print( (char) temp ); // to print at DOS prompt
                fostream.write(temp);   // to write to file
            }

            filesToMearge.add(0,new File(filesToMearge.get(0).getPath()));
            filesToMearge.remove(1);
            filesToMearge.remove(1);


            fostream.close();
            sistream.close();
            fistream1.close();
            fistream2.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

e.g

firstFileSize =12kb

secondFileSize =10kb

finalfileSize=22kb

Size is accurate But sound is missing

No error but in result i found finalfile contains only first file audio second file audio is missing.

Don't know what is the issue.if any one know the solution help me.

Thanks

Nisar Ahmad
  • 1,987
  • 3
  • 13
  • 30

4 Answers4

3

I also struggled with that and solved it using mp4parser

import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.googlecode.mp4parser.authoring.tracks.AppendTrack;

For your case, I believe something like this should work:

public static void mergeAudio(List<File> filesToMerge) {

    String output = Environment.getExternalStorageDirectory().getAbsolutePath() + "output.mp3";

    while (filesToMerge.size()!=1){

        try {

            String[] videoUris = new String[]{
                filesToMerge.get(0).getPath(),
                filesToMerge.get(0).getPath()
            };

            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(output, "rw").getChannel();
            out.writeContainer(fc);
            fc.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

There are a few answers suggesting that, such as:

Community
  • 1
  • 1
filipebarretto
  • 1,842
  • 1
  • 13
  • 27
  • 1
    @SimpleCoder I have a production app running using this code. If you need any help implementing, just let me know. – filipebarretto Aug 30 '16 at 02:01
  • Yeah .. i am stuck on this , please help me . I can be reached on ysapps16@gmail.com – SimpleCoder Aug 30 '16 at 07:09
  • Please let me know what you've tried and where you got stuck. – filipebarretto Aug 30 '16 at 12:31
  • I have tried above code , but cant figure it out what is 'Track'. – SimpleCoder Sep 01 '16 at 07:40
  • @SimpleCoder I added the imports needed from mp4parser to try to make it more clear. Track is a class from mp4parser and this is basically a lib to deal with video and audio. I didn't investigate details about the lib to explain details about the goal of each class. – filipebarretto Sep 01 '16 at 17:13
  • 3
    @SimpleCoder Have you even tested this if this works? Where is the declaration of `inMovies` variable? – ajdeguzman Oct 05 '16 at 07:36
  • @filipebarretto I am facing issue on line "Container out = new DefaultMp4Builder().build(result);" , It takes too much time for long audio tracks please help :-(. – Bhumit Oct 19 '16 at 08:23
  • @Bhumit I still have the same problem. For my use case, I have a warning when the user creates multiple audios and tries to merge them. I give him a warning in my app that it may take long, but I didn't figure out a way to make it quick. If you do find a solution, please share. – filipebarretto Oct 19 '16 at 18:57
  • I know this is a bit old but I had the same issue as @Bhumit. I can merge the audio files but if they're significantly long, like over two minutes, it just takes way too long to merge them. – Lee Jan 27 '17 at 15:57
  • inMovies variable is not declared. videoUris variable nor used. Code NOT work. – user2983041 Sep 17 '17 at 10:29
  • @filipebarretto can you please let me know about `inMovies` ? It seems to be nowhere or am i missing something out here. – Suraj Malviya Dec 11 '18 at 17:39
2

It is too late. But still, someone might need a proper solution. That is why I am suggesting to use AudioMixer-android library.

ZeroOneZeroR
  • 667
  • 1
  • 7
  • 12
0

Well there's a function to merge Audio or Video files

public static boolean mergeMediaFiles(boolean isAudio, String sourceFiles[], String targetFile) {
        try {
            String mediaKey = isAudio ? "soun" : "vide";
            List<Movie> listMovies = new ArrayList<>();
            for (String filename : sourceFiles) {
                listMovies.add(MovieCreator.build(filename));
            }
            List<Track> listTracks = new LinkedList<>();
            for (Movie movie : listMovies) {
                for (Track track : movie.getTracks()) {
                    if (track.getHandler().equals(mediaKey)) {
                        listTracks.add(track);
                    }
                }
            }
            Movie outputMovie = new Movie();
            if (!listTracks.isEmpty()) {
                outputMovie.addTrack(new AppendTrack(listTracks.toArray(new Track[listTracks.size()])));
            }
            Container container = new DefaultMp4Builder().build(outputMovie);
            FileChannel fileChannel = new RandomAccessFile(String.format(targetFile), "rws").getChannel();
            container.writeContainer(fileChannel);
            fileChannel.close();
            return true;
        }
        catch (IOException e) {
            Log.e("MYTAG", "Error merging media files. exception: "+e.getMessage());
            return false;
        }
    }
  • If you got Audios, isAudio should be true. if you got videos isAudio should be false
  • sourceFiles[] array should contain the destinations of the media files such as

    /sdcard/my_songs/audio_1, /sdcard/my_songs/audio_2, /sdcard/my_songs/audio_3

  • targetFile is your final audio merged file should be somthing like

    /sdcard/my_songs/final_audio_1

  • If you deal with large files it's preferred to merge file in background, you can use AsynkTask
Mohamed Embaby
  • 960
  • 8
  • 26
0

String wavFile1 = android.os.Environment.getExternalStorageDirectory()+"/Download/a.mp4"; String wavFile2 = android.os.Environment.getExternalStorageDirectory()+"/Download/b.mp4"; FileInputStream fistream1 = null; // first source file try { fistream1 = new FileInputStream(wavFile1); FileInputStream fistream2 = new FileInputStream(wavFile2);//second source file SequenceInputStream sistream = new SequenceInputStream(fistream1, fistream2); FileOutputStream fostream = new FileOutputStream(android.os.Environment.getExternalStorageDirectory()+"/Download/merge1.mp4");//destinationfile

        int temp;

        while( ( temp = sistream.read() ) != -1)
        {
            // System.out.print( (char) temp ); // to print at DOS prompt
            fostream.write(temp);   // to write to file
        }
        Log.e("Result","Done");

        fostream.close();
        sistream.close();
        fistream1.close();
        fistream2.close();

        Toast.makeText(this, "Done", Toast.LENGTH_SHORT).show();
    }
    catch (FileNotFoundException e) {
        e.printStackTrace();
        Log.e("Not",e+"");
        Toast.makeText(this, "File not Found", Toast.LENGTH_SHORT).show();
    }
    catch (IOException e)
    {
        Toast.makeText(this, ""+e, Toast.LENGTH_SHORT).show();
    }