Android音视频处理之MediaExtractor
16lz
2021-01-24
Android提供了一个MediaExtractor类,可以用来分离容器中的视频track和音频track,下面的例子展示了使用MediaExtractor和MediaMuxer来实现视频的换音:
private void muxingAudioAndVideo() throws IOException { MediaMuxer mMediaMuxer = new MediaMuxer(mOutputVideoPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); // 视频的MediaExtractor MediaExtractor mVideoExtractor = new MediaExtractor(); mVideoExtractor.setDataSource(mVideoPath); int videoTrackIndex = -1; for (int i = 0; i < mVideoExtractor.getTrackCount(); i++) { MediaFormat format = mVideoExtractor.getTrackFormat(i); if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) { mVideoExtractor.selectTrack(i); videoTrackIndex = mMediaMuxer.addTrack(format); break; } } // 音频的MediaExtractor MediaExtractor mAudioExtractor = new MediaExtractor(); mAudioExtractor.setDataSource(mAudioPath); int audioTrackIndex = -1; for (int i = 0; i < mAudioExtractor.getTrackCount(); i++) { MediaFormat format = mAudioExtractor.getTrackFormat(i); if (format.getString(MediaFormat.KEY_MIME).startsWith("audio/")) { mAudioExtractor.selectTrack(i); audioTrackIndex = mMediaMuxer.addTrack(format); } } // 添加完所有轨道后start mMediaMuxer.start(); // 封装视频track if (-1 != videoTrackIndex) { MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); info.presentationTimeUs = 0; ByteBuffer buffer = ByteBuffer.allocate(100 * 1024); while (true) { int sampleSize = mVideoExtractor.readSampleData(buffer, 0); if (sampleSize < 0) { break; } info.offset = 0; info.size = sampleSize; info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME; info.presentationTimeUs = mVideoExtractor.getSampleTime(); mMediaMuxer.writeSampleData(videoTrackIndex, buffer, info); mVideoExtractor.advance(); } } // 封装音频track if (-1 != audioTrackIndex) { MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); info.presentationTimeUs = 0; ByteBuffer buffer = ByteBuffer.allocate(100 * 1024); while (true) { int sampleSize = mAudioExtractor.readSampleData(buffer, 0); if (sampleSize < 0) { break; } info.offset = 0; info.size = sampleSize; info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME; info.presentationTimeUs = mAudioExtractor.getSampleTime(); mMediaMuxer.writeSampleData(audioTrackIndex, buffer, info); mAudioExtractor.advance(); } } // 释放MediaExtractor mVideoExtractor.release(); mAudioExtractor.release(); // 释放MediaMuxer mMediaMuxer.stop(); mMediaMuxer.release();}
MediaExtractor的接口比较简单,首先通过setDataSource()设置数据源,数据源可以是本地文件地址,也可以是网络地址:
MediaExtractor mVideoExtractor = new MediaExtractor();mVideoExtractor.setDataSource(mVideoPath);
然后可以通过getTrackFormat(int index)来获取各个track的MediaFormat,通过MediaFormat来获取track的详细信息,如:MimeType、分辨率、采样频率、帧率等等:
for (int i = 0; i < mVideoExtractor.getTrackCount(); i++) { MediaFormat format = mVideoExtractor.getTrackFormat(i);}
获取到track的详细信息后,通过selectTrack(int index)选择指定的通道:
if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) { mVideoExtractor.selectTrack(i); break;}
指定通道之后就可以从MediaExtractor中读取数据了:
while (true) { int sampleSize = mVideoExtractor.readSampleData(buffer, 0); if (sampleSize < 0) { break; } // do something mVideoExtractor.advance(); // 移动到下一帧}
在读取结束之后,记得释放资源:
mVideoExtractor.release();
更多相关文章
- 腾讯微博客户端开发视频--若水(第三集、第四集)
- Android(安卓)VideoView播放视频
- 音视频转码合成
- Android调用系统摄像头--使用MediaRecorder--2--使用MediaRecord
- android 随手记 videoview循环播放网络视频 和mediaplayer+sufac
- Android(安卓)选择图片、上传图片之PictureSelector
- Android视频方向为什么出现问题以及Android视频应用开发中的处理
- android和PC(Python)通过USB(adb模式)基于Socket传输图像(视频)
- Android(java方法)上实现mp4的分割和拼接 (二)