Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Extract Audio from Video, Mute Video, Crop Video from start, Crop Video from end Android MediaMuxer - JAVA
import android.annotation.SuppressLint;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaMuxer;
import android.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
// Copyright (c) 2018 ArsalImam
// All Rights Reserved
//
public class AudioExtractor {
private static final int DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024;
private static final String TAG = "AudioExtractorDecoder";
/**
* @param srcPath the path of source video file.
* @param dstPath the path of destination video file.
* @param startMs starting time in milliseconds for trimming. Set to
* negative if starting from beginning.
* @param endMs end time for trimming in milliseconds. Set to negative if
* no trimming at the end.
* @param useAudio true if keep the audio track from the source.
* @param useVideo true if keep the video track from the source.
* @throws IOException
*/
@SuppressLint("NewApi")
public void genVideoUsingMuxer(String srcPath, String dstPath, int startMs, int endMs, boolean useAudio, boolean useVideo) throws IOException {
// Set up MediaExtractor to read from the source.
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(srcPath);
int trackCount = extractor.getTrackCount();
// Set up MediaMuxer for the destination.
MediaMuxer muxer;
muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// Set up the tracks and retrieve the max buffer size for selected
// tracks.
HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount);
int bufferSize = -1;
for (int i = 0; i < trackCount; i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
boolean selectCurrentTrack = false;
if (mime.startsWith("audio/") && useAudio) {
selectCurrentTrack = true;
} else if (mime.startsWith("video/") && useVideo) {
selectCurrentTrack = true;
}
if (selectCurrentTrack) {
extractor.selectTrack(i);
int dstIndex = muxer.addTrack(format);
indexMap.put(i, dstIndex);
if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
bufferSize = newSize > bufferSize ? newSize : bufferSize;
}
}
}
if (bufferSize < 0) {
bufferSize = DEFAULT_BUFFER_SIZE;
}
// Set up the orientation and starting time for extractor.
MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
retrieverSrc.setDataSource(srcPath);
String degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
if (degreesString != null) {
int degrees = Integer.parseInt(degreesString);
if (degrees >= 0) {
muxer.setOrientationHint(degrees);
}
}
if (startMs > 0) {
extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
}
// Copy the samples from MediaExtractor to MediaMuxer. We will loop
// for copying each sample and stop when we get to the end of the source
// file or exceed the end time of the trimming.
int offset = 0;
int trackIndex = -1;
ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
muxer.start();
while (true) {
bufferInfo.offset = offset;
bufferInfo.size = extractor.readSampleData(dstBuf, offset);
if (bufferInfo.size < 0) {
Log.d(TAG, "Saw input EOS.");
bufferInfo.size = 0;
break;
} else {
bufferInfo.presentationTimeUs = extractor.getSampleTime();
if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) {
Log.d(TAG, "The current sample is over the trim end time.");
break;
} else {
bufferInfo.flags = extractor.getSampleFlags();
trackIndex = extractor.getSampleTrackIndex();
muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, bufferInfo);
extractor.advance();
}
}
}
muxer.stop();
muxer.release();
return;
}
}
@ArsalRaza

This comment has been minimized.

Copy link
Owner Author

@ArsalRaza ArsalRaza commented Nov 2, 2018

Usage:

Extract Audio From Video:
new AudioExtractor().genVideoUsingMuxer(videoFile, originalAudio, -1, -1, true, false);

Extract Video From Video (Mute):
new AudioExtractor().genVideoUsingMuxer(videoFile, originalAudio, -1, -1, false, true);

Crop Video From Start:
new AudioExtractor().genVideoUsingMuxer(videoFile, originalAudio, timeFromWhereToStart, -1, true, true);

Crop Video From End:
new AudioExtractor().genVideoUsingMuxer(videoFile, originalAudio, -1, timeFromWhereToEnd, true, true);

@danimask

This comment has been minimized.

Copy link

@danimask danimask commented Sep 19, 2019

can someone can tell me how to extract audio from MKV video file this API is working fine for mp4 but not on MKV videos?
thank you

@ArsalImam

This comment has been minimized.

Copy link

@ArsalImam ArsalImam commented Sep 20, 2019

@danimask Currently, MediaMuxer doesn't support MKV format, please check,

MediaMuxer facilitates muxing elementary streams. Currently, MediaMuxer supports MP4, WebM and 3GP file as the output. It also supports muxing B-frames in MP4 since Android Nougat.

ref: https://developer.android.com/reference/android/media/MediaMuxer

@ArsalImam

This comment has been minimized.

Copy link

@ArsalImam ArsalImam commented Sep 20, 2019

You can use ffmpeg-lite to convert MKV format to MP4

@danimask

This comment has been minimized.

Copy link

@danimask danimask commented Sep 23, 2019

Thank you very much for your concern

@liuhaitai

This comment has been minimized.

Copy link

@liuhaitai liuhaitai commented Oct 11, 2019

Nice~

@corgiwooer

This comment has been minimized.

Copy link

@corgiwooer corgiwooer commented Nov 15, 2019

Hey, i have some confusions, can anymone provide me the complete code

@AamirNaseer1

This comment has been minimized.

Copy link

@AamirNaseer1 AamirNaseer1 commented Jan 10, 2020

hi
how can I get converted audio file from this function and store that file in phone storage ?

@mohammadhosseinjafaripour

This comment has been minimized.

Copy link

@mohammadhosseinjafaripour mohammadhosseinjafaripour commented Mar 11, 2020

hi , i was checking that is it possible to achieve it with asynctask ?

@ArsalImam

This comment has been minimized.

Copy link

@ArsalImam ArsalImam commented May 23, 2020

hi , i was checking that is it possible to achieve it with asynctask ?

yes, just wrap it inside asynctask

@ArsalImam

This comment has been minimized.

Copy link

@ArsalImam ArsalImam commented May 23, 2020

hi
how can I get converted audio file from this function and store that file in phone storage ?

@AamirNaseer1
this method will save the converted audio file on the phone storage on the path which you need to provide through parameter dstPath

@kishanverma26

This comment has been minimized.

Copy link

@kishanverma26 kishanverma26 commented Jun 10, 2020

getting issue
java.lang.RuntimeException: Unable to start activity ComponentInfo{MyActivity}: java.lang.IllegalStateException: Failed to start the muxer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.