android - How to mux audio file and video file?

前端 未结 3 691
傲寒
傲寒 2020-12-05 06:09

i have a 3gp file that is recorded from the microphone and a mp4 video file. i want to mux audio file and video file in to a mp4 file and save it. i searched a lot but didn\

相关标签:
3条回答
  • 2020-12-05 06:30

    What you'll need to get working in ffmpeg. Here's a link to help with that:

    FFmpeg on Android

    ffmpeg requires the NDK on Android.

    Once you have that working, you can work on muxing the audio and video together using ffmpeg. Here's a link to a question that does it with 2 video files (the answer should be similar).

    FFMPEG mux video and audio (from another video) - mapping issue

    0 讨论(0)
  • 2020-12-05 06:39

    I had some problem with tracks of audio and video files. they gone and every thing is ok with my code , but Now you can use it for merging an audio file and a video file together.

    Code:

    private void muxing() {
    
    String outputFile = "";
    
    try {
    
        File file = new File(Environment.getExternalStorageDirectory() + File.separator + "final2.mp4");
        file.createNewFile();
        outputFile = file.getAbsolutePath();
    
        MediaExtractor videoExtractor = new MediaExtractor();
        AssetFileDescriptor afdd = getAssets().openFd("Produce.MP4");
        videoExtractor.setDataSource(afdd.getFileDescriptor() ,afdd.getStartOffset(),afdd.getLength());
    
        MediaExtractor audioExtractor = new MediaExtractor();
        audioExtractor.setDataSource(audioFilePath);
    
        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 = videoExtractor.getSampleFlags();
                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 = audioExtractor.getSampleFlags();
                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());
    }
    

    }

    thanks to these sample codes:MediaMuxer Sample Codes-really perfect

    0 讨论(0)
  • 2020-12-05 06:43

    Thanks mohamad ali gharat for this answer, it's help me too much. But there is some change I made to code to work, first: I change

    videoExtractor.setDataSource to videoExtractor.setDataSource(Environment.getExternalStorageDirectory().getPath() + "/Produce.MP4");

    to load video from SDCard. Second: I get error with

    videoBufferInfo.flags = videoExtractor.getSampleFlags();

    so change it to

    videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;

    to make it work as this link say Android MediaMuxer failed to stop

    0 讨论(0)
提交回复
热议问题