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. 强大的PDF格式转换器--迅捷PDF转换器

    1.功能十分强大,具体如图所示,实现了多种文件格式的转换,PDF合并和PDF密码解除也帮了我很大的忙(注意这里的密码解除是强行解除,不需要你知道密码) 2.资源分享 https://www.aliyu ...

  2. 2023浙江省大学生信息安全竞赛技能赛初赛 部分wp

    CRYPTO 小小数学家 1.题目信息 查看代码 19+49=? 96-31=? 86-3=? 20+47=? 29+55=? 35+35=? 81+42=? 73-16=? 52+48=? 0+56 ...

  3. Nginx长连接学习之二

    Nginx长连接学习之二 背景 距离最开始学习Nginx的长连接已经一年半; 距离最开始学习Linux的TCP内核参数也已经过去了一年. 最近产品再次出现了TCP链接相关的问题. 因为一开始不知道部署 ...

  4. [转帖]Oracle 创建和查看DBLink 的方法

    https://www.cnblogs.com/zhouzangood/articles/4612441.html 1.如果需要创建全局 DBLink,则需要先确定用户有创建 dblink 的权限: ...

  5. [转帖]使用Transformers推理

    https://github.com/ymcui/Chinese-LLaMA-Alpaca/wiki/%E4%BD%BF%E7%94%A8Transformers%E6%8E%A8%E7%90%86 ...

  6. 文盘Rust -- 安全连接 TiDB/Mysql

    作者:京东科技 贾世闻 最近在折腾rust与数据库集成,为了偷懒,选了Tidb Cloud Serverless Tier 作为数据源.Tidb 无疑是近五年来最优秀的国产开源分布式数据库,Tidb ...

  7. ClickHouse(14)ClickHouse合并树MergeTree家族表引擎之VersionedCollapsingMergeTree详细解析

    目录 建表语法 使用场景 合并算法 使用例子. 资料分享 参考文章 VersionedCollapsingMergeTree引擎继承自MergeTree并将折叠行的逻辑添加到合并数据部分的算法中.Ve ...

  8. ABP vNext系列文章10---分布式事务集成netcore.Cap

    最近项目中要用到分布式事务功能,调研了DTM和Cap,最终确定用Cap来实现,Cap支持最终一致性,项目中采用MQ作为消息中间件,数据库用的mysql,集成步骤如下: 1.在需要发布消息的服务中引入如 ...

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

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

  10. 分布式ID介绍&实现方案总结

    分布式 ID 介绍 什么是 ID? 日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单 ID 对应且仅对应一个订单. ...