CoreAnimation, AVFoundation i możliwość eksportu wideo

Szukam poprawnego sposobu na wyeksportowanie sekwencji zdjęć do wideo quicktime.

Wiem, że Fundacja AV ma możliwość łączenia lub rekombinowania filmów, a także dodawania ścieżki audio, tworząc pojedynczy zasób wideo.

Teraz ... mój cel jest trochę inny. Chciałbym stworzyć film od podstaw. Mam zestaw UIImage i muszę renderować je wszystkie w jednym filmie. Przeczytałem całą dokumentację Apple o Fundacji AV i znalazłem Avvideocompositioncoreanimationklasą, która ma możliwość pobrania CoreAnimation i ponownego zakodowania go jako wideo. Sprawdziłem również projekt AVEditDemo dostarczony przez Apple, ale coś wydaje się nie działać na moim projekcie.

Oto moje kroki:

1) tworzę warstwę 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) Niż utworzyć instancję 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) eksportuję wideo do ścieżki dokumentu

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];
         }
     });
 }];

Na i z eksportu a uzyskać ten błąd:

Eksport Zakończony: Error Domain=AVFoundationErrorDomain Code = -11822" nie można otworzyć " UserInfo = 0x49a97c0 {nslocalizedfailurereason=ten format multimediów nie jest obsługiwany., NSLocalizedDescription = Cannot Open}

Znalazłem to w dokumentacji: AVErrorInvalidSourceMedia = -11822,

AVErrorInvalidSourceMedia Operacja nie mogła zostać zakończona, ponieważ niektóre nośniki źródłowe nie mogły być odczytane.

Jestem całkowicie pewien, że CoreAnimation zbudowany przeze mnie jest dobry, ponieważ renderowałem go w warstwę testową i prawidłowo widać postęp animacji.

Czy ktoś może mi pomóc zrozumieć, gdzie jest mój błąd?
Author: slugster, 2011-02-17

2 answers

Być może potrzebujesz fałszywego filmu, który zawiera całkowicie czarną ramkę, aby wypełnić warstwę wideo, a następnie dodać warstwę do manpiulate obrazów

 4
Author: Eric.Cheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-23 02:03:32

Znalazłem klasę AVVideoCompositionCoreAnimationTool, która ma zdolność do pobierania CoreAnimation i ponownego kodowania go jako wideo

Zrozumiałem, że to zamiast tego było w stanie tylko pobrać CoreAnimation i dodać go do istniejącego filmu. Właśnie sprawdziłem dokumenty i jedyne dostępne metody również wymagają warstwy wideo.

EDIT: tak. Grzebanie w dokumentach i filmach WWDC, myślę, że powinieneś używać AVAssetWriter zamiast tego i dodawać obrazy do pisarza. Coś w stylu:

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];
 4
Author: Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-04 14:25:23