【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 ...
随机推荐
- html - 多次点击选中页面文字出现蓝色背景的解决方法
body{ -moz-user-select: none; /*火狐*/ -webkit-user-select: none; /*webkit浏览器*/ -ms-user-select: none; ...
- [转帖]Spring为啥不推荐使用@Autowired注解?
https://my.oschina.net/u/5079097/blog/5289666 引言 使用IDEA开发时,同组小伙伴都喜欢用@Autowired注入,代码一片warning,看着很不舒 ...
- [转帖]harbor-db restarting问题
现象: 在安装harbor后,启动时发现harbor-db 一直是restarting,/harbor-jobservice,/harbor-core 这两是starting 状态,如下图 解决: 1 ...
- [转帖]88. sys_kwr
88. sys_kwr ¶ 88.1. 插件sys_kwr简介 ¶ 插件sys_kwr是KingbaseES 的一个扩展插件.主要功能是通过周期性自动记录性能统计相关的快照,分析出KingbaseES ...
- [转帖]关于Linux操作系统中LUN的队列深度(queue_depth)
Linux中的queue_depth(队列深度),可以用lsscsi查看. 不过今天在我的vm 虚拟机环境中(无外界存储),是没有lsscsi命令. 不过,从网上,搜到了如下的信息: $ lsscsi ...
- [转帖]Nginx 性能测试
https://plantegg.github.io/2022/10/10/Nginx%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95/ 压测工具选择 wrk ,apache ...
- Linux 开启防火墙 避免非干系人误操作的处理
公司里面进行系统集成测试. 不想让开发能够更改我的服务器信息, 但是改密码又太麻烦了. 想了想还是用 防火墙好一些. 第一步 开启防火墙 systemctl enable firewalld syst ...
- js数组修改后会互相影响
// 假设httpServe 是服务器返回来的数据 // 我们这里有一个需求, // 某一个区域需要对这一份数据进行展示 // 另一个区域需要只需要展示前1条数据 let httpServe = [ ...
- ClickHouse(09)ClickHouse合并树MergeTree家族表引擎之MergeTree详细解析
目录 建表 数据存储 主键和索引在查询中的表现 主键的选择 选择与排序键不同的主键 索引和分区在查询中的应用 部分单调主键的使用 跳数索引 可用的索引类型 并发数据访问 列和表的 TTL 列TTL 表 ...
- 小白学k8s(12)-k8s中PV和PVC理解
pv和pvc 什么是pv和PVC 生命周期 PV创建的流程 1.创建一个远程块存储,相当于创建了一个磁盘,称为Attach 2.将这个磁盘设备挂载到宿主机的挂载点,称为Mount 3.绑定 持久化卷声 ...