使用AVFoundation实现预告片倒序
2015-12-28 15:55:12 | 来源:玩转帮会 | 投稿:佚名 | 编辑:小柯

原标题:使用AVFoundation实现预告片倒序

作者:黄凯

背景

最近在做一个预告片类的APP,在预告片的编辑模块有一个预告片倒序文件的需求,这个和倒序播放的需求不一样,要求的是生成新的倒序预告片文件

研究过程

一开始原本以为这个需求很简单,但是实现的时候遇到了各种麻烦,在最初,本以为可以直接使用AVMutableComposition对Track直接反转的操作就可以实现预告片的倒序了(看来我真是Too Naive了),然后发现AVFoundation没有提供这样的接口。后面通过各种Google、StackOverflow,还是让我找到了一些实现的思路,谢谢下面俩哥们的实现思路给了我极大的启发 https://github.com/mikaelhellqvist/ReverseClip https://github.com/whydna/ReverseAVAsset

先讲一下预告片倒序的实现原理: 预告片文件如果除去哪些杂七杂八的元数据,那剩下的就是一帧帧的预告片图片了(预告片帧的分类这里不展开讨论),简单的来讲,就是把预告片文件里的每一帧按照相反的方向去排列就可以让预告片倒着播放了。

大体的实现思路如下:

把一个预告片拆分成多个AVAssetTrack,这样做的原因是因为,使用AVAssetReader读取每一帧SampleBuffer的数据是需要把数据加载到内存里面去的,如果直接把整个预告片的SampleBuffer加载到内存,会造成闪退

拆分成多个AVAssetTrack之后,使用AVAssetReader从最后一个AVAssetTrack读取SampleBuffer,这样我们可以从后往前获取预告片的帧数据

获取数据之后通过AVAssetWriterInputPixelBufferAdaptor的- appendPixelBuffer:withPresentationTime:方法来把我们获取到的SampleBuffer倒序写入一个文件

问题

  1. 经过一番折腾,惊喜的发现Demo已经可以Run起来,并且可以输出倒序的预告片文件,但是发现最后的时间总是不对,会少了一截,因为加载AVAsset的时候并没有把准确的预告片长度信息加载进来,所以我们在加载AVAsset的时候需要调用loadValuesAsynchronouslyForKeys方法来获取准确的预告片信息。

  2. 但是对于我的需求却并未满足,因为我们在上面说到,我们获取的时候是一个原始的预告片文件,这个预告片文件没有经过任何的编辑,所以一切看起来都没啥问题,但是有时候我们需要对预告片进行一些编辑,比如合成,比如剪切,比如对预告片做一些Transform等等的一些编辑操作,水印,动画等等,但是这些操作只是生成了一个新的AVMutableComposition,并没有生成新的预告片文件,这个时候如果我们想要直接在经过编辑的文件来生成一个倒序的预告片怎么办?在网上找了很久资料,还是没有找到实现的办法,最后翻阅了官方文档之后看到了AVAssetReaderOutput有一个子类AVAssetReaderVideoCompositionOutput,这个子类有一个属性videoComposition,可以赋值一个AVVideoComposition指令容器,这样我们就可以通过这个属性来准确的加载被编辑过的预告片的编辑指令了。但是指令有一个timeRange属性,我们直接生成的一组AVAssetTrack和原来的AVVideoComposition并不匹配,这个时候我用到了一个Trick的方法来对应

解决办法

我在分割AVAsset的时候,在生成一个新的AVComposition的实例时使用insertTimeRange方法插入的时间并非是kCMTimeZero,而是每一个AVAssetTrack在原来的AVAsset对应的开始和结束位置,这样使用AVAssetReaderVideoCompositionOutput来配置videoComposition,Reader就可以准确的读取包含了编辑指令每一帧的SampleBuffer了,然后再按照上面的方法来倒序写入SampleBuffer即可

经验总结

  • appendPixelBuffer:withPresentationTime:方法不能从后往前写,如果你这样做,会写入失败

  • 兼顾了编辑指令的实现方法会对性能有一定的浪费,因为我们不在kCMTimeZero时间点生成的AVAssetTrack会在Reader读取的时候获取的都是黑帧,随着预告片的分割段数越多,预告片的时间越长,倒序生成的时间也就越长

  • 目前分割的段数是以每段预告片长度最长为1s来分割,如果来操作很长很大的预告片,可能需要耗费很长的时间

  • 分割预告片的时候目前没有对编辑过和没有编辑过的预告片作为区分,如果只针对原预告片倒序输出,可以把每个AVAssetTrack的开始时间设置为kCMTimeZero,这样性能会有很大的提升

tags:

上一篇  下一篇

相关:

美久广场舞 广场舞我不是高富帅教学

  广场舞的健身作用是非常多的,现在跳广场舞的人群是比较多的。今天让小编给大家带来

美久广场舞 广场舞我要去西藏教学预告片

  广场舞一般都是在下午这个时间段跳的,跳广场舞的好处是很多的,可以减掉身体的脂肪

源码推荐(12.21B):石工布局瀑布流,星星上滑动打分

石工布局瀑布流(上传者:wkcao)石工布局瀑布流,用UICollectionView实现滑动打分,通过在星星上面滑动,给予

如何简单地为测试切换AppDelegate

本文由CocoaChina译者小袋子翻译原文:How to Easily Switch Your App Delegate for Testing如何简单地为测

示例详解:UIScrollview与Autolayout的那点事

前言自从写了介绍Masonry那篇文章以后 就一直有人对UIScrollView的那个例子不是很理解UIView*container=[UI

源码推荐(12.28):一种navigation渐变色的实现方案,一句话实现无限轮播器

一种navigation渐变色的实现方案,与背景一体(上传者:lc00oo)navigationBar随背景图渐变,不遮挡上层视图。

刘荣广场舞 时尚广场舞大妹子分解教学

  广场舞的舞队是非常多的,今天让小编给大家带来刘荣广场舞,这首优美的广场舞歌曲《

惠汝广场舞 草原风广场舞新草原情歌

  广场舞是我们大家的舞蹈,广场舞的种类是非常多的。今天让小编给大家带来惠汝广场舞

广场舞教学 经典广场舞晚秋教学预告片

  广场舞是一种非常有活力的舞蹈,广场舞的发展是比较快的,让我们来学习今天的广场舞

广场舞歌曲 草原风广场舞亲亲草原教学

  广场舞是现在非常时尚的舞蹈,跳广场舞给我们带来了快乐和健康,让我们来学习今天的

站长推荐: