1️⃣、目标:把音视频流(使用各种通道传输过来的字节流)合成视频文件
2️⃣、工具:Android原生框架自带的MediaMuxer类
3️⃣、方案:

 private MediaMuxer mMuxer;

MediaMuxer初始化

mMuxer = new MediaMuxer(“需要保存的路径”,MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

MUXER_OUTPUT_MPEG_4//合成的视频文件格式

MediaMuxer添加音视频配置

private int mVideoTrackIndex, mAudioTrackIndex;

Video Track

MediaFormat videoMediaformat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);byte[] header_SPS_1080 = {0, 0, 0, 1, 103, 77, 0, 42, -99, -88, 30, 0, -119, -7, 102, -32, 32, 32, 32, 64};
byte[] header_PPS_1080 = {0, 0, 0, 1, 104, -18, 60, -128};byte[] header_SPS_720 = {0, 0, 0, 1, 103, 77, 0, 31, -99, -88, 20, 1, 110, -101, -128, -128, -128, -127};
byte[] header_PPS_720 = {0, 0, 0, 1, 104, -18, 60, -128};byte[] header_SPS_360 = {0, 0, 0, 1, 103, 77, 0, 30, -99, -88, 40, 11, -2, 89, -72, 8, 8, 8, 16};
byte[] header_PPS_360 = {0, 0, 0, 1, 104, -18, 60, -128};if (width == 640 && height == 360) {videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_360));videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_360));//H264格式的视频需要添加videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);//视频数据格式videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 640 * 360);//缓冲区最大值videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);//帧率
} else if (width == 1280 && height == 720) {videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_720));videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_720));videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1280 * 720);videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);
} else {videoMediaformat.setByteBuffer("csd-0", ByteBuffer.wrap(header_SPS_1080));videoMediaformat.setByteBuffer("csd-1", ByteBuffer.wrap(header_PPS_1080));videoMediaformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);videoMediaformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);videoMediaformat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 20);
}mVideoTrackIndex = mMuxer .addTrack(videoMediaformat);

Audio Track

 MediaFormat audioFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 8000, 1);//音频格式,采样率,通道数audioFormat.setInteger(MediaFormat.KEY_IS_ADTS, 1);//AAC音频需要添加byte[] bytes = new byte[]{(byte) 0x11, (byte) 0x90};ByteBuffer audiobuffer = ByteBuffer.wrap(bytes);audioFormat.setByteBuffer("csd-0", audiobuffer);audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, 96000);//比特率audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 100 * 1024);//作用于inputBuffer的大小mAudioTrackIndex = mMuxer .addTrack(audioFormat);

以上初始化流程完成后

mMuxer.start();//开启合成器

MediaMuxer写数据

private MediaCodec.BufferInfo       bufferInfo     = null;
private MediaCodec.BufferInfo       audioBufferInfo = null;

视频流

