Android提供了一个MediaExtractor类,可以用来分离容器中的视频track和音频track,下面的例子展示了使用MediaExtractor和MediaMuxer来实现视频的换音:

  1. private void muxingAudioAndVideo() throws IOException {
  2. MediaMuxer mMediaMuxer = new MediaMuxer(mOutputVideoPath,
  3. MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
  4.  
  5. // 视频的MediaExtractor
  6. MediaExtractor mVideoExtractor = new MediaExtractor();
  7. mVideoExtractor.setDataSource(mVideoPath);
  8. int videoTrackIndex = -1;
  9. for (int i = 0; i < mVideoExtractor.getTrackCount(); i++) {
  10. MediaFormat format = mVideoExtractor.getTrackFormat(i);
  11. if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
  12. mVideoExtractor.selectTrack(i);
  13. videoTrackIndex = mMediaMuxer.addTrack(format);
  14. break;
  15. }
  16. }
  17.  
  18. // 音频的MediaExtractor
  19. MediaExtractor mAudioExtractor = new MediaExtractor();
  20. mAudioExtractor.setDataSource(mAudioPath);
  21. int audioTrackIndex = -1;
  22. for (int i = 0; i < mAudioExtractor.getTrackCount(); i++) {
  23. MediaFormat format = mAudioExtractor.getTrackFormat(i);
  24. if (format.getString(MediaFormat.KEY_MIME).startsWith("audio/")) {
  25. mAudioExtractor.selectTrack(i);
  26. audioTrackIndex = mMediaMuxer.addTrack(format);
  27. }
  28. }
  29.  
  30. // 添加完所有轨道后start
  31. mMediaMuxer.start();
  32.  
  33. // 封装视频track
  34. if (-1 != videoTrackIndex) {
  35. MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
  36. info.presentationTimeUs = 0;
  37. ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
  38. while (true) {
  39. int sampleSize = mVideoExtractor.readSampleData(buffer, 0);
  40. if (sampleSize < 0) {
  41. break;
  42. }
  43.  
  44. info.offset = 0;
  45. info.size = sampleSize;
  46. info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
  47. info.presentationTimeUs = mVideoExtractor.getSampleTime();
  48. mMediaMuxer.writeSampleData(videoTrackIndex, buffer, info);
  49.  
  50. mVideoExtractor.advance();
  51. }
  52. }
  53.  
  54. // 封装音频track
  55. if (-1 != audioTrackIndex) {
  56. MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
  57. info.presentationTimeUs = 0;
  58. ByteBuffer buffer = ByteBuffer.allocate(100 * 1024);
  59. while (true) {
  60. int sampleSize = mAudioExtractor.readSampleData(buffer, 0);
  61. if (sampleSize < 0) {
  62. break;
  63. }
  64.  
  65. info.offset = 0;
  66. info.size = sampleSize;
  67. info.flags = MediaCodec.BUFFER_FLAG_SYNC_FRAME;
  68. info.presentationTimeUs = mAudioExtractor.getSampleTime();
  69. mMediaMuxer.writeSampleData(audioTrackIndex, buffer, info);
  70.  
  71. mAudioExtractor.advance();
  72. }
  73. }
  74.  
  75. // 释放MediaExtractor
  76. mVideoExtractor.release();
  77. mAudioExtractor.release();
  78.  
  79. // 释放MediaMuxer
  80. mMediaMuxer.stop();
  81. mMediaMuxer.release();
  82. }

MediaExtractor的接口比较简单,首先通过setDataSource()设置数据源,数据源可以是本地文件地址,也可以是网络地址:

  1. MediaExtractor mVideoExtractor = new MediaExtractor();
  2. mVideoExtractor.setDataSource(mVideoPath);

然后可以通过getTrackFormat(int index)来获取各个track的MediaFormat,通过MediaFormat来获取track的详细信息,如:MimeType、分辨率、采样频率、帧率等等:

  1. for (int i = 0; i < mVideoExtractor.getTrackCount(); i++) {
  2. MediaFormat format = mVideoExtractor.getTrackFormat(i);
  3. }

获取到track的详细信息后,通过selectTrack(int index)选择指定的通道:

  1. if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
  2. mVideoExtractor.selectTrack(i);
  3. break;
  4. }

指定通道之后就可以从MediaExtractor中读取数据了:

  1. while (true) {
  2. int sampleSize = mVideoExtractor.readSampleData(buffer, 0);
  3. if (sampleSize < 0) {
  4. break;
  5. }
  6. // do something
  7.  
  8. mVideoExtractor.advance(); // 移动到下一帧
  9. }
