【Android】使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据
1 简介
本文以 mp4 文件为例,讲解去音频操作。mp4 是一种视频封装的容器,里面包含音频(audio)和视频(video)数据,对应的数据编码格式分别为 aac 和 h264。在去音频过程中,主要使用到 MediaFormat、MediaExtractor、MediaMuxer,其作用如下:
- MediaFormat:用于存储视频轨或音频轨的信息(MIME、时长、帧率、比特率、关键帧间隔、视频宽高等);
- MediaExtractor:媒体分离器,用于分离音频和视频数据,并且能够遍历帧数据;
- MediaMuxer:媒体复合器,用于合成音频和视频数据。
(1)MediaFormat
//初始化
MediaFormat mediaFormat = new MediaFormat()
MediaFormat mediaFormat = mediaExtractor.getTrackFormat(i)
//获取MIME
String mime = mediaFormat.getString(MediaFormat.KEY_MIME)
//获取总时长(单位:微秒us)
long durationTime = mediaFormat.getLong(MediaFormat.KEY_DURATION)
//获取帧率
int frameRate = mediaFormat.getInteger(MediaFormat.KEY_FRAME_RATE)
//获取比特率
int bitRate = mediaFormat.getInteger(MediaFormat.KEY_BIT_RATE)
//获取视频宽度(像素:px)
int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH)
//获取视频高度(像素:px)
int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)
//获取关键帧间隔(单位:秒)
int iFrameInterval = mediaFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL)
用户也可以调用 mediaFormat.setX()方法注入属性。
(2)MediaExtractor
//初始化
MediaExtractor mediaExtractor = new MediaExtractor()
//设置资源
setDataSource(String input_path)
mediaExtractor.setDataSource("/sdcard/Pictures/WeiXin/a.mp4")
//获取轨道数
mediaExtractor.getTrackCount()
//获取 mediaFormat
MediaFormat mediaFormat = mediaExtractor.getTrackFormat(index) //index为轨道编号
//选择轨道
mediaExtractor.selectTrack(index) //index为轨道编号
//读取1帧数据到buffer
int input_size = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE) //获取最大输入缓存大小
ByteBuffer buffer = ByteBuffer.allocate(input_size)
int sampleSize = mediaExtractor.readSampleData(buffer, offset) //offset一般取0
//读取下一帧数据
mediaExtractor.advance()
//定位到timeUs附近的关键帧
mediaExtractor.seekTo(timeUs, mode) //mode一般取 MediaExtractor.SEEK_TO_CLOSEST_SYNC
//释放资源
mediaExtractor.release()
(3)MediaMuxer
//初始化
MediaMuxer(String output_path, int format)
MediaMuxer mediaMuxer = new MediaMuxer("/sdcard/a.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
//添加轨道
int videoTrackIndex = mediaMuxer.addTrack(mediaFormat)
//开始合成文件
mediaMuxer.start()
//写入数据
writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo)
//释放资源
mediaMuxer.stop()
mediaMuxer.release()
2 案例
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void get_video() throws IOException {
String input_path = "/sdcard/Pictures/WeiXin/a.mp4"; //源视频素材
String output_path = "/sdcard/a.mp4"; //去音频后的素材
MediaExtractor mediaExtractor = new MediaExtractor();
mediaExtractor.setDataSource(input_path);
MediaMuxer mediaMuxer = new MediaMuxer(output_path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
int input_size =0;
int videoTrackIndex = -1;
int count = mediaExtractor.getTrackCount(); //获取轨道数
for (int i = 0; i < count; i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) { // mp4为“video/avc”
input_size = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
mediaExtractor.selectTrack(i);
videoTrackIndex = mediaMuxer.addTrack(format);
break;
}
}
mediaMuxer.start();
int sampleSize = 0;
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
ByteBuffer buffer = ByteBuffer.allocate(input_size); //也可以设置为:500*1024
while ((sampleSize = mediaExtractor.readSampleData(buffer, 0)) > 0) {
info.offset = 0;
info.size = sampleSize;
info.flags = mediaExtractor.getSampleFlags();
info.presentationTimeUs = mediaExtractor.getSampleTime();
mediaMuxer.writeSampleData(videoTrackIndex, buffer, info); //写入数据
mediaExtractor.advance(); //下一帧
}
mediaExtractor.release();
mediaMuxer.stop();
mediaMuxer.release();
}
3 拓展
可以通过修改 BufferInfo 的 presentationTimeUs 属性,实现倍速导出视频,如下:
float speed = 3.0f; //播放速度
info.presentationTimeUs = (long)(mediaExtractor.getSampleTime()/speed);
mediaMuxer.writeSampleData(videoTrackIndex, buffer, info); //写入数据
特别注意:不要试图通过修改 BufferInfo 的 flags 属性改变帧标签(I帧、P帧、B帧),若想修改帧标签,需要使用 Mediacodec 重新解码和编码。
声明:本文转自【Android】使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据
【Android】使用MediaExtractor、MediaMuxer去掉视频文件中的音频数据的更多相关文章
- 从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中
//从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中 //作者:sandy //时间:2015-10-10 #inclu ...
- [SimplePlayer] 4. 从视频文件中提取音频
提取音频,具体点来说就是提取音频帧.提取方法与从视频文件中提取图像的方法基本一样,这里仅列出其中的不同点: 1. 由于目的提取音频,因此在demux的时候需要指定的是提取audio stream Au ...
- Atitit.android播放smb 网络邻居视频文件解决方案
Atitit.android播放smb 网络邻居视频文件解决方案 Android4.4 1.1. Android4视频播放器不能直接地支持smb协议..子好先转换成个http流 1.2. ES文件浏览 ...
- Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...
- Android 自定义View及其在布局文件中的使用示例(二)
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...
- (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片
你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...
- [SimplePlayer] 1. 从视频文件中提取图像
在开始之前,我们需要了解视频文件的格式.视频文件的格式众多,无法三言两语就能详细分析其结构,尽管如此,ffmpeg却很好地提取了各类视频文件的共同特性,并对其进行了抽象描述. 视频文件格式,统称为co ...
- 代码实现将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
package com.looaderman.test; import java.io.FileNotFoundException; import java.io.FileOutputStream; ...
- Tensorflow 从文件中载入训练数据
本节包含: 用纯文本文件准备训练数据 加载文件中的训练数据 一.用纯文本文件准备训练数据 1.数据的数字化 比如,“是” —— “1”,“否” —— “0” “优”,“中”,“差” —— 1 2 3 ...
- api进阶Day2(低级流)文件流的输出流、读取流。向文件中写入文本数据、读取文件中的字符串、用lambda表达式创建文件过滤器。
文件流:输出流: package io; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...
随机推荐
- 常见的IE布局兼容问题
(1) div 中内容在IE和火狐中居中问题: (2)高度的问题,div出现重叠 (3)浮动引发的问题如外围DIV无法框住内部元素: (4)IE浮动margin产生双倍距离-display:inli ...
- Go-值传递&引用传递
值类型和引用类型 值类型关注其值 引用类型关注其指针 值类型和引用类型区别在于传递值的时候拷贝的对象不同,值传递拷贝是变量的值,引用传递拷贝的是变量的指针 拷贝 -- 传递值 赋值 函数调用 初始化 ...
- [转帖]安全技术和iptables防火墙
目录 安全技术 Netfilter 防火墙工具介绍 iptables firewalld nftables iptables的组成概述 netfilter与iptables关系 iptables的四表 ...
- [转帖]MegaCli命令
MegaCli命令 设置jbod模式 1.3 LSI 9260/9261 raid卡配置 LSI 9260/9261 raid卡支持0.1.10.5.6.50.60 常用命令: 清除raid卡原有的配 ...
- [转帖]Linux:crontab要点整理(表达式,转义,权限管理,日志)
https://www.jianshu.com/p/fd46652f247e 摘要:Linux,crontab整理crontab的使用,包括cron表达式,设置和删除任务,权限管理,查看日志 cron ...
- 手写promise实现自定义封装多个回调函数的执行
自定义封装多个回调函数的执行 <script src="./Promise.js"></script> let p = new Promise((resol ...
- VictoriaMetrics 1.84.0发布
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 11.25日,valyala大神发布了VictoriaMe ...
- 【JS 逆向百例】Fiddler 插件 Hook 实战,某创帮登录逆向
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途 ...
- IDM(最佳的Windows下载工具)
如果你是一名互联网"老司机",那么一定听过「IDM」这款下载工具的大名!它的全名叫做 Internet Download Manager (互联网下载管理器),缩写就是 IDM. ...
- 【druid切换hikari连接池】通过源码分析遇到的问题
一.前言说明 如果不会配置druid连接池的话,可以参考我这篇博文:springboot整合druid: springboot整合所有的starter方法基本都差不多,添加依赖,开启注解,编写配置,增 ...