如何在android中合并音频和视频文件

时间:2015-07-08 06:36:07

标签: android html5 audio video mp4parser

感谢伟大的mp4parser lib,我几乎没有与音频视频多路复用相关的查询。

我们在android中使用了以下代码并尝试过,但我们没有得到预期的输出,我们在特定目录中保留了一个正在运行的mp4文件并尝试但没有运气。

这里我们得到合并的音频和视频,但音频会附加到视频中。附加的音频不会播放,只是增加了视频的宽度。

来自极客的任何帮助。

这是代码,

    File sdCard = Environment.getDataDirectory();

    String videofilepath = Environment.getExternalStorageDirectory().toString()+"/video.mp4";
    String audiofilepath = Environment.getExternalStorageDirectory().toString()+"/audio.aac";
    File file=new File(videofilepath);

    H264TrackImpl h264Track = new H264TrackImpl(new FileDataSourceImpl(videofilepath));
    AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(audiofilepath));

    Movie movie = new Movie();
    movie.addTrack(h264Track);
    movie.addTrack(aacTrack);


    Container mp4file = new DefaultMp4Builder().build(movie);

    FileChannel fc = new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString() + "/video.mp4")).getChannel();
    mp4file.writeContainer(fc);
    fc.close();

4 个答案:

答案 0 :(得分:1)

  1. 我们可以将.m4a.aac.3gp音频文件与android中的.mp4视频文件合并。 2).mp3音频文件无法与视频文件合并。
  2. 以下代码适用于合并.mp4音频和空白视频(无声音):

    public class Search extends FragmentActivity implements LoaderCallbacks<Boolean> {
    
        private final Search self = this;
        private ProgressDialog mProgressDialog;
        VideoView mVideoView;
        ImageView back, next;
        String path;
        String root = Environment.getExternalStorageDirectory().toString();
        String songpath, songname;
        String TAG = "Logcat";
        String[] fileList;
    
        String audiopath = "/sdcard/dubmash/audio.m4a";
        String videopath = "/sdcard/dubmash/video.`mp4`";
        String output;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.search);
    
            Intent i = getIntent();
            if (getIntent().getExtras() != null) {
                songpath = i.getStringExtra("songpath");
                songname = i.getStringExtra("songname");
                Log.e("Search Class :song name", songname);
                Log.e("Search Class :song path", songpath);
            }
    
    
            mVideoView = (VideoView) findViewById(R.id.videoview);
            root = Environment.getExternalStorageDirectory().toString();
    
            back = (ImageView) findViewById(R.id.back);
            next = (ImageView) findViewById(R.id.next);
            String audio = audiopath;
            String video = videopath;
            output = "/sdcard/dubmash/" + songname + ".mp4";
    
            Log.e("FILE", "audio:" + audio + " video:" + video + " out:" + output);
    
            try {
                mux(video, audio, output);
            } catch (NullPointerException e) {
                Toast.makeText(Search.this, "Please Record Again ", Toast.LENGTH_SHORT).show();
            }
    
            try {
                //Delete video file
                File file = new File(videopath);
                boolean deleted = file.delete();
                //Delete Audio file
                File files = new File(audiopath);
                boolean deleted1 = files.delete();
    
    
                mVideoView.setVideoPath(output);
                mVideoView.requestFocus();
                mVideoView.start();
            } catch (NullPointerException e) {
                Toast.makeText(Search.this, "File Not Find", Toast.LENGTH_SHORT).show();
            }
    
    
            Button play = (Button) findViewById(R.id.playvideoplayer);
            play.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    mVideoView.setVideoPath(output);
                    mVideoView.requestFocus();
                    mVideoView.start();
    
                }
            });
    
            next.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent i = new Intent(Search.this, HomePage.class);
                    i.putExtra("showdubs", "dubs");
                    startActivity(i);
                    finish();
                }
            });
    
            back.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent i = new Intent(Search.this, AlbumDetailVideo.class);
                    i.putExtra("songpath", songpath);
                    i.putExtra("songname", songname);
                    startActivity(i);
                    finish();
                }
            });
    
        }
    
        @Override
        public Loader<Boolean> onCreateLoader(int id, Bundle args) {
            return new EditMovieTask(self, args.getInt("type"));
        }
    
        @Override
        public void onLoadFinished(Loader<Boolean> loader, Boolean succeed) {
            getSupportLoaderManager().destroyLoader(loader.getId());
            mProgressDialog.dismiss();
        }
    
        @Override
        public void onLoaderReset(Loader<Boolean> loader) {
        }
    
        public static class EditMovieTask extends AsyncTaskLoader<Boolean> {
    
            private int mType;
    
            public EditMovieTask(Context context, int type) {
                super(context);
                mType = type;
                forceLoad();
            }
    
            @Override
            public Boolean loadInBackground() {
    
                switch (mType) {
                    case 0:
                        //         return append();
                    case 1:
                        //       return crop();
                    case 2:
                        //     return subTitle();
                }
    
                return false;
            }
    
    
        }
    
        public boolean mux(String videoFile, String audioFile, String outputFile) {
            Movie video;
            try {
                video = new MovieCreator().build(videoFile);
                Log.e("Audio Video", "1");
            } catch (RuntimeException e) {
                e.printStackTrace();
                Log.e("Audio Video", "2");
                return false;
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("Audio Video", "3");
                return false;
            }
    
            Movie audio;
            try {
    
                audio = new MovieCreator().build(audioFile);
                Log.e("Audio Video", "4");
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("Audio Video", "5");
                return false;
            } catch (NullPointerException e) {
                e.printStackTrace();
                Log.e("Audio Video", "6");
                return false;
            }
    
            Track audioTrack = audio.getTracks().get(0);
            video.addTrack(audioTrack);
    
            Container out = new DefaultMp4Builder().build(video);
            Log.e("Audio Video", "8");
            FileOutputStream fos;
            try {
                Log.e("Audio Video", "9");
                fos = new FileOutputStream(outputFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
            try {
                Log.e("Audio Video", "10");
                out.writeContainer(byteBufferByteChannel);
                byteBufferByteChannel.close();
                Log.e("Audio Video", "11");
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        private static class BufferedWritableFileByteChannel implements WritableByteChannel {
            //    private static final int BUFFER_CAPACITY = 1000000;
            private static final int BUFFER_CAPACITY = 10000000;
    
            private boolean isOpen = true;
            private final OutputStream outputStream;
            private final ByteBuffer byteBuffer;
            private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];
    
            private BufferedWritableFileByteChannel(OutputStream outputStream) {
                this.outputStream = outputStream;
                this.byteBuffer = ByteBuffer.wrap(rawBuffer);
                Log.e("Audio Video", "13");
            }
    
            @Override
            public int write(ByteBuffer inputBuffer) throws IOException {
                int inputBytes = inputBuffer.remaining();
    
                if (inputBytes > byteBuffer.remaining()) {
                    Log.e("Size ok ", "song size is ok");
                    dumpToFile();
                    byteBuffer.clear();
    
                    if (inputBytes > byteBuffer.remaining()) {
                        Log.e("Size ok ", "song size is not okssss ok");
                        throw new BufferOverflowException();
                    }
                }
    
                byteBuffer.put(inputBuffer);
    
                return inputBytes;
            }
    
            @Override
            public boolean isOpen() {
                return isOpen;
            }
    
            @Override
            public void close() throws IOException {
                dumpToFile();
                isOpen = false;
            }
    
            private void dumpToFile() {
                try {
                    outputStream.write(rawBuffer, 0, byteBuffer.position());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
    
        private void muxing() {
    
            String outputFile = "";
    
            try {
    
                root = Environment.getExternalStorageDirectory().toString();
                String audio = root + "/" + "audio.mp3";
                String video = root + "/" + "rohit.mp4";
    
    
                File file = new File(Environment.getExternalStorageDirectory() + File.separator + "final2.mp4");
                file.createNewFile();
                outputFile = file.getAbsolutePath();
    
    
                MediaExtractor videoExtractor = new MediaExtractor();
                videoExtractor.setDataSource(video);
    
                MediaExtractor audioExtractor = new MediaExtractor();
                audioExtractor.setDataSource(audio);
    
                Log.d(TAG, "Video Extractor Track Count " + videoExtractor.getTrackCount());
                Log.d(TAG, "Audio Extractor Track Count " + audioExtractor.getTrackCount());
    
                MediaMuxer muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    
                videoExtractor.selectTrack(0);
                MediaFormat videoFormat = videoExtractor.getTrackFormat(0);
                int videoTrack = muxer.addTrack(videoFormat);
    
                audioExtractor.selectTrack(0);
                MediaFormat audioFormat = audioExtractor.getTrackFormat(0);
                int audioTrack = muxer.addTrack(audioFormat);
    
                Log.d(TAG, "Video Format " + videoFormat.toString());
                Log.d(TAG, "Audio Format " + audioFormat.toString());
    
                boolean sawEOS = false;
                int frameCount = 0;
                int offset = 100;
                int sampleSize = 256 * 1024;
                ByteBuffer videoBuf = ByteBuffer.allocate(sampleSize);
                ByteBuffer audioBuf = ByteBuffer.allocate(sampleSize);
                MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
                MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
    
    
                videoExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
                audioExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
    
                muxer.start();
    
                while (!sawEOS) {
                    videoBufferInfo.offset = offset;
                    videoBufferInfo.size = videoExtractor.readSampleData(videoBuf, offset);
    
    
                    if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) {
                        Log.d(TAG, "saw input EOS.");
                        sawEOS = true;
                        videoBufferInfo.size = 0;
    
                    } else {
                        videoBufferInfo.presentationTimeUs = videoExtractor.getSampleTime();
                        videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                        muxer.writeSampleData(videoTrack, videoBuf, videoBufferInfo);
                        videoExtractor.advance();
    
    
                        frameCount++;
                        Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs + " Flags:" + videoBufferInfo.flags + " Size(KB) " + videoBufferInfo.size / 1024);
                        Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs + " Flags:" + audioBufferInfo.flags + " Size(KB) " + audioBufferInfo.size / 1024);
    
                    }
                }
    
                Toast.makeText(getApplicationContext(), "frame:" + frameCount, Toast.LENGTH_SHORT).show();
    
    
                boolean sawEOS2 = false;
                int frameCount2 = 0;
                while (!sawEOS2) {
                    frameCount2++;
    
                    audioBufferInfo.offset = offset;
                    audioBufferInfo.size = audioExtractor.readSampleData(audioBuf, offset);
    
                    if (videoBufferInfo.size < 0 || audioBufferInfo.size < 0) {
                        Log.d(TAG, "saw input EOS.");
                        sawEOS2 = true;
                        audioBufferInfo.size = 0;
                    } else {
                        audioBufferInfo.presentationTimeUs = audioExtractor.getSampleTime();
                        audioBufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                        muxer.writeSampleData(audioTrack, audioBuf, audioBufferInfo);
                        audioExtractor.advance();
    
    
                        Log.d(TAG, "Frame (" + frameCount + ") Video PresentationTimeUs:" + videoBufferInfo.presentationTimeUs + " Flags:" + videoBufferInfo.flags + " Size(KB) " + videoBufferInfo.size / 1024);
                        Log.d(TAG, "Frame (" + frameCount + ") Audio PresentationTimeUs:" + audioBufferInfo.presentationTimeUs + " Flags:" + audioBufferInfo.flags + " Size(KB) " + audioBufferInfo.size / 1024);
    
                    }
                }
    
                Toast.makeText(getApplicationContext(), "frame:" + frameCount2, Toast.LENGTH_SHORT).show();
    
                muxer.stop();
                muxer.release();
    
    
            } catch (IOException e) {
                Log.d(TAG, "Mixer Error 1 " + e.getMessage());
            } catch (Exception e) {
                Log.d(TAG, "Mixer Error 2 " + e.getMessage());
            }
        }
    }
    

答案 1 :(得分:0)

似乎问题在于您的输出文件名是输入。尝试更改输出文件的名称。

FileChannel fc = new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString() + "/video_out.mp4")).getChannel();

