如何在Android上合并两个或多个MP3音频文件?

8

我想合并mp3音频文件,但没有成功。

这是我的代码。

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();
        }
    }

}

例如:

第一个文件大小为12kb

第二个文件大小为10kb

最终文件大小为22kb

大小是准确的,但声音丢失了

没有错误,但在结果中我发现最终文件只包含第一个文件的音频,第二个文件的音频丢失了。

不知道问题出在哪里。如果有人知道解决方法,请帮帮我。

谢谢

4个回答

3

我也曾遇到过这个问题,用 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;

针对您的情况,我认为以下内容可能会起到作用:

对于您的案例,我相信这样做应该可行:

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();
        }
    }
}

有一些答案建议如下:


1
@SimpleCoder 我正在使用这段代码运行一个生产应用程序。如果你需要任何帮助来实现它,随时告诉我。 - filipebarretto
是的,我卡在这里了,请帮帮我。您可以通过ysapps16@gmail.com联系到我。 - SimpleCoder
3
@SimpleCoder 你测试过这个代码吗?inMovies变量的声明在哪里? - ajdeguzman
@filipebarretto 我在第 "Container out = new DefaultMp4Builder().build(result);" 行遇到问题,对于长音轨它需要太多时间,请帮忙 :-(。 - Bhumit
@Bhumit 我仍然有同样的问题。对于我的用例,当用户创建多个音频并尝试合并它们时,我会发出警告。我在我的应用程序中向他发出警告可能需要很长时间,但我没有找到快速解决方法。如果您找到解决方案,请分享。 - filipebarretto
显示剩余6条评论

1

虽然现在不是很晚,但还是有人需要一个合适的解决方案。这就是为什么我建议使用AudioMixer-android库。


0

嗯,有一个合并音频或视频文件的函数。

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;
        }
    }
  • 如果你有音频,isAudio 应该为 true。 如果你有视频 isAudio 应该为 false。
  • sourceFiles[] 数组应包含媒体文件的目标位置,例如

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

  • targetFile 是你的最终合并音频文件,应该类似于

    /sdcard/my_songs/final_audio_1

  • 如果要处理大文件,则最好在后台合并文件,可以使用 AsynkTask.

这也使用了 mp4parser,所以在我看来它只能生成 mp4 格式 :/ - ch271828n

0

String wavFile1 = android.os.Environment.getExternalStorageDirectory()+"/Download/a.mp4"; String wavFile2 = android.os.Environment.getExternalStorageDirectory()+"/Download/b.mp4"; FileInputStream fistream1 = null; // 第一个源文件 try { fistream1 = new FileInputStream(wavFile1); FileInputStream fistream2 = new FileInputStream(wavFile2);//第二个源文件 SequenceInputStream sistream = new SequenceInputStream(fistream1, fistream2); FileOutputStream fostream = new FileOutputStream(android.os.Environment.getExternalStorageDirectory()+"/Download/merge1.mp4");//目标文件

        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();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接