我有一个应用程序,我试图在视频上加上时间戳。为此,我使用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);
}
}];
答案 0 :(得分:2)
我与苹果支持保持联系并告诉我这是他的SDK中的一个错误。他们正试图解决这个问题。
此外,我在苹果臭虫记者中打开了一个事件,如果你是苹果开发者,我建议你开一个新的事件来对这一事件施加更大的压力。
https://bugreport.apple.com/logon
最好的问候。
答案 1 :(得分:2)
最后,我喜欢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];
它的工作原理非常好,但是在阵列中需要1或2秒到5000或6000个图像,并且在导出视频时它还需要15000/16000个图像,它会因溢出错误而崩溃。这是框架中的另一个错误。
如您所知,这是框架中的一个问题,至少在Apple修复CATextLayer和动画问题之前,这是一个解决方案,我也将此解决方案提供给苹果。