Я пытаюсь объединить изображения в ранее существовавшее видео, чтобы создать новый видеофайл с помощью AVFoundation на Mac.Смешивание изображений и видео с использованием AVFoundation
До сих пор я прочитал пример документации компании Apple,
ASSETWriterInput for making Video from UIImages on Iphone Issues
Mix video with static image in CALayer using AVVideoCompositionCoreAnimationTool
AVFoundation Tutorial: Adding Overlays and Animations to Videos и несколько других SO связывает
Теперь они доказали, что довольно полезно время от времени, но моя проблема в том, что я не создаю статический водяной знак или наложение, я хочу разместить изображения между частями видео. До сих пор мне удалось получить видео и создать пустые разделы для того, чтобы эти изображения были вставлены и экспортированы.
Моя проблема заключается в том, чтобы изображения вставляли себя в эти пустые разделы. Единственный способ, с помощью которого я могу это сделать, - создать ряд слоев, которые анимируются, чтобы изменить их непрозрачность в правильные времена, но я не могу заставить анимацию работать.
Ниже приведен код, который я использую для создания видеосегментов и анимаций слоев.
//https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_Editing.html#//apple_ref/doc/uid/TP40010188-CH8-SW7
// let's start by making our video composition
AVMutableComposition* mutableComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* mutableCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVMutableVideoComposition* mutableVideoComposition = [AVMutableVideoComposition videoCompositionWithPropertiesOfAsset:gVideoAsset];
// if the first point's frame doesn't start on 0
if (gFrames[0].startTime.value != 0)
{
DebugLog("Inserting vid at 0");
// then add the video track to the composition track with a time range from 0 to the first point's startTime
[mutableCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, gFrames[0].startTime) ofTrack:gVideoTrack atTime:kCMTimeZero error:&gError];
}
if(gError)
{
DebugLog("Error inserting original video segment");
GetError();
}
// create our parent layer and video layer
CALayer* parentLayer = [CALayer layer];
CALayer* videoLayer = [CALayer layer];
parentLayer.frame = CGRectMake(0, 0, 1280, 720);
videoLayer.frame = CGRectMake(0, 0, 1280, 720);
[parentLayer addSublayer:videoLayer];
// create an offset value that should be added to each point where a new video segment should go
CMTime timeOffset = CMTimeMake(0, 600);
// loop through each additional frame
for(int i = 0; i < gFrames.size(); i++)
{
// create an animation layer and assign it's content to the CGImage of the frame
CALayer* Frame = [CALayer layer];
Frame.contents = (__bridge id)gFrames[i].frameImage;
Frame.frame = CGRectMake(0, 720, 1280, -720);
DebugLog("inserting empty time range");
// add frame point to the composition track starting at the point's start time
// insert an empty time range for the duration of the frame animation
[mutableCompositionTrack insertEmptyTimeRange:CMTimeRangeMake(CMTimeAdd(gFrames[i].startTime, timeOffset), gFrames[i].duration)];
// update the time offset by the duration
timeOffset = CMTimeAdd(timeOffset, gFrames[i].duration);
// make the layer completely transparent
Frame.opacity = 0.0f;
// create an animation for setting opacity to 0 on start
CABasicAnimation* frameAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
frameAnim.duration = 1.0f;
frameAnim.repeatCount = 0;
frameAnim.autoreverses = NO;
frameAnim.fromValue = [NSNumber numberWithFloat:0.0];
frameAnim.toValue = [NSNumber numberWithFloat:0.0];
frameAnim.beginTime = AVCoreAnimationBeginTimeAtZero;
frameAnim.speed = 1.0f;
[Frame addAnimation:frameAnim forKey:@"animateOpacity"];
// create an animation for setting opacity to 1
frameAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
frameAnim.duration = 1.0f;
frameAnim.repeatCount = 0;
frameAnim.autoreverses = NO;
frameAnim.fromValue = [NSNumber numberWithFloat:1.0];
frameAnim.toValue = [NSNumber numberWithFloat:1.0];
frameAnim.beginTime = AVCoreAnimationBeginTimeAtZero + CMTimeGetSeconds(gFrames[i].startTime);
frameAnim.speed = 1.0f;
[Frame addAnimation:frameAnim forKey:@"animateOpacity"];
// create an animation for setting opacity to 0
frameAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
frameAnim.duration = 1.0f;
frameAnim.repeatCount = 0;
frameAnim.autoreverses = NO;
frameAnim.fromValue = [NSNumber numberWithFloat:0.0];
frameAnim.toValue = [NSNumber numberWithFloat:0.0];
frameAnim.beginTime = AVCoreAnimationBeginTimeAtZero + CMTimeGetSeconds(gFrames[i].endTime);
frameAnim.speed = 1.0f;
[Frame addAnimation:frameAnim forKey:@"animateOpacity"];
// add the frame layer to our parent layer
[parentLayer addSublayer:Frame];
gError = nil;
// if there's another point after this one
if(i < gFrames.size()-1)
{
// add our video file to the composition with a range of this point's end and the next point's start
[mutableCompositionTrack insertTimeRange:CMTimeRangeMake(gFrames[i].startTime,
CMTimeMake(gFrames[i+1].startTime.value - gFrames[i].startTime.value, 600))
ofTrack:gVideoTrack
atTime:CMTimeAdd(gFrames[i].startTime, timeOffset) error:&gError];
}
// else just add our video file with a range of this points end point and the videos duration
else
{
[mutableCompositionTrack insertTimeRange:CMTimeRangeMake(gFrames[i].startTime, CMTimeSubtract(gVideoAsset.duration, gFrames[i].startTime)) ofTrack:gVideoTrack atTime:CMTimeAdd(gFrames[i].startTime, timeOffset) error:&gError];
}
if(gError)
{
char errorMsg[256];
sprintf(errorMsg, "Error inserting original video segment at: %d", i);
DebugLog(errorMsg);
GetError();
}
}
В настоящее время в этом сегменте непрозрачность рамы установлена на 0.0f, однако, когда я установил его на 1.0f все это делает, это просто место, последний из этих кадров в верхней части видео в течение всего срока.
После этого смотри на экспорт с использованием AVAssetExportSession, как показано ниже
mutableVideoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];
// create a layer instruction for our newly created animation tool
AVMutableVideoCompositionLayerInstruction *layerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:gVideoTrack];
AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
[instruction setTimeRange:CMTimeRangeMake(kCMTimeZero, [mutableComposition duration])];
[layerInstruction setOpacity:1.0f atTime:kCMTimeZero];
[layerInstruction setOpacity:0.0f atTime:mutableComposition.duration];
instruction.layerInstructions = [NSArray arrayWithObject:layerInstruction];
// set the instructions on our videoComposition
mutableVideoComposition.instructions = [NSArray arrayWithObject:instruction];
// export final composition to a video file
// convert the videopath into a url for our AVAssetWriter to create a file at
NSString* vidPath = CreateNSString(outputVideoPath);
NSURL* vidURL = [NSURL fileURLWithPath:vidPath];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPreset1280x720];
exporter.outputFileType = AVFileTypeMPEG4;
exporter.outputURL = vidURL;
exporter.videoComposition = mutableVideoComposition;
exporter.timeRange = CMTimeRangeMake(kCMTimeZero, mutableComposition.duration);
// Asynchronously export the composition to a video file and save this file to the camera roll once export completes.
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (exporter.status == AVAssetExportSessionStatusCompleted)
{
DebugLog("!!!file created!!!");
_Close();
}
else if(exporter.status == AVAssetExportSessionStatusFailed)
{
DebugLog("failed damn");
DebugLog(cStringCopy([[[exporter error] localizedDescription] UTF8String]));
DebugLog(cStringCopy([[[exporter error] description] UTF8String]));
_Close();
}
else
{
DebugLog("NoIdea");
_Close();
}
});
}];
}
Я получаю ощущение, что анимация не началась, но я не знаю. Правильно ли я собираюсь объединить данные изображения в видео, подобное этому?
Любая помощь будет принята с благодарностью.