android中视频压缩功能 示例
时间: 2024-04-22 07:23:53 浏览: 284
Android中可以使用MediaCodec和MediaMuxer来实现视频压缩功能。以下是一个简单的示例:
```java
public class VideoCompressor {
private final static String TAG = "VideoCompressor";
private static final String MIME_TYPE = "video/avc";
private static final int FRAME_RATE = 30;
private static final int I_FRAME_INTERVAL = 1;
private static final int TIMEOUT_US = 10000;
private int mWidth;
private int mHeight;
private int mBitRate;
private int mFrameRate;
private int mIFrameInterval;
private String mInputFilePath;
private String mOutputFilePath;
public VideoCompressor(int width, int height, int bitRate, int frameRate, int iFrameInterval, String inputFilePath, String outputFilePath) {
mWidth = width;
mHeight = height;
mBitRate = bitRate;
mFrameRate = frameRate;
mIFrameInterval = iFrameInterval;
mInputFilePath = inputFilePath;
mOutputFilePath = outputFilePath;
}
public void compress() throws IOException {
MediaExtractor extractor = null;
MediaMuxer muxer = null;
MediaCodec codec = null;
try {
extractor = new MediaExtractor();
extractor.setDataSource(mInputFilePath);
int trackIndex = -1;
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
extractor.selectTrack(i);
codec = MediaCodec.createEncoderByType(MIME_TYPE);
codec.configure(getOutputFormat(format), null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
break;
}
}
if (codec == null) {
throw new RuntimeException("Can't find video track!");
}
muxer = new MediaMuxer(mOutputFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
MediaFormat format = codec.getOutputFormat();
int track = muxer.addTrack(format);
muxer.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
boolean isEOS = false;
long presentationTimeUs = 0;
while (!isEOS) {
int inputBufferIndex = codec.dequeueInputBuffer(TIMEOUT_US);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0) {
codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
presentationTimeUs = extractor.getSampleTime();
codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, TIMEOUT_US);
if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 && bufferInfo.size != 0) {
codec.releaseOutputBuffer(outputBufferIndex, false);
} else {
muxer.writeSampleData(track, outputBuffer, bufferInfo);
codec.releaseOutputBuffer(outputBufferIndex, false);
}
}
}
muxer.stop();
muxer.release();
extractor.release();
codec.stop();
codec.release();
} catch (IOException e) {
Log.e(TAG, "Failed to compress video", e);
throw e;
} finally {
if (muxer != null) {
try {
muxer.stop();
muxer.release();
} catch (Exception e) {
Log.e(TAG, "Failed to release muxer", e);
}
}
if (extractor != null) {
try {
extractor.release();
} catch (Exception e) {
Log.e(TAG, "Failed to release extractor", e);
}
}
if (codec != null) {
try {
codec.stop();
codec.release();
} catch (Exception e) {
Log.e(TAG, "Failed to release codec", e);
}
}
}
}
private MediaFormat getOutputFormat(MediaFormat inputFormat) {
int width = mWidth;
int height = mHeight;
int bitRate = mBitRate;
int frameRate = mFrameRate;
int iFrameInterval = mIFrameInterval;
if (inputFormat.containsKey(MediaFormat.KEY_WIDTH)) {
width = inputFormat.getInteger(MediaFormat.KEY_WIDTH);
}
if (inputFormat.containsKey(MediaFormat.KEY_HEIGHT)) {
height = inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
}
if (inputFormat.containsKey(MediaFormat.KEY_BIT_RATE)) {
bitRate = inputFormat.getInteger(MediaFormat.KEY_BIT_RATE);
}
if (inputFormat.containsKey(MediaFormat.KEY_FRAME_RATE)) {
frameRate = inputFormat.getInteger(MediaFormat.KEY_FRAME_RATE);
}
if (inputFormat.containsKey(MediaFormat.KEY_I_FRAME_INTERVAL)) {
iFrameInterval = inputFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL);
}
MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate);
outputFormat.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1000000 / frameRate);
return outputFormat;
}
}
```
此示例使用H.264编码器,将输入的视频文件压缩为具有自定义宽度,高度,比特率,帧率和关键帧间隔的输出文件。
阅读全文