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音视频处理之基于MediaCodec合并音视频的更多相关文章

  1. Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析

    场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...

  2. 10分钟快速上车短视频风口:基于uniapp框架创建自己的仿抖音短视APP

    在今年也就是第48次发布的<中国互联网络发展状况统计报告>有这样一个数据,21年的上半年以来,我国我国网民规模达10.11亿,其中短视频用户达8.88亿.碎片化的生活场景下,短视频成为人们 ...

  3. iOS直播-播放基于RTMP协议的视频

    iOS直播-播放基于RTMP协议的视频 流媒体协议介绍 1. 伪流媒体: 渐进式下载 : 边下边存, 文件会保存 使用http协议,也能够实现视频播放, 也能快进快退等, 体验上跟流媒体很像. 优酷, ...

  4. 基于语音识别、音文同步、图像OCR的字幕解决方案HtwMedia介绍

    背景介绍 俗话说,“好记性不如乱笔头”,这充分说明了文字归档的重要性.如今随着微信.抖音等移动端app的使用越来越广,人们生产音.视频内容也越来越便捷.而相比语音和视频而言,文字具有易存档.易检索.易 ...

  5. PyQt+moviepy音视频剪辑实战2:一个剪裁视频文件精华内容留存工具的实现

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 ...

  6. android的四层体系结构,基于mvc三层结构浅析

    从多方面理解Android体系结构 1.以分层的方式来看Android 安卓体系结构分为四层. 首先看一下官方关于Android体系结构的图: 1).Linux Kernel:负责硬件的驱动程序.网络 ...

  7. 基于RTP的H264视频数据打包解包类

    from:http://blog.csdn.net/dengzikun/article/details/5807694 最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打 ...

  8. javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)

    javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...

  9. Android开发学习之路--基于vitamio的视频播放器(二)

      终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...

随机推荐

  1. python 虚拟环境的安装

    方式一 1. pip install virtualenv 2. virtualenv 虚拟环境的名字 3. mac上 source + 虚拟环境的目录/bin/activate win上 直接进入虚 ...

  2. apt-get install oracle-java8-installer时Err:7 http://ppa.launchpad.net/webupd8team/java/ubuntu xenial/main amd64 Packages 404 not found

    所有其他网址都有效,而不是amd64端点. 然后,当运行apt-get install oracle-java8-installer时,出现以下错误: Package oracle-java8-ins ...

  3. Egret Engine 2D - Get Started

    Get Started     Egret 也支持在命令行完成编译,运行,发布等操作.在下面的教程中会穿插对应操作的命令行代码.   可新建游戏项目,也可建eui项目   这里包含默认的几个库,egr ...

  4. C++基础--引用的一点补充

    这一篇是对引用的一点补充,内容基本上是来自<C++ primer plus>一书第八章的内容. 前面一篇介绍了引用的一点特点,这里补充一个,将引用用于类对象的时候,有一个体现继承的特征,就 ...

  5. storm on yarn(CDH5) 部署笔记

    按照storm on yarn(Apache hadoop)部署好之后,然后修改HADOOP_HOME,hadoopenv.sh中的JAVA_HOME,以及storm-yarn-master中pom. ...

  6. Ajax校验用户名是否可用

    准备 导包:DBUtil,JDBC,C3P0 在src下导入c3p0-config.xml 导入JDBCUtil 创建数据库 第2.3.条查看https://blog.csdn.net/weixin_ ...

  7. LeetCode——39. 组合总和

    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重复被选 ...

  8. POJ - 3660 Cow Contest(flod)

    题意:有N头牛,M个关系,每个关系A B表示编号为A的牛比编号为B的牛强,问若想将N头牛按能力排名,有多少头牛的名次是确定的. 分析: 1.a[u][v]=1表示牛u比牛v强,flod扫一遍,可以将所 ...

  9. 基于python的小波阈值去噪算法

    https://blog.csdn.net/alwaystry/article/details/52756051 发表于 2018-01-10 16:32:17 嵌入式设计应用 +关注 小波图像去噪原 ...

  10. VC++ DLL 3 动态链接库

    前面先介绍了静态链接库的方式提供了函数结构的方法,现在就来说下,如果用非MFC的动态链接库要怎么实现,这个过程稍微复杂一点点,但是基本也都是一个套路下来. 1.新建一个工程: 2.编写cpp文件和头文 ...