Android将多个视频文件拼接为一个文件

正文
利用android的2个类MediaExtractor(抽取音/视频帧) + MediaMuxer
(将音视频重新写入一个多媒体文件,完成封装)。

合成文件为MP4。为啥是MP4? 因为android支持最好的就是这个格式。MediaMuxer的native实现者是MPEG4Writer。

合成mp4视频主要有三个步骤:

  1. 开始时,创建MediaMuxer,写入文件头部ftyp;
  2. 进行时,遍历文件,读取每一帧,实时写入新文件的数据块mdat,并在内存中存储trak表。到下一个文件时,pts offset增加;
  3. 所有文件都读取完,结束,索引信息trak表写入moov。关闭文件描述符。

话不多说,直接给github的demo代码:
https://github.com/xf420811/VideoComposerDemo

关于视频合成的一些问题

  1. 前后2个视频的video fps不一样,有关系吗?
    没有关系。底层decoder不会因为fps有变化,就不解码。做render的时候,是根据pts做显示,不会用fps。(fps一般用于pts没有,或者出错时,decoder根据fps重新计算pts,送给render。)

  2. 前后2个视频的video codec不一样,有关系吗?
    有关系。底层decoder会根据不同的codec建立真正的decoder实例,如AVCDecoder, HEVCDecoder,到解码完成前,这个无法实时切换。

  3. 前后2个视频的video 分辨率不一样,有关系吗?
    有关系。底层decoder解码时,会根据分辨率等参数,创建解码后的Output Buffer, 假设分辨率突然变大了,那buffer大小就不够,无法存储,会崩溃。

  4. Audio sample rate /channel number不一样有关系吗?
    有关系。因为这2个参数,在播放音频时,底层建立decoder,就需要设置这2个参数,如果解码到一半,突然变了,一声道变成2声道了,或者sample rate从44.1k变成32k了,那有些厂商如果不支持sample rate动态变化,就会出错,最终效果,很可能是播放时变成杂音。
    ————————————————
    版权声明:本文为CSDN博主「长江很多号」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/newchenxf/article/details/78524896

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴为您解答问题!对于您的问题,我可以给您提供一些基本的思路。 在 Android 开发中,for 循环是非常常见的控制流结构,但是如果不注意,很容易出现效率低下的情况。因此,以下是一些常用的优化方法: 1. 使用增强型 for 循环 增强型 for 循环是一种简化代码的语法,可以避免手动迭代数组或集合的麻烦。例如: ```java int[] array = {1, 2, 3, 4, 5}; for (int i : array) { Log.d(TAG, "i = " + i); } ``` 这种写法能够大大简化代码,同时避免了手动迭代数组的问题。 2. 避免在循环中创建对象 在循环中创建对象会导致频繁的内存分配和回收,从而导致性能降低。因此,如果可能的话,应该避免在循环中创建对象。例如: ```java StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append(i); } String result = sb.toString(); ``` 这个例子中,我们使用 StringBuilder 对象来拼接字符串,而不是在循环中创建多个 String 对象。 3. 避免在循环中进行 I/O 操作 I/O 操作是非常昂贵的,特别是在 Android 这样的移动设备上。因此,如果可能的话,应该避免在循环中进行 I/O 操作。例如: ```java File file = new File("path/to/file"); FileInputStream fis = new FileInputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { // do something with the data } fis.close(); ``` 这个例子中,我们使用 FileInputStream 读取文件,并在循环中处理数据。为了避免频繁的 I/O 操作,我们应该尽可能地一次性读取全部数据,然后在循环外部处理。 希望这些方法能够帮助您写出更高效的 for 循环。如果您还有其他问题,欢迎继续向我提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值