cakeyframeanimation - AVFoundation export video with animation at specific time duration in previously recorded video? -
i using avassetexportsession export video animation @ specific time. running fine before 2 days. changed , stopped working don't know wrong it. sorry long code.
can me it?
the code attached below. in advance.
- (ibaction)btnaddclick:(id)sender { //contains cgimage of image sequence animation gunimagesarray = [[nsmutablearray alloc]init]; //contains cmtime array time duration [0-1] keytimesarray = [[nsmutablearray alloc]init]; (int = 1; i<31; i++) { nsstring *imagename = [nsstring stringwithformat:@"frame_%d.png",i]; [gunimagesarray addobject:(id)[uiimage imagenamed:imagename].cgimage]; } double currenttime = cmtimegetseconds(mplayer.currenttime); nslog(@"currentduration %f",currenttime); (int z = 1; z<31; z++) { nsnumber *temp = [nsnumber numberwithfloat:(currenttime+(float)z/30)]; [keytimesarray addobject:temp]; } nslog(@"key times %@",keytimesarray); //create avurlasset video url avurlasset* videoasset = [avurlasset urlassetwithurl:murl options:nil]; //create avmutable composition avmutablecomposition* mixcomposition = [avmutablecomposition composition]; //create avmutablecompositiontrack add avmutablecomposition avmutablecompositiontrack *compositionvideotrack = [mixcomposition addmutabletrackwithmediatype:avmediatypevideo preferredtrackid:kcmpersistenttrackid_invalid]; [compositionvideotrack setpreferredtransform:[[[videoasset trackswithmediatype:avmediatypevideo] objectatindex:0] preferredtransform]]; //create avassettrack avassettrack *clipvideotrack = [[videoasset trackswithmediatype:avmediatypevideo] objectatindex:0]; //calculate video duration time cmtimerange emptyrange = cmtimerangemake(kcmtimezero, cmtimemake(videoasset.duration.value, videoasset.duration.timescale)); nslog(@"empty video track range %@", [nsvalue valuewithcmtimerange:emptyrange]); nserror *error; bool result = [mixcomposition inserttimerange:emptyrange ofasset:videoasset attime:mixcomposition.duration error:&error]; nslog(@"result = %d",result); cgsize videosize = [clipvideotrack naturalsize]; nslog(@"video width = %f height = %f",videosize.width,videosize.height); //animation start calayer *parentlayer = [calayer layer]; parentlayer.backgroundcolor = [uicolor redcolor].cgcolor; calayer *videolayer = [calayer layer]; videolayer.backgroundcolor = [uicolor orangecolor].cgcolor; parentlayer.frame = cgrectmake(0, 0, videosize.width, videosize.height); videolayer.frame = cgrectmake(0, 0, videosize.width, videosize.height); [parentlayer addsublayer:videolayer]; avsynchronizedlayer *animationlayer = [calayer layer]; animationlayer.opacity = 1.0; animationlayer.backgroundcolor = [uicolor yellowcolor].cgcolor; [animationlayer setframe:videolayer.frame]; [parentlayer addsublayer:animationlayer]; cakeyframeanimation *frameanimation = [[cakeyframeanimation alloc] init]; frameanimation.begintime = 0.1; [frameanimation setkeypath:@"contents"]; frameanimation.calculationmode = kcaanimationdiscrete; //mode of transformation of images [animationlayer setcontents:[gunimagesarray lastobject]]; //set array objects encounterd frameanimation.autoreverses = no; //if set yes, transition in fade in fade out manner frameanimation.duration = 1.0; //set image duration , can predefined float value frameanimation.repeatcount = 1; //this inifinite, can set integer value [frameanimation setvalues:gunimagesarray]; [frameanimation setkeytimes:keytimesarray]; [frameanimation setremovedoncompletion:no]; [frameanimation setdelegate:self]; [animationlayer addanimation:frameanimation forkey:@"contents"]; //end animation //start composing avmutablevideocomposition* videocomp = [avmutablevideocomposition videocomposition]; videocomp.rendersize = videosize; //videocomp.rendersize = cgsizemake(352.0, 288.0); videocomp.renderscale = 1.0; videocomp.frameduration = cmtimemake(1, 30); videocomp.animationtool = [avvideocompositioncoreanimationtool videocompositioncoreanimationtoolwithpostprocessingasvideolayer:animationlayer inlayer:parentlayer]; ///layer instruction avmutablevideocompositioninstruction *instruction = [avmutablevideocompositioninstruction videocompositioninstruction]; cmtimerange timerange = cmtimerangemake(kcmtimezero, videoasset.duration); instruction.timerange = timerange; avassettrack *videotrack = [[mixcomposition trackswithmediatype:avmediatypevideo] objectatindex:0]; avmutablevideocompositionlayerinstruction* layerinstruction = [avmutablevideocompositionlayerinstruction videocompositionlayerinstructionwithassettrack:videotrack]; instruction.layerinstructions = [nsarray arraywithobject:layerinstruction]; videocomp.instructions = [nsarray arraywithobject: instruction]; nsurl *audiourl = [[nsbundle mainbundle] urlforresource:@"loud_gunshot" withextension:@"mp3"]; avurlasset* audioasset1 = [[avurlasset alloc]initwithurl:audiourl options:nil]; nserror*nullerror = null; avmutablecompositiontrack *compositionaudiotrack1 = [mixcomposition addmutabletrackwithmediatype:avmediatypeaudio preferredtrackid:kcmpersistenttrackid_invalid]; [compositionaudiotrack1 inserttimerange:cmtimerangemake(kcmtimezero,audioasset1.duration) oftrack:[[audioasset1 trackswithmediatype:avmediatypeaudio]objectatindex:0] attime:mplayer.currenttime error:&nullerror]; //start export session _assetexport = [[avassetexportsession alloc] initwithasset:mixcomposition presetname:avassetexportpresetpassthrough]; _assetexport.videocomposition = videocomp; nsstring* videoname = @"video6.mov"; nsstring *exportpath = [nstemporarydirectory() stringbyappendingpathcomponent:videoname]; nsurl *exporturl = [nsurl fileurlwithpath:exportpath]; if ([[nsfilemanager defaultmanager] fileexistsatpath:exportpath]) { [[nsfilemanager defaultmanager] removeitematpath:exportpath error:nil]; } _assetexport.outputfiletype = avfiletypequicktimemovie; _assetexport.outputurl = exporturl; _assetexport.shouldoptimizefornetworkuse = yes; [_assetexport exportasynchronouslywithcompletionhandler: ^(void ) { switch (_assetexport.status) { case avassetexportsessionstatuscompleted: { //your finalization code here nslog(@"export completed."); dispatch_async(dispatch_get_main_queue(), ^{ [self exportdidfinish:_assetexport]; }); } break; case avassetexportsessionstatusfailed: { uialertview *alert = [[uialertview alloc] initwithtitle:@"export failed" message:_assetexport.error.description delegate:nil cancelbuttontitle:@"ok" otherbuttontitles:nil]; [alert show]; nslog(@"export failed. %@", _assetexport.error); } break; case avassetexportsessionstatuscancelled: { nslog(@"export cancelled."); } break; default: break; } }]; } -(void)exportdidfinish:(avassetexportsession*)session { nsurl *exporturl = session.outputurl; alassetslibrary *library = [[alassetslibrary alloc] init]; if ([library videoatpathiscompatiblewithsavedphotosalbum:exporturl]) { [library writevideoatpathtosavedphotosalbum:exporturl completionblock:^(nsurl *asseturl, nserror *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { uialertview *alert = [[uialertview alloc] initwithtitle:@"error" message:@"video saving failed" delegate:nil cancelbuttontitle:@"ok" otherbuttontitles:nil]; [alert show]; } else { uialertview *alert = [[uialertview alloc] initwithtitle:@"video saved" message:@"saved photo album" delegate:self cancelbuttontitle:@"ok" otherbuttontitles:nil]; [alert show]; } }); }]; } nslog(@"completed"); //uialertview *alert = [[uialertview alloc] initwithtitle:@"alertview" message:@"video edited successfully." delegate:self cancelbuttontitle:@"ok" otherbuttontitles:nil]; //[alert show]; }
instead of avassetexportpresetpassthrough use other preset , works.
Comments
Post a Comment