Настройка AVSynchonizedLayer - PullRequest
12 голосов
/ 09 мая 2011

Я пытался создать концепцию, которая связывает видео с объектом анимации (по сути, я «ротоскопирую» выбранное пользователем растровое изображение на стандартном видео в определенных местах). После просмотра всего доступного материала Apple, касающегося Core Animation (WWDC10 и т. Д.) И AVSync..Layer (пример кода Apple WWDC10, пример кода документа), просто не хватает достаточно четкого изолированного примера кода, чтобы понять, как это реализовать. Режим воспроизведения правильно.

Используя CA, у меня есть видео актив, который загружается в CALayer, и анимация, которая прикрепляется к растровому изображению и затем подключается к другому CALayer. Я создал AVSynchronizedLayer и добавил оба объекта в качестве подслоев.

Когда это дерево добавляется в свойство слоя UIView, я ожидал, что воспроизведение анимации будет выполняться синхронно с видео. Вместо этого я вижу только воспроизведение видео, и анимация никогда не выполняется - вот соответствующие части моего кода, которые все находятся в одном контроллере вида (называемом в ViewDidLoad).

Video101.m4v = простое видео m4v, gerald.png = bitmap

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"Video101" withExtension:@"m4v"];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];

AVPlayer *player = [[AVPlayer playerWithPlayerItem:playerItem]retain];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
playerLayer.frame = CGRectMake(0, 0, 1024, 768);
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

CALayer *gerald = [CALayer layer];
gerald.frame = CGRectMake(0, 0, 120, 120);
gerald.contents = (id) [UIImage imageNamed:@"gerald.png"].CGImage;

[self.view.layer addSublayer:playerLayer];
[self.view.layer insertSublayer:gerald above:playerLayer];


CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
anim.duration = 18.0;

anim.values = [NSArray arrayWithObjects:
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(480.0, 206.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(10.0, 760.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)],
               [NSValue valueWithCGPoint:CGPointMake(320.0, 406.0)],
               [NSValue valueWithCGPoint:CGPointMake(310.0, 400.0)], nil];


anim.keyTimes = [NSArray arrayWithObjects:
                 [NSNumber numberWithFloat:0.02],
                 [NSNumber numberWithFloat:0.06],
                 [NSNumber numberWithFloat:0.09],
                 [NSNumber numberWithFloat:0.1], 
                 [NSNumber numberWithFloat:0.12],
                 [NSNumber numberWithFloat:0.2],
                 [NSNumber numberWithFloat:0.25],
                 [NSNumber numberWithFloat:0.32], 
                 [NSNumber numberWithFloat:0.38],
                 [NSNumber numberWithFloat:0.49],
                 [NSNumber numberWithFloat:0.53],
                 [NSNumber numberWithFloat:0.59], 
                 [NSNumber numberWithFloat:0.63],
                 [NSNumber numberWithFloat:0.69],
                 [NSNumber numberWithFloat:0.78],
                 [NSNumber numberWithFloat:0.81], 
                 [NSNumber numberWithFloat:0.91], 
                 [NSNumber numberWithFloat:1.0], nil];


AVSynchronizedLayer *syncLayer = [AVSynchronizedLayer synchronizedLayerWithPlayerItem:playerItem];
[syncLayer addSublayer:gerald];
[gerald addAnimation:anim forKey:@"transform.position"];

[self.view.layer addSublayer:syncLayer];

[player play];

Какой правильный формат или способ для реализации AVSynchronizedLayer, чтобы анимация и воспроизведение видео вместе?

1 Ответ

14 голосов
/ 10 мая 2011

Вы правильно настроили CAKeyframeAnimation за исключением одного бита: Согласно лекции WWDC "Редактирование медиа с помощью AV Foundation", вам нужно установить для свойства beginTime вашей анимации ненулевое значение.

Ноль beginTime автоматически переводится в CACurrentMediaTime (). Используйте небольшое ненулевое число: например, 1e-100 или -1e-100 (AVCoreAnimationBeginTimeAtZero)

Я думаю, что если вы добавите anim.beginTime = AVCoreAnimationBeginTimeAtZero;, вы обнаружите, что анимация начинается именно тогда, когда начинается воспроизведение видео.

...