CAKeyframeAnimation не анимирует CATextLayer при экспорте видео

У меня есть приложение, в котором я пытаюсь поставить метку времени на видео. Для этого я использую AVFoundation и Core Animation, чтобы поместить CATextLayer поверх видеослоя. Если я помещу текст в свойство строки CATextLayer, строка правильно отобразится в экспортированном видео. Если я затем добавлю анимацию в CATextLayer, текст никогда не изменится. Я полагаю, что я что-то упустил из виду, но я могу найти, что это такое.

Спасибо заранее за любую помощь.

Вот пример кода.

AVMutableComposition *composition = [AVMutableComposition composition];

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.frameDuration = CMTimeMake(1, 30);

AVMutableCompositionTrack *videoCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];

AVMutableCompositionTrack *audioCompositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
NSDictionary *assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];

AVAsset *asset = [[AVURLAsset alloc] initWithURL:myUrl options:assetOptions];

AVAssetTrack *audioAssetTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
[audioCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:audioAssetTrack atTime:kCMTimeZero error:nil];

AVAssetTrack *videoAssetTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
[videoCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, [asset duration]) ofTrack:videoAssetTrack atTime:kCMTimeZero error:nil];

videoComposition.renderSize = videoCompositionTrack.naturalSize;

AVMutableVideoCompositionInstruction *videoCompositionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
videoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration);

AVMutableVideoCompositionLayerInstruction *videoCompositionLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoCompositionTrack];
[videoCompositionLayerInstruction setOpacity:1.0f atTime:kCMTimeZero];
videoCompositionInstruction.layerInstructions = @[videoCompositionLayerInstruction];

videoComposition.instructions = @[videoCompositionInstruction];

CALayer *parentLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0.0f, 0.0f, videoComposition.renderSize.width, videoComposition.renderSize.height);

CALayer *videoLayer = [CALayer layer];
videoLayer.frame = CGRectMake(0.0f, 0.0f, videoComposition.renderSize.width, videoComposition.renderSize.height);
[parentLayer addSublayer:videoLayer];

CATextLayer *textLayer = [CATextLayer layer];
textLayer.font = (__bridge CFTypeRef)([UIFont fontWithName:@"Helvetica Neue" size:45.0f]);
textLayer.fontSize = 45.0f;
textLayer.foregroundColor = [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f].CGColor;
textLayer.shadowColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f].CGColor;
textLayer.shadowOffset = CGSizeMake(0.0f, 0.0f);
textLayer.shadowOpacity = 1.0f;
textLayer.shadowRadius = 4.0f;
textLayer.alignmentMode = kCAAlignmentCenter;
textLayer.truncationMode = kCATruncationNone;

CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"string"];

// Step 8: Set the animation values to the object.
keyFrameAnimation.calculationMode = kCAAnimationLinear;
keyFrameAnimation.values = @[@"12:00:00", @"12:00:01", @"12:00:02", @"12:00:03",
                             @"12:00:04", @"12:00:05", @"12:00:06", @"12:00:07",
                             @"12:00:08", @"12:00:09"];
keyFrameAnimation.keyTimes = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.1f],
                               [NSNumber numberWithFloat:0.2f], [NSNumber numberWithFloat:0.3f],
                               [NSNumber numberWithFloat:0.4f], [NSNumber numberWithFloat:0.5f],
                               [NSNumber numberWithFloat:0.6f], [NSNumber numberWithFloat:0.7f],
                               [NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:0.9f]];
keyFrameAnimation.beginTime = AVCoreAnimationBeginTimeAtZero;
keyFrameAnimation.duration = CMTimeGetSeconds(composition.duration);
keyFrameAnimation.removedOnCompletion = YES;

