iOS 仿抖音圖片轉(zhuǎn)視頻效果

本圖片轉(zhuǎn)視頻加入了圖片縮放和轉(zhuǎn)場(chǎng)效果,通過(guò)向一個(gè)本地的黑色背景視頻black.mp4加入圖片的縮放和轉(zhuǎn)場(chǎng)動(dòng)畫(huà)來(lái)實(shí)現(xiàn)

- (void)videoAnimation:(NSArray *)imgArr (void(^)(NSURL*))success{

//每張圖片顯示的時(shí)間

NSInteger picTime = 3;

//獲取背景視頻地址

? ? NSString *videoPath = [[NSBundle mainBundle] pathForResource:@"black" ofType:@"mp4"];

? ? NSString *cachePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"imagesComposition.mp4"];

? ? if ([[NSFileManager defaultManager] fileExistsAtPath:cachePath])

? ? ? ? {

? ? ? ? ? ? [[NSFileManager defaultManager] removeItemAtPath:cachePath error:nil];

? ? ? ? }

? ? NSURL? ? *exportUrl = [NSURLfileURLWithPath:cachePath];

//視頻時(shí)長(zhǎng)

? ? NSInteger tempDuration =self.imgArr.count*picTime+0.1*self.imgArr.count;

? ? NSInteger duration = tempDuration >180.0?180.0:tempDuration;

//通過(guò)本地視頻地址創(chuàng)建視頻源

? ? AVURLAsset*videoAsset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:videoPath]];

? ? AVMutableComposition *mutableComposition = [AVMutableComposition composition];

//獲取視頻軌道

? ? AVMutableCompositionTrack *videoCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

? ? AVAssetTrack *videoAssetTrack = [videoAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;

? ? CMTimeValue value = videoAsset.duration.timescale* duration;

? ? CMTime endTime =CMTimeMake(value, videoAsset.duration.timescale);

? ? CMTimeRange timeR = CMTimeRangeMake(kCMTimeZero, endTime);

? ? [videoCompositionTrack insertTimeRange:timeR ofTrack:videoAssetTrack atTime:kCMTimeZero error:nil];

//獲取視頻軌道上的素材添加到最終合成的視頻軌道中

? ? AVMutableVideoCompositionInstruction *videoCompostionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];

? ? videoCompostionInstruction.timeRange= timeR;

? ? AVMutableVideoCompositionLayerInstruction *videoLayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoCompositionTrack];

? ? [videoLayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];

? ? [videoLayerInstruction setOpacity:0 atTime:endTime];

? ? videoCompostionInstruction.layerInstructions=@[videoLayerInstruction];


? ? AVMutableVideoComposition *mutableVideoComposition = [AVMutableVideoComposition videoComposition];

? ? mutableVideoComposition.renderSize=CGSizeMake(720,1280);

? ? mutableVideoComposition.frameDuration=CMTimeMake(1,25);

? ? mutableVideoComposition.instructions=@[videoCompostionInstruction];


//創(chuàng)建一個(gè)存放圖片圖層的數(shù)組

? ? CALayer*bgLayer = [[CALayer alloc]init];

? ? bgLayer.frame=CGRectMake(0,0,720,1280);

? ? bgLayer.position=CGPointMake(360,640);

? ? NSMutableArray *imageLayers = [NSMutableArray array];

? ? for(UIImage*img?in?self.imgArr) {

? ? ? ? CALayer*imageL = [[CALayer alloc]init];

? ? ? ? imageL.contents= (__bridgeid)img.CGImage;

? ? ? ? imageL.bounds=CGRectMake(0,0,720,1280);

? ? ? ? imageL.contentsGravity = kCAGravityResizeAspect;

? ? ? ? imageL.backgroundColor = [UIColor blackColor].CGColor;

? ? ? ? imageL.anchorPoint=CGPointMake(0,0);

? ? ? ? [bgLayer addSublayer:imageL];

? ? ? ? [imageLayers addObject:imageL];

? ? }

//圖片圖層添加動(dòng)畫(huà)效果

? ? ? ? [imageLayers enumerateObjectsUsingBlock:^(id? _Nonnullobj,NSUIntegeridx,BOOL*_Nonnullstop) {

? ? ? ? ? ? CABasicAnimation*animation1 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

? ? ? ? ? ? animation1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

? ? ? ? ? ? animation1.removedOnCompletion=false;

? ? ? ? ? ? animation1.beginTime=1.1+picTime* idx;

? ? ? ? ? ? animation1.fromValue= [NSNumber numberWithFloat:1.0];

? ? ? ? ? ? animation1.toValue= [NSNumber numberWithFloat:1.1];

? ? ? ? ? ? animation1.duration=2;

? ? ? ? ? ? animation1.fillMode=kCAFillModeBoth;

? ? ? ? ? ? [(CALayer*)obj addAnimation:animation1 forKey:@"transform.scale"];

? ? ? ? ? ? CABasicAnimation*animation2 = [CABasicAnimation animationWithKeyPath:@"position"];

? ? ? ? ? ? animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

? ? ? ? ? ? animation2.removedOnCompletion=false;

? ? ? ? ? ? animation2.beginTime=0.1+picTime* idx;

? ? ? ? ? ? animation2.fromValue= [NSValue valueWithCGPoint:CGPointMake(720* idx,0)];

? ? ? ? ? ? animation2.toValue= [NSValue valueWithCGPoint:CGPointMake(0,0)];

? ? ? ? ? ? animation2.duration=1;

? ? ? ? ? ? animation2.fillMode=kCAFillModeBoth;

? ? ? ? ? ? [(CALayer*)obj addAnimation:animation2forKey:@"position"];


? ? ? ? }];

//創(chuàng)建視頻圖層并添加生成的圖片動(dòng)畫(huà)

? ? ? ? CALayer*parentLayer = [[CALayer alloc]init];

? ? ? ? CALayer*videoLayer = [[CALayer alloc]init];

? ? ? ? parentLayer.frame=CGRectMake(0,0,720,1280);

? ? ? ? videoLayer.frame=CGRectMake(0,0,720,1280);

? ? ? ? [parentLayer addSublayer:videoLayer];

? ? ? ? [parentLayer addSublayer:bgLayer];

? ? ? ? parentLayer.geometryFlipped=YES;

//視頻圖層加入最終合成的視頻軌道中

? ? mutableVideoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];


//導(dǎo)出視頻

? ? AVAssetExportSession *assetExport = [AVAssetExportSession exportSessionWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality];

? ? assetExport.outputFileType = AVFileTypeMPEG4;

? ? assetExport.outputURL= exportUrl;

? ? assetExport.shouldOptimizeForNetworkUse = YES;

? ? assetExport.videoComposition= mutableVideoComposition;

? ? [assetExport exportAsynchronouslyWithCompletionHandler:^{

? ? ? ? if (assetExport.status == AVAssetExportSessionStatusCompleted) {

? ? ? ? ? ? if(success) {

? ? ? ? ? ? ? ? success(exportUrl);

? ? ? ? ? ? }

? ? ? ? }

? ? }];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容