Skip to content

Instantly share code, notes, and snippets.

@ArsalRaza
Last active January 25, 2024 11:39
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save ArsalRaza/132a6e99d59aa80b9861ae368bc786d0 to your computer and use it in GitHub Desktop.
Save ArsalRaza/132a6e99d59aa80b9861ae368bc786d0 to your computer and use it in GitHub Desktop.
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
Copy link
Author

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
Copy link

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
Copy link

@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
Copy link

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

@danimask
Copy link

Thank you very much for your concern

@liuhaitai
Copy link

Nice~

@corgiwooer
Copy link

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

@AamirNaseer1
Copy link

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

@mohammadhosseinjafaripour

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

@ArsalImam
Copy link

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

yes, just wrap it inside asynctask

@ArsalImam
Copy link

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
Copy link

kishanverma26 commented Jun 10, 2020

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

@kerolsafififawzy
Copy link

How do I know if I have completed the transfer or not in order to do so?
My question may be a foolish but a beginner

@Kanishk251296
Copy link

Code is working fine but is there a way to get the codec format of audio in mp3 format
Extension is showing mp3 but the codec of audio is AAC

@ChudamaniMeher
Copy link

ChudamaniMeher commented Jan 30, 2021

Which way the source path is given?
I tried both Uri(content:\..) path and real path(/storage/emulated/0/Download/..)
on both, I get this error
E/ClearFileSource: Failed to open file /filename/ (No such file or directory)
please help me.

@ChudamaniMeher
Copy link

Code is working fine but is there a way to get the codec format of audio in mp3 format
Extension is showing mp3 but the codec of audio is AAC

Which way the source path is given?
I tried both Uri(content:..) path and real path(/storage/emulated/0/Download/..)
on both, I get this error
E/ClearFileSource: Failed to open file /filename/ (No such file or directory)
please help me.

@bboymoonchild
Copy link

Hi. I changed srcPath from string to Uri, to use the video loaded from mediastore intent.
And it shows the message :

V/MediaWriter: Track event err/info msg:101, trackId:1, type:1000,val:-1011
I/MPEG4Writer: Normal stop process
D/MPEG4Writer: Audio track stopping. Stop source
Audio track source stopping
Audio track source stopped

Can you tell me why this happens ? It seems that I cannot separate the audio/video .

@Apsalogics
Copy link

Apsalogics commented Feb 15, 2021

i Try to Mute the Video By using this Class
But when Video Size is too Big Mean more then an Hour Ore very less mean half minute than muxer is Failed to Stop

My Logcat is

Process: Pakig name, PID: 23171
java.lang.IllegalStateException: Failed to stop the muxer
at android.media.MediaMuxer.nativeStop(Native Method)
at android.media.MediaMuxer.stop(MediaMuxer.java:466)
at Pakig name.ConverterFolder.AudioExtractor.genVideoUsingMuxer(AudioExtractor.java:108)
at Pakig name.ConverterFolder.Convert_VideoToMp3_Activity.StartAbstractionVideo(Convert_VideoToMp3_Activity.java:459)
at Pakig name.ConverterFolder.Convert_VideoToMp3_Activity.MuteVideoFile(Convert_VideoToMp3_Activity.java:443)
at Pakig name.ConverterFolder.Convert_VideoToMp3_Activity.access$100(Convert_VideoToMp3_Activity.java:86)
at Pakig name.ConverterFolder.Convert_VideoToMp3_Activity$10.onClick(Convert_VideoToMp3_Activity.java:327)
at android.view.View.performClick(View.java:7394)
at android.view.View.performClickInternal(View.java:7348)
at android.view.View.access$3900(View.java:827)
at android.view.View$PerformClick.run(View.java:28293)
at android.os.Handler.handleCallback(Handler.java:899)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:238)
at android.app.ActivityThread.main(ActivityThread.java:7864)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:998)

@ad-swiderek
Copy link

Code is working fine but is there a way to get the codec format of audio in mp3 format
Extension is showing mp3 but the codec of audio is AAC

Which way the source path is given?
I tried both Uri(content:..) path and real path(/storage/emulated/0/Download/..)
on both, I get this error
E/ClearFileSource: Failed to open file /filename/ (No such file or directory)
please help me.

Same issue here, did you find a solution?

@arinmodi
Copy link

arinmodi commented Aug 9, 2021

How can i track the progress of audio extraction in percentage ?

@ArsalImam
Copy link

ArsalImam commented Aug 19, 2021

@iamsarwandahri The above code doesn't add any extension, it uses dstPath for the extension (this means your dstPath has mp4 as an extension, please implement your own stuff correctly before asking others for the improvement). If you have any doubts other than that, you can write your own implementation for MediaMuxer/MediaExtractor/MediaCodec.
Thanks, mate.

@ArsalImam
Copy link

@arinmodi

How can i track the progress of audio extraction in percentage ?

You can modify the for iteration and calculate the percentage (on the basis of track count) there.

@ArsalImam
Copy link

ArsalImam commented Aug 19, 2021

Code is working fine but is there a way to get the codec format of audio in mp3 format
Extension is showing mp3 but the codec of audio is AAC

Which way the source path is given?
I tried both Uri(content:..) path and real path(/storage/emulated/0/Download/..)
on both, I get this error
E/ClearFileSource: Failed to open file /filename/ (No such file or directory)
please help me.

@ChudamaniMeher @ad-swiderek it is based on file path (Uri will not work as MediaMuxer doesn't support remote Uris)

@iamsarwandahri
Copy link

@iamsarwandahri The above code doesn't add any extension, it uses dstPath for the extension (this means your dstPath has mp4 as an extension, please implement your own stuff correctly before asking others for the improvement). If you have any doubts other than that, you can write your own implementation for MediaMuxer/MediaExtractor/MediaCodec.
Thanks, mate.

I was mistaken, Thanks mate.

@AamirMehmoodlucky
Copy link

arsl i need your two mintues please

@avirias
Copy link

avirias commented Oct 8, 2021

It's throwing java.lang.IllegalStateException: Failed to add the track to the muxer here

@DoozyDoz
Copy link

@arinmodi

How can i track the progress of audio extraction in percentage ?

You can modify the for iteration and calculate the percentage (on the basis of track count) there.

This makes the progress only 2, I would prefer tracking the progress of the audio extraction

@DikenMaharjan
Copy link

The audio of .ts files are broken and the audio is not continuous.. Is this the problem of .ts file or emulator or extractor doesn't work well with .ts files?

@codeAndroid725
Copy link

i want to fast forward a video containing audio from the above code.
I am changing presentationTime as:
bufferInfo.presentationTimeUs= (bufferInfo.presentationTimeUs/4)
It speed's up my video but audio has not been fasten
Help Me......

@BitBlueDevStudio
Copy link

What is the real output audio file format in the end?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment