前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于提升VideoEditor导出视频速度的一些建议

关于提升VideoEditor导出视频速度的一些建议

作者头像
马上就说
发布2023-03-05 14:46:31
5920
发布2023-03-05 14:46:31
举报
文章被收录于专栏:码上就说

接上篇我们继续聊一下VideoEditor中视频导出,这次我们谈谈【如何优化视频导出的速度】,视频的导出速度算是VideoEditor的一个非常重要的衡量指标,如何导出速度太慢了,那么VideoEditor肯定是流失相当一部分用户的。本文关于视频导出速度的优化都是经过实践证明过的,非常具有参考意义。

要想提升导出速度,毫无疑问肯定要使用硬解码和硬编码,毕竟GPU处理的速度比CPU不是快一点点,但是软解码和软编码也是需要支持的,你需要考虑特殊的情况,Android平台上手机五花八门,你不得不兼容所有可能的情况。

上一篇文章比较清晰地介绍了视频导出的基本流程:带你梳理VideoEditor视频导出流程,视频导出经过了解码 ——> 声音帧和视频帧处理 ——> 编码 的过程,很简单就能看出可能耗时的点。就一个视频帧的处理过程而言,它是串行的,就是必须要将视频Packet解码,才能处理这个视频帧,处理完成之后,才能对它进行编码。(这儿可以忽略解封的时间,解封装的耗时比较少,所以不需要过多的考虑)。

解码和编码的过程可以看成是互为逆过程,有两种选择,硬解码/硬编码或者软解码/软编码,硬解码/硬编码底层是采用GPU处理的,软解码/软编码是采用CPU计算的,所以硬解码/硬编码效率更高,采用哪种方式,要结合很多种情况:

  • 是否支持特定格式的硬解码、硬编码
  • 当前的MediaCodec实例是否超过特定的值

我们在上一篇文章也表示了,视频宽高、码率、帧率、格式是导出的必备参数,这些参数也可以用来确定内置的MediaCodec是否支持?下面判断是否支持特定格式的硬编码和硬解码。

代码语言:javascript
复制
public static boolean isMediaCodecEncodeSupported(String mimeType, int videoWidth, int videoHeight) {
    MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
    final MediaCodecInfo[] infoList = codecList.getCodecInfos();
    for (int index = 0; index < infoList.length; index++) {
        MediaCodecInfo codecInfo = infoList[index];
        if (!codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (String type : types) {
            if (!mimeType.equalsIgnoreCase(type)) {
                continue;
            }
            MediaCodecInfo.CodecCapabilities codecCapabilities = codecInfo.getCapabilitiesForType(type);
            MediaCodecInfo.VideoCapabilities videoCapabilities = codecCapabilities.getVideoCapabilities();
            if (videoCapabilities != null) {
                return videoCapabilities.isSizeSupported(videoWidth, videoHeight);
            }
        }
    }
    return false;
}
代码语言:javascript
复制
public static boolean isMediaCodecDecodeSupported(String mimeType, int videoWidth, int videoHeight) {
    MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
    final MediaCodecInfo[] infoList = codecList.getCodecInfos();
    for (int index = 0; index < infoList.length; index++) {
        MediaCodecInfo codecInfo = infoList[index];
        if (codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (String type : types) {
            if (!mimeType.equalsIgnoreCase(type)) {
                continue;
            }
            MediaCodecInfo.CodecCapabilities codecCapabilities = codecInfo.getCapabilitiesForType(type);
            MediaCodecInfo.VideoCapabilities videoCapabilities = codecCapabilities.getVideoCapabilities();
            if (videoCapabilities != null) {
                return videoCapabilities.isSizeSupported(videoWidth, videoHeight);
            }
        }
    }
    return false;
}

送入MediaCodec内部进行解码和编码,时长就不是我们能控制的,这部分时间不可优化。所以只要保证解码和编码使用的是MediaCodec,那过程1和过程3没有可以优化的空间。

过程2是处理Frame的过程,一般采用OpenGL,这个过程我们一般有三个原则:

  • 尽量采用FBO/EBO/ABO方式处理texture
  • 纹理如果过大要进行压缩
  • 严禁采用glFinish()

上面谈的一帧视频的处理过程,完整的视频有若干帧,例如一个14s、25fps的视频,共有350帧,那就要经历350个上面的过程。加入1帧处理需要100ms,那么总共需要35000ms才能导出这个视频。这个视频就比较长了。

既然一帧视频的处理过程是比较独立的,那可不可以将350帧分为多段,例如分为两段,分别是175帧,导出两个7s的视频,然后将这两个视频合成一个新的视频。

这就是本文要讨论的并行导出,就是将一个完整的视频分为两段或者多段,然后分别处理,最后将各小段视频合成一个完整的视频。例如导出一个14s的视频需要35000ms,拆分成两个7s的视频,就可以大大缩短导出的时间了。那是不是切分越多越好?

首先我们要明确导出视频是需要消耗资源的,这个资源就是MediaCodec,最终是送入到GPU中处理,一个手机中的MediaCodec实例是有限的,正常情况下,一个手机可以提供的MediaCodec实例最多有16个,如果当前使用的MediaCodec实例超过16个,那么手机将无法正常工作。MediaCodec资源是手机中的所有App共同持有。所以并行分段的个数不是越多越好。

  • 只有一段,需要两个MediaCodec(一个用来解码视频,一个用来编码视频),注意:音频的解码和编码可以不要用MediaCodec,毕竟音频的耗时少多了,不是瓶颈。
  • 分成两段,需要四个MediaCodec
  • 分成三段,需要六个MediaCodec
  • 分成四段,需要八个MediaCodec

简单分享一下结论吧,两段并行速度提升50% ~ 70%,内存增加20%, 三段并行速度提升60% ~ 90%,内存增加80%;并行超过三段的话就无法明显提升速度了。我比较建议并行两段,在一些性能很好的机型上并行三段。

并行转码有什么注意的点,大家使用的时候要着重注意下面的问题:

  • 精确分段,seek到一个中间点,多段视频需要严格按照这个时间点。
  • 转场特效相关的时间点需要特殊处理
  • 分段转码之后需要将多段视频合成一个新的视频

如果你在实践过程中遇到什么问题,欢迎来咨询讨论。聊完了【视频的导出速度】,接下来我们将要涉及【视频的清晰度】,这也是非常重要的一个章节,除了基本的编码优化,有没有一些AI的方式能提升视频的清晰度呢?欢迎大家来脑暴,可以将你的想法私信发给我,我们一起进步。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 音视频平凡之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
GPU 云服务器
GPU 云服务器(Cloud GPU Service,GPU)是提供 GPU 算力的弹性计算服务,具有超强的并行计算能力,作为 IaaS 层的尖兵利器,服务于生成式AI,自动驾驶,深度学习训练、科学计算、图形图像处理、视频编解码等场景。腾讯云随时提供触手可得的算力,有效缓解您的计算压力,提升业务效率与竞争力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档