Ios 使用AVMutableVideoComposition时AVMutableComposition冻结的奇怪行为

Ios 使用AVMutableVideoComposition时AVMutableComposition冻结的奇怪行为,ios,objective-c,video,avfoundation,avmutablecomposition,Ios,Objective C,Video,Avfoundation,Avmutablecomposition,我正在尝试使用AVMutableComposition合并多个视频。我面临的问题是,每当我尝试添加任何AVMutableVideoComposition以应用任何指令时,我的播放都会在AVPlayer中以精确的6秒时间冻结 另一件有趣的事情是,如果我使用相同的videoComposition导出后在iPad的Photos应用程序中播放它,它会播放得很好。那么为什么它会在AVPlayer中冻结6秒 代码: 另外,我知道问题主要是videoComposition,因为如果我删除videoCompos

我正在尝试使用
AVMutableComposition
合并多个视频。我面临的问题是,每当我尝试添加任何
AVMutableVideoComposition
以应用任何指令时,我的播放都会在
AVPlayer
中以精确的6秒时间冻结

另一件有趣的事情是,如果我使用相同的
videoComposition
导出后在iPad的Photos应用程序中播放它,它会播放得很好。那么为什么它会在
AVPlayer
中冻结6秒

代码:

另外,我知道问题主要是
videoComposition
,因为如果我删除
videoComposition
,那么它在
AVPlayer
上播放得很好

更新1:我刚刚发现,当它在6秒后冻结时,如果我将滑块向后或向前拖动(即使用
seekToTime
),它将再次正常播放,而不再冻结

此外,即使视频冻结,音频仍能正常播放


更新2:如果我继续使用
AVAssetExportSession
以相同的
AVMutableComposition
导出它,并从导出的视频中加载资源,它工作正常。所以,当我直接播放
AVMutableComposition
时,问题就出现了。

最后,我找到了解决方法

您应该在playerItem的状态更改为.ReadyToPlay后播放

请参阅下文

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 is changed to .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()
}       
func startVideoPlayer(){
让playerItem=AVPlayerItem(资产:self.composition!)
playerItem.videoComposition=self.videoComposition!
let player=AVPlayer(playerItem:playerItem)
player.actionAtItemEnd=.None
videoPlayerLayer=AVPlayerLayer(播放器:播放器)
videoPlayerLayer!.frame=self.bounds
/*添加playerItem的观察者*/
player.addObserver(self,forKeyPath:“player.currentItem.status”,选项:。新建,上下文:nil)
NSNotificationCenter.defaultCenter().addObserver(self,选择器:“PlayerItemDidReachen:”,名称:AVPlayerItemDidPlayToEndTimeNotification,对象:playerItem);
self.layer.addSublayer(videoPlayerLayer!)
}
重写func observeValueForKeyPath(键路径:String?,对象对象的类型:AnyObject?,更改:[String:AnyObject]?,上下文:UnsafeMutablePointer){
如果keyPath!=nil&&keyPath!==“player.currentItem.status”{
如果让newValue=更改?[NSKeyValueChangeNewKey]{
如果AVPlayerStatus(rawValue:newValue as!Int)=.ReadyToPlay{
playVideo()/*状态更改为.ReadyToPlay后播放*/
}
}
}否则{
super.observeValueForKeyPath(键路径,of对象:object,change:change,context:context)
}
}    
func PlayerItemDidReachen(通知:NSNotification){
让playerItem=notification.object为!AVPlayerItem
playerItem.seekToTime(kCMTimeZero)
播放视频()
} 
func播放视频(){
videoPlayerLayer?.player!.play()
}       

我也有同样的问题,运气好吗?又一次;这种情况仍然存在。有人能在这里做出反应吗?@朱利安目前还不能解决这个问题。最终解决了出口问题,这需要等待。在提供赏金后也不注意这个问题。继续投票,希望最终有人注意到。@Julian请检查我的答案。我刚刚解决了这个问题,就像30分钟前一样,谢谢你。实际上我有一个不同的问题。我为资产轨道而不是合成轨道创建了说明。。。愚蠢的一个,但我还是花了3个星期才找到正确的组合
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 is changed to .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()
}