2014-02-13 41 views
3

我試圖加載視頻,在其上添加一個動畫,然後導出它, 但動畫從未開始在導出的視頻中播放。 它只是顯示圖像「dogge_icon.png」。AV基金會動畫永遠不會開始播放

我試過不同類型的動畫,不知道我做錯了什麼。 任何幫助將不勝感激。

代碼:

-(void) createCompositionWithPicture { 
    AVMutableComposition* composition = [AVMutableComposition composition]; 

    NSString *videoPath = [[NSBundle mainBundle] pathForResource:@"Movie" ofType:@"m4v"]; 

    NSLog(@"Path: %@", videoPath); 
    NSURL *videoURL = [[NSURL alloc] initFileURLWithPath:videoPath]; 
    AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:videoURL options:nil]; 

    AVMutableCompositionTrack *videoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 

    [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:kCMTimeZero error:nil]; 

    // Create an AVMutableVideoCompositionLayerInstruction for the video track. 
    AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    mainInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration); 

    AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack]; 

    // Setup video composition 
    AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; 
    videoComposition.renderSize = CGSizeMake(videoTrack.naturalSize.width,videoTrack.naturalSize.height); 
    videoComposition.frameDuration = CMTimeMake(1, 30); 

    mainInstruction.layerInstructions = [NSArray arrayWithObject:videolayerInstruction]; 
    videoComposition.instructions = [NSArray arrayWithObject:mainInstruction]; 

    NSLog(@"Width: %f Height: %f", videoTrack.naturalSize.width, videoTrack.naturalSize.height); 

    // Setup animation layer 
    UIImage* image = [UIImage imageNamed:@"dogge_icon.png"]; 
    CALayer *animationLayer = [CALayer layer]; 
    animationLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height); 
    [animationLayer setMasksToBounds:YES]; 
    [animationLayer setContents: (id)image.CGImage]; 

    // Add animation 
    CABasicAnimation *animation = 
    [CABasicAnimation animationWithKeyPath:@"transform.scale"]; 

    animation.duration=5.0; 
    animation.autoreverses=YES; 
    animation.fromValue = [NSNumber numberWithFloat:1.0f]; 
    animation.toValue = [NSNumber numberWithFloat:2.0f]; 
    animation.repeatCount=10; 
    animation.beginTime = AVCoreAnimationBeginTimeAtZero; 
    [animationLayer addAnimation:animation forKey:@"scale"]; 
    NSLog(@"animationLayer animations: %@", [animationLayer animationKeys]); 

    // Build layer hierarchy 
    CALayer *parentLayer = [CALayer layer]; 
    CALayer *videoLayer = [CALayer layer]; 

    parentLayer.frame = CGRectMake(0, 0, videoTrack.naturalSize.width, videoTrack.naturalSize.height); 
    videoLayer.frame = CGRectMake(0, 0, videoTrack.naturalSize.width, videoTrack.naturalSize.height); 

    [parentLayer addSublayer:videoLayer]; 
    [parentLayer addSublayer:animationLayer]; 

    videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool 
          videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer]; 

    // Export 
    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetHighestQuality]; 

    NSString *exportVideoPath = [STPFileUtilities getPathToFileIn: NSDocumentDirectory WithName: @"composition.mov"]; 
    [STPFileUtilities deleteFileIfExists:exportVideoPath]; 
    NSURL *exportURL = [NSURL fileURLWithPath:exportVideoPath]; 

    exportSession.outputURL = exportURL; 
    exportSession.outputFileType = AVFileTypeQuickTimeMovie; 
    exportSession.videoComposition = videoComposition; 
    [exportSession exportAsynchronouslyWithCompletionHandler:^{ 
     switch (exportSession.status) { 
      case AVAssetExportSessionStatusFailed:{ 
       NSLog(@"FAIL: %@", exportSession.error); 
       break; 
      } 
      case AVAssetExportSessionStatusCompleted: { 
       NSLog (@"SUCCESS"); 
      } 
     }; 
    }]; 
} 

回答

2

我不知道我的所作所爲。 我從頭開始重寫了整個代碼並添加

animation.removedOnCompletion = NO; 

所有動畫和現在的作品。

0

的文檔狀態:

您使用AVVideoCompositionCoreAnimationTool對象納入 核心動畫在視頻組成。

任何動畫將在視頻的時間軸,而不是 實時進行解釋,所以你應該:

  1. 集動畫BEGINTIME屬性AVCoreAnimationBeginTimeAtZero而不是0(CoreAnimation與CACurrentMediaTime代替);
  2. 將removedOnCompletion設置爲NO,以免它們被自動刪除;
  3. 避免使用與UIView對象關聯的圖層。

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVVideoCompositionCoreAnimationTool_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40009744-CH1-DontLinkElementID_1

因此,爲什麼加入

animation.removedOnCompletion = NO; 

作品在你的答案表明你自己的問題。雖然我不是100%確定這裏發生了什麼,但如果我不得不猜測,我會說核心動畫是預處理的,然後與視頻層合成。如果將其刪除,則在視頻合成發生之前將其刪除。

當對樂曲使用CALayers和動畫時,如果我想將它們切換爲「關閉」,我必須將它們設置爲0不透明度以隱藏它們。


如何在特定時間開始的動畫。

以下示例(未測試)基本上將整個圖層設置爲透明(不透明度0.0)。在2秒(startTime)開始動畫,並在3秒內將不透明度從0.5降至1.0(半透明至完全不透明)。它應該在最後「關閉」 - 它會默認回到初始化(完全透明)值。

基本上就是這樣,只需在幾秒鐘內設置開始和持續時間即可。它在幀和時間之間進行「有趣」的追蹤,但你可以做到。我使用大量的動畫層,所有這些動畫層都被連接到一個圖層中,並且都具有多個時間點。最大的麻煩在於跟蹤什麼是什麼以及什麼時候發生。

+0

如果我想在兩秒後添加動畫,該怎麼辦?我可以在AVCoreAnimationBeginTimeAtZero上添加幾秒鐘嗎?我試過flipAnimation.beginTime = CACurrentMediaTime()+ 1;但沒有運氣。 – Nil

+0

您需要自己計算時間並將其添加到動畫中。我不認爲你可以在合成視頻的情況下使用CACurrentMediaTime。我會在你的答案中加入一些細節。 –