2015-07-14 4 views
6

Я пытаюсь объединить несколько видеороликов, используя AVMutableComposition. Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я пытаюсь добавить любые AVMutableVideoComposition для применения каких-либо инструкций, мое воспроизведение замерзает в AVPlayer с точностью до 6 секунд.Странное поведение AVMutableComposition замораживание при использовании AVMutableVideoComposition

Еще одна интересная вещь, что она отлично работает, если я воспроизвожу ее в приложении «Фотографии» iPad после экспорта с использованием того же videoComposition. Так почему он замерзает в AVPlayer через 6 секунд?

Код:

AVMutableComposition *mutableComposition = [AVMutableComposition composition]; 

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

    AVMutableCompositionTrack *audioCompositionTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeAudio 
                         preferredTrackID:kCMPersistentTrackID_Invalid]; 

    for (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; 

Кроме того, я знаю, проблема в основном videoComposition, потому что если я удалить videoComposition, то он играет отлично на AVPlayer.

UPDATE 1: Я только что узнал, что, когда она замерзает через 6 секунд, если я перетащить ползунок назад или вперед (т.е. использовать seekToTime.), Он начинает играть снова нормально без какого-либо дальнейшего замораживания.

Также звук продолжает хорошо воспроизводиться, даже когда видео заморожено.

UPDATE 2: Если я просто идти вперед и экспортировать его, используя AVAssetExportSession с таким же AVMutableComposition и загрузка активов из экспортируемого видео, он отлично работает. Так что только когда я играю AVMutableComposition, проблема возникает.

+1

У меня была такая же проблема, любая удача? – naresh

+0

Снова; это все еще происходит. Может ПОЖАЛУЙСТА, кто-то здесь реагирует? –

+0

@Julian Не удалось решить это до сих пор. Закончилось урегулирование с экспортом, которое предполагает ожидание. Никакое внимание к проблеме после предлагать щедрот также. Следите за обновлениями и надейтесь, что кто-то это заметит. – blancos

ответ

0

Наконец-то я получил решение исправить это.

Вы должны играть после статуса игрока. Статус изменился на .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() 
}