Ich versuche, Bilder in ein bereits vorhandenes Video zu spleißen, um eine neue Videodatei mit AVFoundation auf Mac zu erstellen.Mischen von Bildern und Video mit AVFoundation
Bisher habe ich die Apple-Dokumentation Beispiel lesen,
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 und einige andere Links SO
Und dies bewiesen haben zu sein manchmal ziemlich nützlich, aber mein Problem ist, dass ich keine statische erstellen Wasserzeichen oder ein Overlay genau ich möchte Bilder zwischen Teilen des Videos einfügen. Bisher habe ich es geschafft, das Video zu erstellen und leere Abschnitte zu erstellen, damit diese Bilder eingefügt und exportiert werden können.
Mein Problem ist, dass die Bilder in diese leeren Abschnitte eingefügt werden. Der einzige Weg, den ich sehen kann, ist, eine Reihe von Layern zu erstellen, die animiert werden, um ihre Deckkraft zur richtigen Zeit zu ändern, aber ich kann nicht scheinen, dass die Animation funktioniert.
Der folgende Code ist, was ich verwende, um die Videosegmente und Ebenenanimationen zu erstellen.
//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();
}
}
nun in diesem Segment der Deckkraft des Rahmen wird auf 0.0f gesetzt, aber wenn ich es eingestellt alle 1.0F es tut, ist nur Platz die letzten diesen Rahmen auf das Video für die gesamte Dauer.
Danach wird die vide exportiert wird unter Verwendung eines AVAssetExportSession wie unten
gezeigtmutableVideoComposition.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();
}
});
}];
}
ich das Gefühl, dass die Animation nicht gestartet wird, aber ich weiß es nicht. Gehe ich hier richtig herum, um Bilddaten in ein Video zu spleißen?
Jede Hilfe wäre sehr willkommen.