在读取结束之后,记得释放资源:
  1. mVideoExtractor.release();

Android音视频处理之基于MediaCodec合并音视频的更多相关文章

  1. Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析

    场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...

  2. 10分钟快速上车短视频风口:基于uniapp框架创建自己的仿抖音短视APP

    在今年也就是第48次发布的<中国互联网络发展状况统计报告>有这样一个数据,21年的上半年以来,我国我国网民规模达10.11亿,其中短视频用户达8.88亿.碎片化的生活场景下,短视频成为人们 ...

  3. iOS直播-播放基于RTMP协议的视频

    iOS直播-播放基于RTMP协议的视频 流媒体协议介绍 1. 伪流媒体: 渐进式下载 : 边下边存, 文件会保存 使用http协议,也能够实现视频播放, 也能快进快退等, 体验上跟流媒体很像. 优酷, ...

  4. 基于语音识别、音文同步、图像OCR的字幕解决方案HtwMedia介绍

    背景介绍 俗话说,“好记性不如乱笔头”,这充分说明了文字归档的重要性.如今随着微信.抖音等移动端app的使用越来越广,人们生产音.视频内容也越来越便捷.而相比语音和视频而言,文字具有易存档.易检索.易 ...

  5. PyQt+moviepy音视频剪辑实战2:一个剪裁视频文件精华内容留存工具的实现

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.引言 ...

  6. android的四层体系结构,基于mvc三层结构浅析

    从多方面理解Android体系结构 1.以分层的方式来看Android 安卓体系结构分为四层. 首先看一下官方关于Android体系结构的图: 1).Linux Kernel:负责硬件的驱动程序.网络 ...

  7. 基于RTP的H264视频数据打包解包类

    from:http://blog.csdn.net/dengzikun/article/details/5807694 最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打 ...

  8. javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG、javaCV-openCV)

    javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...

  9. Android开发学习之路--基于vitamio的视频播放器(二)

      终于把该忙的事情都忙得差不多了,接下来又可以开始good good study,day day up了.在Android开发学习之路–基于vitamio的视频播放器(一)中,主要讲了播放器的界面的 ...

随机推荐

  1. oracle常用密令大全

    1.create user username identified by password;//建用户名和密码oracle ,oracle 2.grant connect,resource,dba t ...

  2. js运用sort对json 数组进行排序

    Array.sort()方法是用来对数组项进行排序的 ,默认情况下是进行升序排列.sort() 方法可以接受一个 方法为参数. sort()排序时每次比较两个数组项都回执行这个参数,并把两个比较的数组 ...

  3. Mac Go 环境变量配置

    GOPATH 是工作目录,就是你打代码,代码的存放目录 GOROOT 是Go的安装目录,我下载的是免安装版的 现在的Go环境变量就是设置成这个样子, 终于Bee不会报错了!!!

  4. ImportError: dynamic module does not define init function (initcaffe)

    https://github.com/BVLC/caffe/issues/2770 $ python2 -c "import caffe" Traceback (most rece ...

  5. slf4j NoSuchMethodError 错误 ---- 版本冲突

    java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/Stri ...

  6. 实验吧Web-中-登陆一下好吗??

    题目上说:不要怀疑,我已经过滤了一切,还再逼你注入,哈哈哈哈哈! 可以试试,只要是输入的关键字都被过滤了,双写也被过滤掉了. 用万能密码发现,or被过滤掉了. 这里用到的是admin为:'=',密码为 ...

  7. [XSS防御]HttpOnly之四两拨千斤

    今天看了<白帽子讲web安全>一书,顺便记录一下,HttpOnly的设置 httponly的设置值为 TRUE 时,使得Javascript无法获取到该值,有效地防御了XSS打管理员的 c ...

  8. 使用NtQueryInformationFile函数获得不到完整路径

    #include <windows.h> #include <iostream> using namespace std; typedef struct _OBJECT_NAM ...

  9. 恒生UFX交易接口基本介绍

    https://zhidao.baidu.com/question/203296047903136445.html 1.恒生UFT和UFX有什么区别? UFT是一个极速交易系统,UFX是一个统一接入系 ...

  10. Python的安装部署

    Python的安装部署 参考:https://www.runoob.com/w3cnote/pycharm-windows-install.html 参考:https://jingyan.baidu. ...