CoreAnimation,AVFoundation和制作视频导出的能力

问题描述:

我正在寻找将我的图片序列导出到Quicktime视频的正确方法。CoreAnimation,AVFoundation和制作视频导出的能力

我知道AV Foundation有能力合并或重组视频,也可以添加构建单个视频资产的音轨。

现在...我的目标有点不同。我会从头创建一个视频。我有一套UIImage,我需要将它们全部渲染到一个视频中。 我阅读了关于AV Foundation的所有Apple文档,并且我找到了AVVideoCompositionCoreAnimationTool类,它有能力采用CoreAnimation并将其重新编码为视频。我还检查了Apple提供的AVEditDemo项目,但似乎没有对我的项目起作用。

这里我的步骤:

1)我创建了CoreAnimation层

CALayer *animationLayer = [CALayer layer]; 
[animationLayer setFrame:CGRectMake(0, 0, 1024, 768)]; 

CALayer *backgroundLayer = [CALayer layer]; 
[backgroundLayer setFrame:animationLayer.frame]; 
[backgroundLayer setBackgroundColor:[UIColor blackColor].CGColor]; 

CALayer *anImageLayer = [CALayer layer]; 
[anImageLayer setFrame:animationLayer.frame]; 

CAKeyframeAnimation *changeImageAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; 
[changeImageAnimation setDelegate:self]; 
changeImageAnimation.duration = [[albumSettings transitionTime] floatValue] * [uiImagesArray count]; 
changeImageAnimation.repeatCount = 1; 
changeImageAnimation.values = [NSArray arrayWithArray:uiImagesArray]; 
changeImageAnimation.removedOnCompletion = YES; 
[anImageLayer addAnimation:changeImageAnimation forKey:nil]; 

[animationLayer addSublayer:anImageLayer]; 

2)比我实例化AVComposition

AVMutableComposition *composition = [AVMutableComposition composition]; 
composition.naturalSize = CGSizeMake(1024, 768); 

CALayer *wrapLayer = [CALayer layer]; 
wrapLayer.frame = CGRectMake(0, 0, 1024, 768); 
CALayer *videoLayer = [CALayer layer]; 
videoLayer.frame = CGRectMake(0, 0, 1024, 768); 
[wrapLayer addSublayer:animationLayer]; 
[wrapLayer addSublayer:videoLayer]; 

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 


AVMutableVideoCompositionInstruction *videoCompositionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
videoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMake([imagesFilePath count] * [[albumSettings transitionTime] intValue] * 25, 25)); 

AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstruction]; 
videoCompositionInstruction.layerInstructions = [NSArray arrayWithObject:layerInstruction]; 

videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:wrapLayer]; 
videoComposition.frameDuration = CMTimeMake(1, 25); // 25 fps 
videoComposition.renderSize = CGSizeMake(1024, 768); 
videoComposition.instructions = [NSArray arrayWithObject:videoCompositionInstruction]; 

3)我出口的视频文件的路径

AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetLowQuality]; 
session.videoComposition = videoComposition; 

NSString *filePath = nil; 
filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
filePath = [filePath stringByAppendingPathComponent:@"Output.mov"];  

session.outputURL = [NSURL fileURLWithPath:filePath]; 
session.outputFileType = AVFileTypeQuickTimeMovie; 

[session exportAsynchronouslyWithCompletionHandler:^ 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSLog(@"Export Finished: %@", session.error); 
     if (session.error) { 
      [[NSFileManager defaultManager] removeItemAtPath:filePath error:NULL]; 
     } 
    }); 
}]; 

在与出口的得到这个错误:

出口成品:错误域= AVFoundationErrorDomain代码= -11822“无法打开”的UserInfo = 0x49a97c0 {NSLocalizedFailureReason =不支持这种媒体格式,NSLocalizedDescription =无法打开}

我发现它的内部文件:AVErrorInvalidSourceMedia = -11822,

AVErrorInvalidSourceMedia 操作无法完成,因为一些媒体来源无法读取。

我完全相信我的CoreAnimation构建是正确的,因为我将它渲染到测试图层中,并且我可以正确地看到动画进度。

任何人都可以帮助我了解我的错误在哪里?

+0

尝试张贴,或提交假的电影与苹果的错误报告。他们可能会告诉你你做错了什么。 – 2011-12-02 00:51:34

也许你需要的是包含全黑帧,填补了视频层,然后添加一个的CALayer到manpiulate图像上的苹果开发者论坛

I found the AVVideoCompositionCoreAnimationTool class that have the ability to take a CoreAnimation and reencode it as a video

我的理解是,这只能够采取CoreAnimation并将其添加到现有的视频。我只是检查了文档,并且唯一可用的方法也需要视频图层。

编辑:是的。挖掘文档和WWDC视频,我认为您应该使用AVAssetWriter,并将图像添加到作者。喜欢的东西:

AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:somePath] fileType:AVFileTypeQuickTimeMovie error:&error]; 

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, [NSNumber numberWithInt:320], AVVideoWidthKey, [NSNumber numberWithInt:480], AVVideoHeightKey, nil]; 
AVAssetWriterInput* writerInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings] retain]; 

[videoWriter addInput:writerInput]; 

[videoWriter startWriting]; 
[videoWriter startSessionAtSourceTime:CMTimeMakeWithSeconds(0, 30)] 
[writerInput appendSampleBuffer:sampleBuffer]; 
[writerInput markAsFinished]; 
[videoWriter endSessionAtSourceTime:CMTimeMakeWithSeconds(60, 30)]; 
[videoWriter finishWriting]; 
+0

我认为你是对的。我会看更多这个。我试图存储一系列图像。 – Franky 2013-12-31 07:19:52

+0

在编写`UIImage`或`CGImageRef`的上下文中,'sampleBuffer`是什么?只是原始图像像素?用`CMSampleBufferCreateForImageBuffer`制作? – bcattle 2014-06-27 19:14:20