It's been a while since this question was asked but after looking everywhere, I have managed to come up with something similar by sampling data in real time during recording (at 1/30 sec. with a timer for a video recorded at 30fps) and storing it in an array. Then in post-processing, I create multiple CALayers in a loop for each data element in the array and draw the visualisation of that data on each layer.
Each layer has an CAAnimation that fades in opacity at the correct media timeline with the beginTime attribute, which is simply 1/30 sec. multiplied by the array index. This is so short a time that the layer immediately appears over the preceeding layer. If the layer background is opaque, it will obscure the needle rendered in the previous layer and so appear to animate the needle in pretty good synch with the original video capture. You may have to tweak the timing a little but I am no more than one frame out.
/******** 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;
It is processor and memory intensive, so it's not great for long videos or complex drawing. I am sure there are more elegant methods but this works and I hope this helps.