2015-07-14 6 views
6

Sto cercando di unire più video utilizzando AVMutableComposition. Il problema che devo affrontare è che ogni volta che provo ad aggiungere qualsiasi AVMutableVideoComposition per applicare le istruzioni, la mia riproduzione si blocca in AVPlayer alla durata esatta di 6 secondi.Comportamento strano del congelamento di AVMutableComposition durante l'utilizzo di AVMutableVideoComposition

Un'altra cosa interessante è che funziona bene se lo riproduco nell'app Foto di iPad dopo l'esportazione utilizzando lo stesso videoComposition. Quindi perché si blocca in AVPlayer in 6 secondi?

Codice:

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; 

Inoltre, so problema è in gran parte videoComposition perché se mi tolgo la videoComposition, poi gioca bene su AVPlayer.

UPDATE 1: Ho appena scoperto che quando si blocca dopo 6 secondi, se mi trascina il cursore avanti o indietro (cioè utilizzare seekToTime.), Inizia a giocare di nuovo normalmente senza ulteriori congelamento.

Anche l'audio continua a suonare bene anche quando il video è congelato.

UPDATE 2: Se mi basta andare avanti e l'esportazione utilizzando AVAssetExportSession con lo stesso AVMutableComposition, e il carico di asset da dei video esportato, funziona benissimo. Quindi è proprio quando gioco direttamente a AVMutableComposition, il problema sorge.

+1

Ho avuto lo stesso problema, un po 'di fortuna? – naresh

+0

Ancora; questo succede ancora. PER FAVORE qualcuno può reagire qui? –

+0

@ Julian Non sono in grado di risolverlo fino ad ora. Finito per stabilirsi con l'esportazione che comporta l'attesa. Nessuna attenzione al problema dopo aver offerto anche la taglia. Continua a svendere e spera che qualcuno lo noti alla fine. – blancos

risposta

0

Infine, ho trovato la soluzione per risolvere questo problema.

Si dovrebbe giocare dopo che lo stato di playerItem è cambiato in .ReadyToPlay.

Si prega di vedere come di seguito.

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() 
}  
Problemi correlati