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的视频播放器(一)中,主要讲了播放器的界面的 ...
随机推荐
- 【剑指Offer】面试题10- II. 青蛙跳台阶问题
题目 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶.求该青蛙跳上一个 n 级的台阶总共有多少种跳法. 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返 ...
- SpringBoot的Banner横幅
SpringBoot的Banner横幅即在SpringBoot应用程序启动过程中,日志输出的如下内容: 如果想替换此部分内容的话,可以在classpath根路径下建立一个文件,命名为:banner.t ...
- UltraISO制作manjaro系统盘,使用优盘
下载系统镜像 默认是清华镜像 刻入方式一定要选RAW方式
- springmvc的InternalResourceViewResolver自我理解
原文链接:https://blog.csdn.net/wwzuizz/article/details/78268007 它的作用是在Controller返回的时候进行解析视图 @RequestMapp ...
- Codeforces_449B 最短路+统计
也是给这个题目跪了一天...时间不多了,也不多讲 首先要用 nlogn的优先队列dijstla来求最短路,n^2的会超时,不过发现SPFA好像也可以过,他的复杂度应该介于NlogN和N^2之间. 然后 ...
- python print %s 号格式化输出
python %号格式化输出: 一种字符串格式化的语法, 基本用法是将值插入到%s占位符的字符串中. %s,表示格式化一个对象为字符 "%±(正负号表示)3(数字表示字符串的长度)s&quo ...
- 修改完Apache的配置文件,重启Apache后,仍无法打开网页
在修改Apache的配置文件时,由于某些非正常操作,导致httpd.conf文件非正常打开,需要继续enter进入, 这是会在httpd.conf同级目录中产生一个隐藏文件,.httpd.conf.s ...
- adfs环境安装
安装文档参考: https://docs.microsoft.com/zh-cn/windows-server/identity/ad-fs/deployment/set-up-the-lab-env ...
- pandas dataframe取差集:删掉已存在的数据,保留未插入的数据
适用场景: 插入数据到mysql中,中途中断,导致部分数据未插入成功.避免下次插入时插入了重复的数据. 思路: 1.读取已插入的数据, 2.读取全部数据(包含已插入和未插入的), 3.将已插入的数据添 ...
- CSS 宽,高,背景设置
width 宽,height 高,background 背景:背景色 background-color:颜色值--英文单词/十六进制/rgb:背景图 background-image:url(‘图片路 ...