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();
来源:简书