【音视频】剪辑 SDK(裁剪/旋转/变速)

【音视频】剪辑 SDK(裁剪/旋转/变速)

💡 原文中文,约13900字,阅读约需33分钟。
📝

内容提要

本文介绍移动端视频剪辑SDK的开发,聚焦裁剪、旋转、变速三大核心能力。通过时间轴模型实现帧级精准操作,iOS端用AVAssetReader/Writer支持旋转裁剪的passthrough快路径,Android端用MediaExtractor/Muxer处理变速重编码。强调剪辑是留存关键,性能上能不重编码就不重编码,并分享踩坑记录与性能对比。

🔎

延伸解读

剪辑能力是留存关键

文章指出,很多团队把精力放在拍摄画质上,却忽略了剪辑才是用户二次传播的关键。用户平均会剪掉30%的时长,90%的用户需要旋转矫正,剪辑做不好用户会直接转向剪映等竞品。因此,剪辑SDK不仅是功能,更是留存引擎,值得产品团队重视。

快路径与慢路径的架构分离

文章强调性能优化的核心是能不重编码就不重编码。旋转和裁剪可以通过passthrough快路径实现,耗时仅约2秒;而变速因改变时间戳必须重编码,耗时可达18秒。因此,架构上应将快路径(旋转/裁剪)与慢路径(变速/滤镜)分离,以提升导出效率和用户体验。

时间轴模型是剪辑引擎的灵魂

文章提出剪辑不是逐帧操作,而是对时间轴的声明式描述。通过时间轴模型,将剪辑操作抽象为数据,预览和导出共用同一映射公式,确保所见即所得。这种设计不仅双端一致,还简化了复杂剪辑逻辑的实现,是剪辑SDK的核心抽象。

帧级精准预览的代价与权衡

文章指出帧级精准预览需要设置requestedTimeToleranceBefore/After为零,这会导致每次seek都解码到目标帧,速度慢但准确。为平衡性能,建议预览缩略图使用大容差(快),主预览窗口使用小容差(准),分开配置两套容差,以满足不同场景的需求。

Q&A

移动端视频剪辑SDK的核心能力有哪些?为什么剪辑能力对产品很重要?

核心能力包括裁剪、旋转和变速。剪辑能力是用户二次传播的关键,因为用户平均会剪掉30%的时长,90%的用户需要旋转矫正横屏视频,变速用于卡点视频等。如果剪辑能力做不好,用户会转向剪映/CapCut等工具。

时间轴模型中,变速后时间轴时间与源视频时间如何映射?

映射公式为:sourceTime = sourceStart + (timelineTime - clipStart) × speed。其中sourceTime是源视频时间,sourceStart是片段在源视频中的起始时间,timelineTime是时间轴上的时间,clipStart是片段在时间轴上的起始时间,speed是播放速度。

iOS端实现旋转和裁剪时,如何做到不重编码(passthrough)?

使用AVAssetReader和AVAssetWriter,设置outputSettings为nil以直接传递压缩数据,旋转通过设置AVAssetWriterInput的transform属性实现,裁剪通过设置reader的timeRange实现。这样避免了像素重编码,速度快。

为什么变速必须重编码?Android端变速的核心步骤是什么?

变速改变了时间戳,无法直接传递压缩数据,因此必须重编码。Android端使用MediaExtractor读取数据,通过修改输出PTS(时间戳)实现变速,核心步骤包括:选择轨道、设置源时间范围、计算输出PTS(源偏移除以速度)、写入MediaMuxer。

帧级精准预览的实现要点是什么?如何平衡精度和性能?

实现要点是使用AVAssetImageGenerator并设置requestedTimeToleranceBefore和requestedTimeToleranceAfter为.zero,以获得精确帧。但这样每次seek都会解码到目标帧,速度慢。为平衡性能,预览缩略图可以使用较大的tolerance,主预览窗口使用较小的tolerance,分开配置。

在剪辑SDK开发中,有哪些常见的坑?如何解决?

常见坑包括:1) 导出视频没声音,因为audioOutput为nil时未添加音频输入,解决方法是判断audioTrack是否存在并同步添加;2) 旋转后画面被裁剪,因为transform旋转后尺寸变化但writer未更新,解决方法是旋转90/270度时交换宽高;3) 变速后拖进度卡顿,因为I帧变稀疏,解决方法是使用SEEK_TO_CLOSEST_SYNC或重编码;4) 帧级预览内存暴涨,因为未取消旧任务,解决方法是维护当前task引用并取消旧的;5) 裁剪边界花屏,因为起点非关键帧,解决方法是向前对齐到最近I帧;6) 双端时长不一致,因为时间精度不同,解决方法是统一时间基准为微秒。

剪辑SDK的性能对比结果如何?为什么说能不重编码就不重编码?

性能对比显示:旋转90度使用transform passthrough耗时2.1秒,裁剪50%使用timeRange passthrough耗时1.8秒,变速2x使用MediaExtractor+Muxer耗时3.5秒,而旋转+裁剪+变速全链路重编码耗时18秒。因此,旋转和裁剪可以走passthrough快路径,只有变速和滤镜需要重编码,所以能不重编码就不重编码,以提升性能。

🏷️

标签

➡️

继续阅读