使用CABasicAnimation animationWithKeyPath:@"内容"在CATextLayer上显示视频上的动态叠加文本

时间:2015-09-06 06:19:11

标签: ios video core-animation calayer

我正在开发一款为视频添加动态文字(如字幕)的应用。有许多类似的问题,但没有一个确实有一个可行的答案。我非常希望使用" ContentAnimate"而不是"内容"作为基于Synchronising image, text, and positioning with CoreAnimation的animationKeyPath 但这对我没用。

我可以将视频显示在视频上作为叠加层,但动画不起作用 - 我总是看到CATextLayer的原始基础文本。以下是我设置字幕和叠加的方法:

        // 1 - Set up the text layer
        CATextLayer *subtitle1Text = [[CATextLayer alloc] init];
        [subtitle1Text setFont:@"Helvetica-Bold"];
        //[subtitle1Text setString:[NSString stringWithFormat:@"%@: %@",  bookmark.creatorMonkeyName, bookmark.info]];
        [subtitle1Text setString:@"Place holder"];

        [subtitle1Text setFontSize:36];
        [subtitle1Text setFrame:CGRectMake(0, 0, videoSize.width, 100)];
        [subtitle1Text setAlignmentMode:kCAAlignmentCenter];
        [subtitle1Text setForegroundColor:[[UIColor whiteColor] CGColor]];


        // 2 - The  overlay
        CALayer *overlayLayer = [CALayer layer];
        [overlayLayer addSublayer:subtitle1Text];
        overlayLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
        [overlayLayer setMasksToBounds:YES];
        overlayLayer.hidden = YES;

        CALayer *parentLayer = [CALayer layer];
        CALayer *videoLayer = [CALayer layer];
        parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
        videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);

        [parentLayer addSublayer:videoLayer];
        [parentLayer addSublayer:overlayLayer];
        videoComp.renderSize = videoSize;
        videoComp.frameDuration = CMTimeMake(1, (int32_t) fps);

以下是我添加动画的方法:

            CABasicAnimation *showCommentAnimation2 = [CABasicAnimation animationWithKeyPath:@"contents"];

            [CATransaction begin];
            [CATransaction setDisableActions:YES];

            overlayLayer.hidden = NO;
            showCommentAnimation2.fromValue = @"Hello";
            showCommentAnimation2.toValue = @"Goodbye";
            showCommentAnimation2.beginTime = bookmark.relativeTimeStamp;
            showCommentAnimation2.duration = commentTimeDisplayed;
            [subtitle1Text addAnimation:showCommentAnimation2 forKey:[@(i) stringValue]]; //"i" is an iterator, This should allow multiple animations of the same type
            [CATransaction setDisableActions:NO];
            [CATransaction commit];

字幕弹出并消失 - 但我总是得到文字"占位符"从来没有"你好"或者"再见"。

我使用以下方法将视频导出到相机胶卷:

        videoComp.animationTool = [AVVideoCompositionCoreAnimationTool
                                   videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
    _assetExport.videoComposition = videoComp;
    _assetExport.outputFileType = @"public.mpeg-4";
    _assetExport.outputURL = outputFileUrl;
    [_assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void ) {
         if (AVAssetExportSessionStatusCompleted == _assetExport.status) {
             DLog(@"AVAssetExportSessionStatusCompleted");
             ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];
             DLog(@"About to copy video to camera roll");
             //move video to camera roll

             [library writeVideoAtPathToSavedPhotosAlbum:outputFileUrl completionBlock:^(NSURL *assetURL, NSError *error) {
                 [self removeWaitingScreen];
                 dispatch_async(dispatch_get_main_queue(), ^(void){
                     MPMoviePlayerViewController* theMovie = [[MPMoviePlayerViewController alloc] initWithContentURL: assetURL];
                     [_viewController presentMoviePlayerViewControllerAnimated:theMovie];

                 });
             }];
         } else{
             // a failure may happen because of an event out of your control
             // for example, an interruption like a phone call comming in
             // make sure and handle this case appropriately
             DLog(@"Error - Export Session Status: %ld", (long)_assetExport.status);
             dispatch_async(dispatch_get_main_queue(), ^(void){
                 [self removeWaitingScreen];
                 [[[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", NSStringFromClass([self class]))
                                              message:NSLocalizedString(@"Video Creation Failed", nil)
                                             delegate:nil
                                    cancelButtonTitle:NSLocalizedString(@"OK", nil)
                                    otherButtonTitles: nil] autorelease] show];
             });
         }

   [videoComp release];
   }];

}];

有人可以帮忙吗?

如果有更好的方法将字幕刻录到视频中,我愿意接受建议。

感谢。

2 个答案:

答案 0 :(得分:1)

具有关键路径contents的动画无法与字符串值(@"Hello"@"Goodbye"一起使用)。图层的contents属性包含图像,手动设置或由图层本身绘制。

简单地设置文本图层的string属性应足以导致隐式动画。但是,听起来你需要一个显式动画才能控制beginTime。这样做的方法是使用CATransition。有关示例,请参阅here

答案 1 :(得分:0)

感谢jtbandes我明白了。

步骤1:创建一个动画,在适当的时间更改该图层的隐藏属性:

CAKeyframeAnimation *showCommentAnimation = [CAKeyframeAnimation animationWithKeyPath:@"hidden"];
        [showCommentAnimation setValue:@"hidestring" forKey:@"MyAnimationType"];
        showCommentAnimation.values = @[@(NO),@(YES)];
        showCommentAnimation.keyTimes = @[@0.0, @1.0];
        showCommentAnimation.calculationMode = kCAAnimationDiscrete;
        showCommentAnimation.removedOnCompletion = NO;
        showCommentAnimation.delegate = self;

第2步:为每个评论创建单独的CATextLayer

CATextLayer *subtitle1Text = [[CATextLayer alloc] init];

将该图层的文本更改为相应的副标题:

[subtitle1Text setString:@"Actual subtitle for that layer"];

步骤3:使用适当的时间添加动画:

showCommentAnimation.beginTime = subtitle.relativeTimeStamp;
[subtitle1Text addAnimation:showCommentAnimation forKey:[@"setstring" stringByAppendingString:[@(i) stringValue]]]; //use showCommentAnimation to set hidden propert