[textLayer addAnimation:keyFrameAnimation forKey:@"string"];
textLayer.frame = CGRectMake(0.0f, 20.0f, videoComposition.renderSize.width, 55.0f);
[parentLayer addSublayer:textLayer];
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPreset1920x1080];
exportSession.videoComposition = videoComposition;
exportSession.audioMix = audioMix;
exportSession.outputFileType = [exportSession.supportedFileTypes objectAtIndex:0];
exportSession.outputURL = mySaveUrl;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
    self.delegate = nil;

    switch (exportSession.status) {
        case AVAssetExportSessionStatusCancelled:
            NSLog(@"Export session cancelled.");
            break;
        case AVAssetExportSessionStatusCompleted:
            NSLog(@"Export session completed.");
            break;
        case AVAssetExportSessionStatusFailed:
            NSLog(@"Export session failed.");
            break;
        case AVAssetExportSessionStatusUnknown:
            NSLog(@"Export session unknown status.");
            break;
        case AVAssetExportSessionStatusWaiting:
            NSLog(@"Export session waiting.");
            break;
        default:
            break;
    }
    NSError *error = exportSession.error;
    if (error != nil) {
        NSLog(@"An error ocurred while exporting.  Error: %@: %@", error.localizedDescription, error.localizedFailureReason);
    }
}];

comment
Знаете ли вы, как создать эффект перехода между двумя изображениями при создании видео. Если вы знаете, как это возможно, пожалуйста, помогите мне..   -  person Milan patel    schedule 26.12.2014


Ответы (2)


Я остаюсь на связи со службой поддержки Apple, и мне сказали, что это ошибка в его SDK. Они пытаются решить проблему.

Также я открываю инцидент в репортере об ошибках Apple. Если вы разработчик Apple, я рекомендую вам открыть новый, чтобы оказать большее давление на этот инцидент.

https://bugreport.apple.com/logon

С наилучшими пожеланиями.

person c4esp    schedule 21.12.2013
comment
Спасибо за обновление, и я должен извиниться перед всеми, кто читал этот пост с интересом, так как я не обновлял свой вопрос. Я работаю с Apple над этим. Вы правы, это ошибка, и они работают над ее исправлением. Мне сказали попробовать поместить мою анимацию в группу анимаций и посмотреть, сработает ли это. Это не для меня, но другим может повезти больше, чем мне. - person Rob; 23.12.2013
comment
Кажется, эта ошибка все еще существует, у вас есть обновление? Кроме того, у вас есть номер радара на жучке? - person tomgerhardt; 08.09.2014

Наконец я нашел решение в CATextLayer и анимации. Вероятно, это не лучшее решение, но, по крайней мере, оно работает нормально.

Чтобы решить эту проблему, мы должны передать NSString в UIImage или CALayer, а затем поместить все эти изображения (CGImage) в NSMutableArray и загрузить этот изменяемый массив в CAKeyAnimation и выполнить модификацию переменной содержимого.

 -(UIImage *)imageFromText:(NSString *)text
 {
UIGraphicsBeginImageContextWithOptions(sizeImageFromText,NO,0.0);//Better resolution (antialiasing)
//UIGraphicsBeginImageContext(sizeImageFromText); // iOS is < 4.0

[text drawInRect:aRectangleImageFromText withAttributes:attributesImageFromText];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return image;
}

Добавление изображений в NSmutableArray

 [NSMutableArrayAux addObject:(__bridge id)[self imageFromText:@"Hello"].CGImage];

Установите CAKeyAnimation, чтобы изменить содержимое изображения (изменить изображение)

 CAKeyframeAnimation *overlay = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
 overlay.values = [[NSArray alloc] initWithArray:NSMutableArrayAux];

Он работает очень хорошо, но для 5000 или 6000 изображений в массиве требуется 1 или 2 секунды, а также с 15000/16000 изображений при экспорте видео происходит сбой с ошибкой переполнения. Это еще одна ошибка в фреймворке.

Как вы знаете, это проблема фреймворка, и это решение, по крайней мере, до тех пор, пока Apple не исправит CATextLayer и проблему с анимацией, также я даю это решение и Apple.

person c4esp    schedule 02.01.2014