答案 2 :(得分:0)

我知道我有点迟到了,但这对那些需要这个的人有帮助:

一些小建议总是尝试使用 AsynchTask 来提供这些东西,它可以让你在背景中拥有这个东西,因为它的方法名为 doInBackground()那么试试看也是以同样的方式帮助你的好东西。

您的代码有一些变化,实施它并且您将获得结果。

File sdCard = Environment.getDataDirectory();

String videofilepath = Environment.getExternalStorageDirectory().toString()+"/video.mp4";
String audiofilepath = Environment.getExternalStorageDirectory().toString()+"/audio.aac";
File file=new File(videofilepath);

Movie videoOutput = null;
Movie audioOutput = null;

try{
            videoOutput = MovieCreator.build(videoFilePath);
            audioOutput = MovieCreator.build(audioFilePath);
        }catch (Exception e){
                e.printStackTrace();
        }

        List<Track> finalTrack = new ArrayList<>();
        for(Track track : videoOutput.getTracks()){
            if(track.getHandler().equals("vide"))
                finalTrack.add(track);
        }

        for(Track track : audioOutput.getTracks()){
            if(track.getHandler().equals("soun"))
                finalTrack.add(track);
        }

        videoOutput.setTracks(finalTrack);

Container mp4file = new DefaultMp4Builder().build(movie);

String filePath = Environment.getExternalStorageDirectory().toString() + "/video.mp4"    

try{
FileChannel fc = new FileOutputStream(new File(filePath)).getChannel();
mp4file.writeContainer(fc);
fc.close();
}catch(Exception e){
   //catch exception 
}
return filePath;

这里filePath是主输出合并文件的路径,它存储在指定的位置。你可以通过在视频播放器中播放来检查它。

快乐学习。如果你愿意,可以随意提出任何问题。 :)

答案 3 :(得分:0)

String videofilepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/append.mp4";
String audiofilepath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/originalSound.aac";

AACTrackImpl aacTrack = null;
try {
    aacTrack = new AACTrackImpl(new FileDataSourceImpl(audiofilepath));
    Movie countVideo = MovieCreator.build(videofilepath);
    Movie movie = new Movie();
    movie.addTrack(countVideo.getTracks().get(0));
    movie.addTrack(aacTrack);

    Container mp4file = new DefaultMp4Builder().build(movie);

    FileChannel fc = new FileOutputStream(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/video.mp4")).getChannel();
    mp4file.writeContainer(fc);
    fc.close();
} catch (IOException e) {
    e.printStackTrace();
}