Android音视频处理之基于MediaCodec合并音视频
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合并音视频的更多相关文章
- Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析
		场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ... 
- 10分钟快速上车短视频风口:基于uniapp框架创建自己的仿抖音短视APP
		在今年也就是第48次发布的<中国互联网络发展状况统计报告>有这样一个数据,21年的上半年以来,我国我国网民规模达10.11亿,其中短视频用户达8.88亿.碎片化的生活场景下,短视频成为人们 ... 
- iOS直播-播放基于RTMP协议的视频
		iOS直播-播放基于RTMP协议的视频 流媒体协议介绍 1. 伪流媒体: 渐进式下载 : 边下边存, 文件会保存 使用http协议,也能够实现视频播放, 也能快进快退等, 体验上跟流媒体很像. 优酷, ... 
- 基于语音识别、音文同步、图像OCR的字幕解决方案HtwMedia介绍
		背景介绍 俗话说,“好记性不如乱笔头”,这充分说明了文字归档的重要性.如今随着微信.抖音等移动端app的使用越来越广,人们生产音.视频内容也越来越便捷.而相比语音和视频而言,文字具有易存档.易检索.易 ... 
- PyQt+moviepy音视频剪辑实战2:一个剪裁视频文件精华内容留存工具的实现
		专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 ... 
- android的四层体系结构,基于mvc三层结构浅析
		从多方面理解Android体系结构 1.以分层的方式来看Android 安卓体系结构分为四层. 首先看一下官方关于Android体系结构的图: 1).Linux Kernel:负责硬件的驱动程序.网络 ... 
- 基于RTP的H264视频数据打包解包类
		from:http://blog.csdn.net/dengzikun/article/details/5807694 最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打 ... 
- javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)
		javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ... 
- Android开发学习之路--基于vitamio的视频播放器(二)
		终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ... 
随机推荐
- (排序EX)P1093 奖学金
			题解: #include<iostream>using namespace std;int r=0;void swap(int &a,int &b){ int t=a; ... 
- PWC6199:Generated servlet error:Only a type can be imported. org.apache.jasper.tagplugins.jstl.core.ForEach resolves to a package
			<%@ import="org.apache.jasper.tagplugins.jstl.core.ForEach"%> 去掉这条语句,就不报错了.所以问题就出在这里 ... 
- 2.9 初识 jetpack
			Android Jetpack 组件 Android Jetpack 组件是库的集合 这些库是为协同工作而构建的,也可以单独采用,同时利用 Kotlin 语言功能帮助提高工作效率.可全部使用,也可混合 ... 
- quartz详解1:初步了解quartz
			http://blog.itpub.NET/11627468/viewspace-1763389/ 一.引入 你曾经需要应用执行一个任务吗?这个任务每天或每周星期二晚上11:30,或许仅仅每个月的最后 ... 
- 学习spring的第二天
			对昨天的查漏:关于<bean>标签的scope属性,是由它决定原型和单例的,而不是说你java代码中用到了单例模式就是单例了. 其二就是lazy-init属性,它对于scope=" ... 
- jsch通过SSH2执行linux命令
			public class SSHUtils { private Channel channel; private Session session = null; private int timeout ... 
- UVA - 1631 Locker(密码锁)(dp---记忆化搜索)
			题意:有一个n(n<=1000)位密码锁,每位都是0~9,可以循环旋转.每次可以让1~3个相邻数字同时往上或者往下转一格.输入初始状态和终止状态(长度不超过1000),问最少要转几次. 分析: ... 
- Neo4j--常用的查询语句
			参考 https://www.w3cschool.cn/neo4j 准备工作 插入一堆朝代节点 插入我大明皇帝节点 创建大明皇帝统治大明王朝的关系 看一下结果 WHERE WHERE 语法 WHERE ... 
- FTP服务器 vsftp samba服务器 共享 smb
			FTP服务器 vsftp samba服务器 共享 smb 马哥视频 参考1 参考3 参考2 参考4 vsftp服务器实现匿名用户上传.修改权限和一些设置 win7访问 地址栏输入 ftp://账号 ... 
- SpringCloud学习之手把手教你用IDEA搭建入门项目(二)
			本篇博客是承接上一篇<手把手教你用IDEA搭建SpringCloud入门项目(一)>,不清楚的请到我的博客空间查看后再看本篇博客 1)先创建一个Eureka服务注册中心模块,用来作为服务的 ... 
