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();

最新文章

  1. Apply 与 Call 的用法(简化版)
  2. C#、.NET网络请求总结(WebClient和WebRequest)
  3. VC++全局变量初始化
  4. Windows Phone 开发起步之旅之一 平台环境的搭建
  5. 用sql获取某字符串中的数字部分的语句
  6. 【转】使用命令行方式创建和启动android模拟器
  7. ZOJ3768 夹逼查找【STL__lower_bound()_的应用】
  8. 在微信小程序中学习flex布局
  9. FastDFS 学习笔记
  10. admin 显示多对多字段
  11. python生成器 获取 目录下文件
  12. while循环 格式化输出 密码本 编码的初识
  13. JPush Flutter Plugin(Futter推送-极光推送)
  14. Android SDK开发
  15. Android学习笔记二:activity的理解
  16. 推荐系统之余弦相似度的Spark实现
  17. IIR滤波器设计(调用MATLAB IIR函数来实现)
  18. Delphi 组件渐进开发浅谈(一)——由简入繁
  19. 单源最短路径spfa模板(pascal)洛谷P3371
  20. Redis的字典扩容与ConcurrentHashMap的扩容策略比较

热门文章

  1. 自定义 radio 的样式,更改选中样式
  2. windows自带的颜色编辑器居中
  3. java内存机制 垃圾回收
  4. 爱奇艺用券付费VIP电影+python爬虫程序+可视化界面+下载本地
  5. bugku-Web 文件包含2
  6. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring框架的基本思想
  7. python期末复习—列表
  8. 2020PHP面试-SQL篇
  9. OGG实验:喂奶间隔数据表通过OGG配置同步
  10. JavaScript 之 异步请求