美文网首页
Android 中多个Mp3音频文件合成

Android 中多个Mp3音频文件合成

作者: chuanggggg | 来源:发表于2020-05-28 11:24 被阅读0次

    由于项目需求,需要将多个Mp3文件合并成一个Mp3文件,老项目中使用 FileChannel.transferFrom方法合并,直接导致生成的音频文件无法正确获取进度和时长,调研后选择使用MediaExtractor方法,参考https://juejin.im/post/5da80562f265da5bb5584a82

      /**
         *  合并音频文件
         *   @param videoPath  音频片段路径集合
         *   @param resultPath  生成文件路径
         *   @param isAdd  追加or覆盖
         *
         */
        public static void mergeMP3Files(List<String> videoPath,String resultPath,boolean isAdd){
            File file = new File(resultPath);
            if (file.exists()) {
                file.delete();
            }
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            try {
                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(resultPath, isAdd), 1024 * 200);
                for (int i = 0; i < videoPath.size(); i++) {
                    writeVideoFile(videoPath.get(i),outputStream);
                }
                outputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /**
         *   @param videoPath  音频片段路径
         *   @param outputStream 音频流
         */
        public static void writeVideoFile(String videoPath, BufferedOutputStream outputStream){
            try {
                MediaExtractor extractor = new MediaExtractor();
                extractor.setDataSource(videoPath);
                int videoTrackIndex = getAudioTrack(extractor);
                if (videoTrackIndex < 0) {
                    return ;
                }
                //选择音频轨道
                extractor.selectTrack(videoTrackIndex);
                MediaFormat mediaFormat = extractor.getTrackFormat(videoTrackIndex);
                //获取音频时间
                float time = mediaFormat.getLong(MediaFormat.KEY_DURATION) / 1000;//返回的是微秒,转换成毫秒
                //合并音频
                ByteBuffer buffer = ByteBuffer.allocate(1024 * 200);
                while (true) {
                    int sampleSize = extractor.readSampleData(buffer, 0);
                    if (sampleSize <= 0) {
                        break;
                    }
                    byte[] buf = new byte[sampleSize];
                    buffer.get(buf, 0, sampleSize);
                    //写入文件
                    outputStream.write(buf);
                    //音轨数据往前读
                    extractor.advance();
                }
                extractor.release();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取音频数据轨道
         */
        private static  int getAudioTrack(MediaExtractor extractor) {
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);
                if (mime.startsWith("audio")) {//audio为音频,video为视频
                    return i;
                }
            }
            return -1;
        }
    

    ------------------------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------------------------------------
    本来以为合成的功能已经实现,项目本地播放并没有发现问题,但是把合成的文件放到其他播放器中播放时,问题出现了。文件播放到最后几秒时,音频总时长会莫名的自增,以及合成的文件总时长与多个音频片段相加的时长有几秒偏差。应该是音频文件在流写入时出了问题,有了解的大牛帮忙分析分析。最后放弃这个合并方案,选择了FFmpeg合并,解决了音频合成问题。合并命令如下:

        /**
         *   @param mp3ListFile  多个Mp3音频片段的路径拼接字符串  拼接规则 a.mp3|b.mp3|c.mp3
         *   @param resultFile  生成文件路径
         */
        public  String mergeMp3Cmd(String mp3ListFile,String resultFile){
            String cmd = "ffmpeg -i concat:%s -acodec copy %s";
            cmd = String.format(cmd, mp3ListFile,resultFile);
            return cmd;
        }
    

    相关文章

      网友评论

          本文标题:Android 中多个Mp3音频文件合成

          本文链接:https://www.haomeiwen.com/subject/toeoahtx.html