Как связать / синхронизировать анимацию с видеозаписью в реальном времени - PullRequest
5 голосов
/ 29 июня 2011

Описание приложения : Спидометр. Имеет игольчатый циферблат и анимированные иглы в качестве наложения на видео. Я выводил анимацию иглы на видео через постобработку. Я использую AVAssetExportSession и создаю AVComposition, содержащий мои анимированные слои, а также видео и аудио дорожки из видео. Это отлично работает. Видео показывает, иголка оживляет.

В настоящее время, чтобы воспроизвести анимацию во время постобработки, я сохранил любое изменение скорости со времени, прошедшего с начала «записи» видео. Во время постобработки я затем запускаю таймер (ы) на основе сохраненных данных времени / скорости, чтобы затем оживить иглу до следующей скорости.

Проблема : Результирующая пара видео / анимация не полностью точна, и часто наблюдается несоответствие между скоростью, отображаемой при съемке видео и его воспроизведении и компоновке. (обычно игла идет перед видео) из-за того, что наложение / сжатие во время экспорта не обязательно происходит в реальном времени.

Вопрос : Есть ли способ, которым я могу вставить информацию о скорости в видеопоток записи, а затем получить к ней доступ при экспорте, чтобы согласовать видео и спидометр по времени?

Было бы неплохо получить обратный вызов в определенное время во время экспорта, который содержит мои данные о скорости.

Как всегда ... спасибо!

Ответы [ 5 ]

1 голос
/ 20 марта 2014

Прошло довольно много времени с тех пор, как этот вопрос был задан, но, посмотрев везде, мне удалось придумать нечто похожее, сэмплировав данные в реальном времени во время записи (со скоростью 1/30 с, с таймером для видео, записанного со скоростью 30 кадров в секунду). ) и хранить его в массиве. Затем в постобработке я создаю несколько CALayers в цикле для каждого элемента данных в массиве и рисую визуализацию этих данных на каждом слое.

Каждый слой имеет анимацию CAAnimation, которая исчезает в непрозрачности на правильной временной шкале медиа с атрибутом beginTime , который составляет всего 1/30 сек. умножается на индекс массива. Это настолько короткое время, что слой сразу появляется поверх предыдущего слоя. Если фон слоя непрозрачен, он затеняет иглу, визуализированную в предыдущем слое, и, таким образом, кажется, что анимирует иглу в довольно хорошей синхронизации с оригинальным захватом видео. Возможно, вам придется немного подправить время, но я не более чем на один кадр.

/******** this has not been compiled but you should get the idea ************

// Before starting the AVAssetExportSession session and after the AVMutableComposition routine

CALayer* speedoBackground = [[CALayer alloc] init]; // background layer for needle layers
[speedoBackground setFrame:CGRectMake(x,y,width,height)]; // size and location
[speedoBackground setBackgroundColor:[[UIColor grayColor] CGColor]];
[speedoBackground setOpacity:0.5] // partially see through on video

// loop through the data
for (int index = 0; index < [dataArray count]; index++) {

  CALayer* speedoNeedle = [[CALayer alloc] init]; // layer for needle drawing
  [speedoNeedle setFrame:CGRectMake(x,y,width,height)]; // size and location
  [speedoNeedle setBackgroundColor:[[UIColor redColor] CGColor]];
  [speedoNeedle setOpacity:1.0]; // probably not needed

  // your needle drawing routine for each data point ... e.g.
  [self drawNeedleOnLayer:speedoNeedle angle:[self calculateNeedleAngle[dataArray objectAtIndex:index]]];

  CABasicAnimation *needleAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
  needleAnimation.fromValue = [NSNumber numberWithFloat:(float)0.0];
  needleAnimation.toValue = [NSNumber numberWithFloat:(float)1.0]; // fade in
  needleAnimation.additive = NO;
  needleAnimation.removedOnCompletion = NO; // it obscures previous layers
  needleAnimation.beginTime = index*animationDuration;
  needleAnimation.duration = animationDuration -.03; // it will not animate at this speed but layer will appear immediately over the previous layer at the correct media time
  needleAnimation.fillMode = kCAFillModeBoth;
  [speedoNeedle addAnimation:needleAnimation forKey:nil];
  [speedoBackground addSublayer:needleOverlay];
}

[parentLayer addSublayer:speedoBackground];

.
.
.
// when the AVAssetExportSession has finished, make sure you clear all the layers
parentLayer.sublayers = nil;

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

1 голос
/ 10 июля 2011

Вы должны использовать CAAnimations и свойство beginTime, чтобы заранее настроить анимацию, затем используйте AVVideoComposition + AVVideoCompositionCoreAnimationTool , чтобы добавить их в видео при экспорте.Обратите внимание на состояние документации:

Любая анимация будет интерпретироваться на временной шкале видео, а не в реальном времени ...

Таким образом, ваша анимация будет выстроена именно там, где вы указываетес результирующим фильмом.

1 голос
/ 09 июля 2011

Если вам нужно встроить метаданные во время работы приложения на iPhone, я не знаю, как это сделать. Если вы можете выполнить встраивание ранее, используйте HTTP LIve Streaming и HTTP Live Streaming Tools.

Метаданные генерируются в файле id3taggenerator и внедряются в видео с использованием mediafilesegmenter. Пример:

id3taggenerator -o camera1.id3 -text "Dolly camera"
id3taggenerator -o camera2.id3 -text "Tracking camera"

Существует несколько видов метаданных, которые вы можете встраивать, включая двоичные объекты. Обратитесь к странице справочника для деталей. Теперь нам нужно сослаться на сгенерированный файл из «мета-макрофайла». Это простой текстовый файл в следующем формате:

60 id3 camera1.id3
120 id3 camera2.id3

Первое число - это количество секунд, прошедших с начала видео, в которое вы хотите вставить уведомление. Я точно не помню команду mediafilesegmenter, извините, вы должны передать как минимум файл макроса, индекс и видеофайл.

Полученное видео содержит метаданные, которые публикуются MPMoviePlayerController в качестве уведомлений. Подробности смотрите на этой странице: http://jmacmullin.wordpress.com/2010/11/03/adding-meta-data-to-video-in-ios/

1 голос
/ 09 июля 2011

Вместо использования таймеров для анимации иглы создайте анимацию ключевого кадра на основе записанных вами данных о скорости.

Таймеры и CA обычно плохо сочетаются, по крайней мере, не так, как я понимаю из вашего описания.

0 голосов
/ 10 июля 2011

В этом году на WWDC есть сеанс, который может дать иной подход к тому, что вы делаете.Вы можете посмотреть видео здесь: http://developer.apple.com/videos/wwdc/2011/.Ищите один под названием «Работа со СМИ в AVFoundation».Интересные биты около минуты 26 или около того.Я не совсем уверен, что понимаю проблему, но когда я прочитал ее, мне пришла в голову эта сессия.

...