ios - Weird behaviour of AVMutableComposition freezing while using AVMutableVideoComposition -
i trying merge multiple videos using avmutablecomposition
. problem face whenever try add avmutablevideocomposition
applying instructions, playback freezes in avplayer
@ exact 6 seconds duration.
another interesting thing plays fine if play in photos app of ipad after exporting using same videocomposition
. why freezes in avplayer
@ 6 seconds?
code:
avmutablecomposition *mutablecomposition = [avmutablecomposition composition]; avmutablecompositiontrack *videocompositiontrack = [mutablecomposition addmutabletrackwithmediatype:avmediatypevideo preferredtrackid:kcmpersistenttrackid_invalid]; avmutablecompositiontrack *audiocompositiontrack = [mutablecomposition addmutabletrackwithmediatype:avmediatypeaudio preferredtrackid:kcmpersistenttrackid_invalid]; (avurlasset *asset in assets) { avassettrack *assettrack; assettrack = [[asset trackswithmediatype:avmediatypevideo] objectatindex:0]; avassettrack *audioassettrack = [asset trackswithmediatype:avmediatypeaudio].firstobject; nserror *error; [videocompositiontrack inserttimerange:cmtimerangemake(kcmtimezero, assettrack.timerange.duration ) oftrack:assettrack attime:time error:&error]; if (error) { nslog(@"asset url :: %@",assettrack.asset); nslog(@"error1 - %@", error.debugdescription); } [audiocompositiontrack inserttimerange:cmtimerangemake(kcmtimezero, audioassettrack.timerange.duration) oftrack:audioassettrack attime:time error:&error]; if (error) { nslog(@"error2 - %@", error.debugdescription); } time = cmtimeadd(time, assettrack.timerange.duration); if (cgsizeequaltosize(size, cgsizezero)) { size = assettrack.naturalsize;; } } avmutablevideocompositioninstruction *maininstruction = [avmutablevideocompositioninstruction videocompositioninstruction]; avmutablevideocompositionlayerinstruction *videotracklayerinstruction = [avmutablevideocompositionlayerinstruction videocompositionlayerinstructionwithassettrack:videocompositiontrack]; maininstruction.timerange = cmtimerangemake(kcmtimezero, time); maininstruction.layerinstructions = [nsarray arraywithobjects:videotracklayerinstruction, nil]; avmutablevideocomposition *maincompositioninst = [avmutablevideocomposition videocomposition]; maincompositioninst.instructions = [nsarray arraywithobject:maininstruction]; maincompositioninst.frameduration = cmtimemake(1, 30); maincompositioninst.rendersize = size; pi = [avplayeritem playeritemwithasset:mutablecomposition]; pi.videocomposition = maincompositioninst;
also, know problem videocomposition
because if remove videocomposition
, plays fine on avplayer
.
update 1: found out when freezes after 6 seconds, if drag slider or forward(i.e. use seektotime
), starts playing again without further freeze.
also audio keeps on playing fine when video frozen.
update 2: if go ahead , export using avassetexportsession
same avmutablecomposition
, , load asset of exported video, works fine. when play avmutablecomposition
directly, problem arises.
finally, got solution fix this.
you should play after playeritem's status changed .readytoplay.
please see below.
func startvideoplayer() { let playeritem = avplayeritem(asset: self.composition!) playeritem.videocomposition = self.videocomposition! let player = avplayer(playeritem: playeritem) player.actionatitemend = .none videoplayerlayer = avplayerlayer(player: player) videoplayerlayer!.frame = self.bounds /* add playeritem's observer */ player.addobserver(self, forkeypath: "player.currentitem.status", options: .new, context: nil) nsnotificationcenter.defaultcenter().addobserver(self, selector: "playeritemdidreachend:", name: avplayeritemdidplaytoendtimenotification, object: playeritem); self.layer.addsublayer(videoplayerlayer!) } override func observevalueforkeypath(keypath: string?, ofobject object: anyobject?, change: [string : anyobject]?, context: unsafemutablepointer<void>) { if keypath != nil && keypath! == "player.currentitem.status" { if let newvalue = change?[nskeyvaluechangenewkey] { if avplayerstatus(rawvalue: newvalue as! int) == .readytoplay { playvideo() /* play after status changed .readytoplay */ } } } else { super.observevalueforkeypath(keypath, ofobject: object, change: change, context: context) } } func playeritemdidreachend(notification: nsnotification) { let playeritem = notification.object as! avplayeritem playeritem.seektotime(kcmtimezero) playvideo() } func playvideo() { videoplayerlayer?.player!.play() }
Comments
Post a Comment