CoreAnimation, AVFoundation и возможность сделать экспорт видео - PullRequest
9 голосов
/ 17 февраля 2011

Я ищу правильный способ экспортировать мою последовательность изображений в видео быстрого доступа.

Я знаю, что у AV Foundation есть возможность объединять или рекомбинировать видео, а также добавлять звуковую дорожку, создавая один видео актив.

Теперь ... моя цель немного другая. Я бы создал видео с нуля. У меня есть набор UIImage, и мне нужно визуализировать их все в одном видео. Я прочитал всю документацию Apple об AV Foundation и обнаружил класс AVVideoCompositionCoreAnimationTool, который имеет возможность взять CoreAnimation и перекодировать его как видео. Я также проверил проект AVEditDemo, предоставленный Apple, но в моем проекте что-то не работает.

Вот мои шаги:

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 верна, потому что я рендерил ее в тестовый слой и мог правильно видеть прогресс анимации.

Кто-нибудь может помочь мне понять, где моя ошибка?

Ответы [ 2 ]

5 голосов
/ 23 марта 2012

возможно, вам нужен поддельный фильм, который содержит полностью черную рамку для заполнения видеослоя, а затем добавьте CALayer для манипуляции изображениями

4 голосов
/ 08 марта 2011

Я нашел класс AVVideoCompositionCoreAnimationTool, у которого есть возможность взять CoreAnimation и перекодировать его как видео

Насколько я понимаю, вместо этого можно было взять только 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];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...