bufferInfo.offset = 0;
bufferInfo.size = /*naluIndex*/视频流数据的大小;if (/*(naluBuffer[4] & 0x1f) == 5*/判断I帧) {bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;//I帧} else if (/*(naluBuffer[4] & 0x1f) == 7 || (naluBuffer[4] & 0x1f) == 8 ||(frameBuffer[4] & 0x1f) == 6*/判断预测帧) {bufferInfo.flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;//B,P帧} else {bufferInfo.flags = 0;//SEI}
bufferInfo.presentationTimeUs = getPTSUs();
mMuxer.writeSampleData(mVideoTrackIndex , /*outputBuffer*/视频流, bufferInfo);

bufferInfo在合成时非常重要,这要是出现异常,则合成的视频也会存在异常

private long prevOutputPTSUs = 0;
/***获取下一个编码表示时间*/protected long getPTSUs() {long result = System.nanoTime() / 1000L;if (result < prevOutputPTSUs)result = (prevOutputPTSUs - result) + result;return result;}

音频流

audioBufferInfo.offset = 0;
audioBufferInfo.size = /*nReadSize*/音频数据流大小;
audioBufferInfo.flags = 0;
audioBufferInfo.presentationTimeUs = getPTSUs();
mMuxer.writeSampleData(mVideoTrackIndex , /*outputBuffer*/音频流, bufferInfo);

stop和release

if (mMuxer != null) {try {mMuxer.stop();mMuxer.release();} catch (IllegalStateException ex) {ex.printStackTrace();}
}

4️⃣结束语:
1.没有音频数据的情况下,不要addAudioTrack。

Android音视频合成工具-MediaMuxer相关推荐

  1. Android音视频之MediaCodec和MediaMuxer使用

    一.MediaCodec介绍 Android中可以使用MediaCodec来访问底层的媒体编解码器,可以对媒体进行编/解码. MediaCodec可以处理的数据有以下三种类型:压缩数据.原始音频数据. ...

  2. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  3. Android 音视频开发入门指南

    最近收到很多网友通过邮件或者留言说想学习音视频开发,该如何入门,我今天专门写篇文章统一回复下吧. 音视频这块,目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的,希望我后面能挤出时间整 ...

  4. android硬编码封装mp4,【Android 音视频开发打怪升级:音视频硬解码篇】四、音视频解封和封装:生成一个MP4...

    [声 明] 首先,这一系列文章均基于自己的理解和实践,可能有不对的地方,欢迎大家指正. 其次,这是一个入门系列,涉及的知识也仅限于够用,深入的知识网上也有许许多多的博文供大家学习了. 最后,写文章过程 ...

  5. 谈谈对Android音视频开发的探究

    ​ 在日常生活中,视频类应用占据了我们越来越多的时间,各大公司也纷纷杀入这个战场,不管是抖音.快手等短视频类型,虎牙.斗鱼等直播类型,腾讯视频.爱奇艺.优酷等长视频类型,还是Vue.美拍等视频编辑美颜 ...

  6. Android 音视频难学?音视频(流媒体)开发学习也有套路

    我们都知道音视频流媒体开发这块的知识比较纷繁复杂,对新手很不友好,自学难度大,想要们既需要比较扎实的C/C++基础,又需要有很多的工程/项目经验,今天就从音视频开发/开源框架/就业方向分析,为广大开发 ...

  7. Android 音视频采集与软编码总结

    请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/75807435(本文已在 "任玉刚" 微信公众号发布 ...

  8. Android 音视频开发(三) -- Camera2 实现预览、拍照功能

    音视频 系列文章 Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍 ...

  9. 推荐几个堪称教科书级别的 Android 音视频入门项目

    公众号回复:OpenGL,领取学习资源大礼包 在 直播 中有提到几个不错的开源项目,这里再重点推荐一下: 目前,市面上关于音视频学习的相关书籍并不多,而且即使看了书籍学了理论,最终还是要回归到代码上来 ...

最新文章

  1. TVM代码生成codegen
  2. 使用 EclEmma 来显示代码覆盖率
  3. 基站的结构、种类、发展介绍
  4. Odoo10 启动选项
  5. Leetcode 6.Z 字形变换 (每日一题 20210630)
  6. fetch + async await 使用原生JS发送网络请求
  7. 1001: [BeiJing2006]狼抓兔子
  8. 设计模式---读书笔记
  9. 【学习笔记】数据链路层——信道划分访问控制(FDM、TDM、STDM、WDM、CDM CDMA)
  10. python数据挖掘分析案例python_Python 数据挖掘实例 决策树分析
  11. thinkpad卡在logo界面_四大系列 一个品牌,超好用的商务伴侣Thinkpad
  12. 判断图像局部过暗_数字图像处理(第五章)
  13. LayaAir graphics 矢量绘图之直线、折线、曲线
  14. windows下编译librtmp库
  15. Java 定时任务@Scheduled使用
  16. 《构建之法》第1.2.3章读后感 以及《硅谷传奇》观后感
  17. 数模笔记(四):插值与拟合1.0
  18. 关于GX WORKS2中M8002、M8012、M8013无法使用的问题
  19. 《重构--改善既有代码的设计》--代码的坏味道(3)
  20. 如何从零开始写一个操作系统?

热门文章

  1. npm安装、切换淘宝镜像
  2. 测试需求平台3- 登录打通和产品列表功能实现
  3. 小学计算机社团总结报告,小学社团活动总结范文
  4. 英雄连门最新服务器开启时间,新版客户端现已开启公测!
  5. Android版中文分词器:原理、接入和启动优化
  6. android开发 获取相册名称_Android获取手机上各个相册名称和相片的方法
  7. 企业支付宝,登录限制,大额三年,不可用余额,支付关闭,
  8. 在windows2000中提示您无法关闭计算机!
  9. [ElementUI] 修改默认语言为英文
  10. android manager provider模式,安卓情景模式开发(一)-控制GPS/WIFI/蓝牙/飞行模式...