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去掉视频文件中的音频数据的更多相关文章

  1. 从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中

    //从视频文件中读入数据-->将数据转换为灰度图-->对图像做canny边缘检测-->将这三个结构显示在一个图像中 //作者:sandy //时间:2015-10-10 #inclu ...

  2. [SimplePlayer] 4. 从视频文件中提取音频

    提取音频,具体点来说就是提取音频帧.提取方法与从视频文件中提取图像的方法基本一样,这里仅列出其中的不同点: 1. 由于目的提取音频,因此在demux的时候需要指定的是提取audio stream Au ...

  3. Atitit.android播放smb 网络邻居视频文件解决方案

    Atitit.android播放smb 网络邻居视频文件解决方案 Android4.4 1.1. Android4视频播放器不能直接地支持smb协议..子好先转换成个http流 1.2. ES文件浏览 ...

  4. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  5. Android 自定义View及其在布局文件中的使用示例(二)

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...

  6. (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片

    你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...

  7. [SimplePlayer] 1. 从视频文件中提取图像

    在开始之前,我们需要了解视频文件的格式.视频文件的格式众多,无法三言两语就能详细分析其结构,尽管如此,ffmpeg却很好地提取了各类视频文件的共同特性,并对其进行了抽象描述. 视频文件格式,统称为co ...

  8. 代码实现将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出

    package com.looaderman.test; import java.io.FileNotFoundException; import java.io.FileOutputStream; ...

  9. Tensorflow 从文件中载入训练数据

    本节包含: 用纯文本文件准备训练数据 加载文件中的训练数据 一.用纯文本文件准备训练数据 1.数据的数字化 比如,“是” —— “1”,“否” —— “0” “优”,“中”,“差” —— 1 2 3  ...

  10. api进阶Day2(低级流)文件流的输出流、读取流。向文件中写入文本数据、读取文件中的字符串、用lambda表达式创建文件过滤器。

    文件流:输出流: package io; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...

随机推荐

  1. [转帖]Export Prometheus metrics from SQL queries

    https://github.com/albertodonato/query-exporter query-exporter is a Prometheus exporter which allows ...

  2. [转帖]存储器分级:L1 Cache 比内存和 SSD 快多少倍?

    目录 1.为什么会有存储器分级策略? 2.存储器分级策略 2.1 存储器的级别 2.2.1 L1-Cache 2.2.2 L2-Cache 2.2.3 L3-Cache 3.内存 4.SSD 和硬盘 ...

  3. [转帖]Linux进程的Uninterruptible sleep(D)状态

    https://cloud.tencent.com/developer/article/1581022 Linux系统进程状态 PROCESS STATE CODES Here are the dif ...

  4. [转帖]学会使用Kafka(八)Kafka基本客户端命令操作

    https://www.cnblogs.com/rexcheny/articles/9463811.html 主题管理 创建主题 1 kafka-topics.sh --bootstrap-serve ...

  5. [转帖]Linux中awk命令正确的求最大值、最小值、平均值、总和

    https://blog.csdn.net/fireblue1990/article/details/51622416 test.txt文件内容: 9 11 35 21 42 118 求最大值: aw ...

  6. 【转帖】Java Full GC (Ergonomics) 的排查

    文章目录 1. Full GC (Ergonomics) 1.1 Java 进程一直进行 Full GC 1.2 Full GC 的原因 1.3 检查堆占用 2. 代码检查 3. 解决方式 1. Fu ...

  7. Nginx 系列 | (转)Nginx 上传文件:client_max_body_size 、client_body_buffer_size

    原文:http://php-note.com/article/detail/488 client_max_body_size client_max_body_size 默认 1M,表示 客户端请求服务 ...

  8. pytest-xdist分布式

    使用pytest框架运行每条case的时候,都是上一条运行结束才会运行下一条,要是有成千上百条case 且每条运行2s那就是2*总条数,会浪费大量的时间和人力.为了节约时间和人力成本,pytest提供 ...

  9. 如何安装typescript-如何运行typescript

    如何安装 typescript npm install typescript -g 安装 ts 之前需要安装 node 哈 查看 ts 的版本 tsc -V 我的是 3.6.3 的版本 typescr ...

  10. 手撕Vuex-实现共享数据

    经过上一篇章介绍,完成了添加全局 $store,接下来就是实现共享数据的功能. 在 Vuex 中,共享数据是通过 state 来实现的,所以我们需要在 Nuex.js 文件中实现 state 的功能. ...