如何用AVFoundation将视频生成Live Photo。
Live Photo其实就是一个mov文件和一张jpg文件,在下面保存Live Photo代码中就可以看出。
1 | [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ |
是不是任意的mov文件和jpg就可以生成Live Photo呢?当然是不行的,因为系统在元数据上进行了标记。
Begin
1 | NSString *_assetIdentifier; |
_assetIdentifier
是用[[NSUUID UUID] UUIDString]
生成的唯一标识符。
Image
首先我们取视频中某一时间点来生成一个jpg。
1 | AVAssetImageGenerator* generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset]; |
也可以用其他图片,但是需要设置jpg的元数据,给这个jpg一个标记。
Video
视频上有两个点要设置,一个唯一标识符_assetIdentifier
,一个是关键帧
Transcoding
如果视频不是mov文件而是mp4的,就需要转码了,转码有两个方式,一个是用AVAssetReaderTrackOutput
和AVAssetWriterInput
,一个是用AVAssetExportSession
AVAssetReader && AVAssetWriter
首先我们先得到视频的videoTrack和audioTrack(可能没有)
1 | AVAssetTrack *videoTrack = [[_asset tracksWithMediaType:AVMediaTypeVideo] firstObject]; |
Progress
1 | /// Accurate to microsecond. |
得到videoTrack和audioTrack的持续时间,精确到毫秒。
AVAssetReader
1 | AVAssetReaderTrackOutput *videoReaderTrackOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack |
在这里我们读取的格式为
kCVPixelFormatType_32BGRA
AVAssetWriter
1 | AVAssetWriterInput *videoWriteInput = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeVideo |
设置输出的编码格式为
AVVideoCodecH264
并设置视频的宽高。
Audio
1 | AVAssetWriterInput *audioWriteInput = nil; |
在这里对音频做特殊的处理。
Metadata
1 | NSDictionary *spec = @{(NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: [NSString stringWithFormat:@"%@/%@", AVMetadataKeySpaceQuickTimeMetadata, kKeyStillImageTime], |
Writer Metadata
1 | AVMutableMetadataItem *assetIdentifierMetadataItem = [[AVMutableMetadataItem alloc] init]; |
添加唯一标识符。
Time Metadata
1 | AVMutableMetadataItem *stillImageTimeMetadataItem = [[AVMutableMetadataItem alloc] init]; |
添加关键帧。
AVAssetExportSession
好像无法直接使用AVAssetExportSession来生成相应的mov文件,主要是由于无法在时间线上添加元数据,导致系统无法识别哪个是关键帧。
Code
1 |
|
⚠️ 提供的🌰是默认将第一帧作为关键帧。
写入的方法是先写入Video,再写入Audio。在Apple提供的例子中使用的是dispatch_group来同时写入Video和Audio,但是个人理解却没有这样的方式好用。