-
-
Save danimask/58565e4d2a3648f3f85d13877e63fb0a 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment