Android - How is a cartoon of an audio file and a video file?

I have a 3gp file recorded from a microphone and an mp4 video file. I want the mux audio and video file to mp4 file to be saved. I searched a lot, but did not find anything useful to use MediaMuxer api for Android. MediaMuxer api

UPDATE: this is my method that supports two files, I have an exception. and the reason is there is no track in the mp4 destination file! can someOne help me with adding audio and video track to muxer ??

An exception

java.lang.IllegalStateException: Failed to stop the muxer 

my code is:

 private void cloneMediaUsingMuxer( String dstMediaPath) throws IOException { // Set up MediaExtractor to read from the source. MediaExtractor soundExtractor = new MediaExtractor(); soundExtractor.setDataSource(audioFilePath); MediaExtractor videoExtractor = new MediaExtractor(); AssetFileDescriptor afd2 = getAssets().openFd("Produce.MP4"); videoExtractor.setDataSource(afd2.getFileDescriptor() , afd2.getStartOffset(),afd2.getLength()); //PATH //extractor.setDataSource(); int trackCount = soundExtractor.getTrackCount(); int trackCount2 = soundExtractor.getTrackCount(); //assertEquals("wrong number of tracks", expectedTrackCount, trackCount); // Set up MediaMuxer for the destination. MediaMuxer muxer; muxer = new MediaMuxer(dstMediaPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); // Set up the tracks. HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount); for (int i = 0; i < trackCount; i++) { soundExtractor.selectTrack(i); MediaFormat SoundFormat = soundExtractor.getTrackFormat(i); int dstIndex = muxer.addTrack(SoundFormat); indexMap.put(i, dstIndex); } HashMap<Integer, Integer> indexMap2 = new HashMap<Integer, Integer>(trackCount2); for (int i = 0; i < trackCount2; i++) { videoExtractor.selectTrack(i); MediaFormat videoFormat = videoExtractor.getTrackFormat(i); int dstIndex2 = muxer.addTrack(videoFormat); indexMap.put(i, dstIndex2); } // Copy the samples from MediaExtractor to MediaMuxer. boolean sawEOS = false; int bufferSize = MAX_SAMPLE_SIZE; int frameCount = 0; int offset = 100; ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize); MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); MediaCodec.BufferInfo bufferInfo2 = new MediaCodec.BufferInfo(); muxer.start(); while (!sawEOS) { bufferInfo.offset = offset; bufferInfo.size = soundExtractor.readSampleData(dstBuf, offset); bufferInfo2.offset = offset; bufferInfo2.size = videoExtractor.readSampleData(dstBuf, offset); if (bufferInfo.size < 0) { sawEOS = true; bufferInfo.size = 0; bufferInfo2.size = 0; }else if(bufferInfo2.size < 0){ sawEOS = true; bufferInfo.size = 0; bufferInfo2.size = 0; } else { bufferInfo.presentationTimeUs = soundExtractor.getSampleTime(); bufferInfo2.presentationTimeUs = videoExtractor.getSampleTime(); //bufferInfo.flags = extractor.getSampleFlags(); int trackIndex = soundExtractor.getSampleTrackIndex(); int trackIndex2 = videoExtractor.getSampleTrackIndex(); muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, bufferInfo); soundExtractor.advance(); videoExtractor.advance(); frameCount++; } } Toast.makeText(getApplicationContext(),"f:"+frameCount,Toast.LENGTH_SHORT).show(); muxer.stop(); muxer.release(); } 

UPDATE 2: the problem is resolved! check my answer to my question.

thanks for the help

+5
source share
3 answers

I had a problem with audio and video file tracks. they are gone, and everything is fine with my code, but now you can use it to merge the audio file and the 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 code examples: MediaMuxer code examples are really perfect

+10
source

Thanks mohamad ali gharat for this answer, it helps me a lot. But there are some changes that I made to the code to work, first: I change

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

to download video from SDCard . Secondly: I get an error with

videoBufferInfo.flags = videoExtractor.getSampleFlags();

change it to

videoBufferInfo.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;

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

+1
source

What do you need to work in ffmpeg. Here's a link to help with this:

FFmpeg on Android

ffmpeg requires an NDK for Android.

Once you get started, you can work with multiplexing audio and video with ffmpeg. Here's a link to a question that does this with 2 video files (the answer should be similar).

FFMPEG multimedia video and audio (from another video) - display problem

0
source

All Articles