2012-07-20 2 views
1

다음 문제가 있습니다. 나는 각각 다른 AVPlayerItem으로 초기화 된 두 개의 AVPlayers를 가지고있다. AVPlayerItem이 성공적으로로드되면 뷰 레이어에 AVPlayerLayer를 추가합니다. 아래 코드에서 알 수 있습니다.seekToTime이 두 AVPlayers의 동시 재생을 엉망으로 만듭니다.

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.playerItem = [[AVPlayerItem alloc] initWithURL:[self.video getVideoPath]]; 
    [self.playerItem addObserver:self forKeyPath:@"status" options:0 context:nil]; 
    [self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:0 context:nil]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(videoEnded) 
              name:AVPlayerItemDidPlayToEndTimeNotification 
              object:nil]; 


    self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem]; 

    self.overlayPlayerItem = [[AVPlayerItem alloc] initWithURL:[self.compareVideo getVideoPath]]; 

    [self.overlayPlayerItem addObserver:self forKeyPath:@"status" options:0 context:nil]; 
    [self.overlayPlayerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:0 context:nil]; 

    if (self.overlayPlayer==nil) { 
     self.overlayPlayer = [[AVPlayer alloc] initWithPlayerItem:self.overlayPlayerItem]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([object isKindOfClass:[AVPlayerItem class]]) 
    { 
     AVPlayerItem *item = (AVPlayerItem *)object; 
     //playerItem status value changed? 
    if ([keyPath isEqualToString:@"status"]) 
    { //yes->check it... 
     switch(item.status) 
     { 
      case AVPlayerItemStatusFailed: 
       NSLog(@"player item status failed"); 
       break; 
      case AVPlayerItemStatusReadyToPlay: 
      { 
       NSLog(@"player item status is ready to play"); 
       if (item == self.playerItem && !videoLayerAdded) { 
        videoLayerAdded = YES; 
        AVPlayerLayer* layer = [AVPlayerLayer playerLayerWithPlayer:player]; 
        layer.frame = self.videoContainer.bounds; 
        [self.videoContainer.layer insertSublayer:layer atIndex:0]; 
       } else if (item == self.overlayPlayerItem && !overlayLayerAdded){ 
        overlayLayerAdded = YES; 
        AVPlayerLayer* layer = [AVPlayerLayer playerLayerWithPlayer:overlayPlayer]; 
        layer.frame = self.videoOverlayContainer.bounds; 
        [self.videoOverlayContainer.layer insertSublayer:layer atIndex:0]; 
       } 
       break; 
      } 
      case AVPlayerItemStatusUnknown: 
       NSLog(@"player item status is unknown"); 
       break; 
     } 
    } 
    else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) 
    { 
     if (item.playbackBufferEmpty) 
     { 
      NSLog(@"player item playback buffer is empty"); 
     } 
    } 
} 
} 

재생 버튼을 누르면 동영상이 재생됩니다. 내가 다시 치면 멈추고, 지금까지는 그렇게 좋아.

- (IBAction)playButtonClicked:(id)sender{ 

    //is playing 
    if(self.player.rate>0.0 || self.overlayPlayer.rate>0.0){ 
     [self.player pause]; 
     [self.overlayPlayer pause]; 
    } else { 
     [self.player play]; 
     [self.overlayPlayer play]; 
    } 
} 

두 개의 UISlider를 통해 각 비디오를 앞뒤로 돌아갈 수 있습니다. seekToTime을 사용하여 비디오의 특정 시간으로 건너 뜁니다.

- (IBAction)sliderChanged:(id)sender{ 
    UISlider *slider = (UISlider *)sender; 

    //stop any video when using the slider 
    if(self.player.rate>0.0){ 
      [self.player pause]; 
    } 
    if(self.overlayPlayer.rate>0.0){ 
     [self.overlayPlayer pause]; 
    } 

    if (slider.tag == 1) { 
     double time = (self.playerTimeSlider.value * CMTimeGetSeconds(self.player.currentItem.asset.duration)); 
     [self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; 
    } else if (slider.tag == 2){ 
     double time = (self.overlayTimeSlider.value * CMTimeGetSeconds(self.overlayPlayer.currentItem.asset.duration)); 
     [self.overlayPlayer seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero]; 
    } 
} 

동영상 길이가 다를 수 있습니다. 그러나 비디오가 끝나면 다시 startToTime으로 설정합니다.

제 문제는 처음에 두 비디오를 모두 재생할 수 있다는 것입니다. 문제없이 일시 중지하고 다시 시작할 수 있습니다. 그러나 일단 동영상을 일시 중지하고 seekToTime을 사용하면 동영상이 다시 시작되거나 동영상이 끝나면 seekToTime으로 다시 설정하고 다시 재생됩니다. 내 상태 관찰자는 두 PlayerItem에 대해 AVPlayerItemStatusFailed를 실행합니다.

그런 다음 항목의 지속 시간은 0이됩니다. 그러나 PlayerItems가 0이 아닌지 확인했습니다.

나는 충돌하지 않지만 더 이상 비디오를 재생할 수 없습니다. 한 명만 사용하면 seekToTime으로 건너 뛰고 문제없이 동영상 끝 부분에서 다시 설정할 수 있습니다.

나는 포럼을 통해 읽고 사람들이 분명히 최대 4 개의 AVPlayers를 사용할 수 있다고 말했기 때문에 2로 저장해야한다고 생각합니다. 다른 앱에서도 비디오 렌더링 파이프 라인을 사용할 수 있다고 읽었지만, 내 iPad에 백그라운드에서 다른 앱이 없습니다.

이 기능이 나에게 도움이되지 않는 이유에 대한 도움이 필요하거나 수정 사항을 보내 주시면 대단히 감사하겠습니다.

는 업데이트 :

error: Error Domain=AVFoundationErrorDomain Code=-11819 "Cannot Complete Action" 
UserInfo=0x19e370 {NSLocalizedRecoverySuggestion=Try again later., 
NSLocalizedDescription=Cannot Complete Action} 

코드 AVErrorMediaServicesWereReset에 대한 -11819 약자 는 사실은 이제 AVPlayerItem 개체에서 오류를 기록. 그것은 저를 도울 누군가를 돕는가?

답변

2

이 긴 촬영을 할 수 있지만, 문서의 다음 페이지에서 살펴 수 있습니다 (전후) 제로의 허용 오차를 제공함으로써 당신은 아마 일으키는

AV Foundation Programming Guide - Seeking—Repositioning the Playhead

내 힌트가된다 디코더는 정확한 요청 프레임을 계산하는 키 프레임에서 벗어나지 않습니다.

동시에 두 항목을 재생할 때 함께 사용하면 iOS 내부 미디어 서비스에 할당 된 리소스가 고갈 될 수 있습니다. 따라서 리셋이 발생합니다. 재생되는 비디오의 품질 및 형식이 가장 중요하다는 사실이 여러 가지 요소에 달려 있다고 생각합니다.

스크러빙에서 정확한 시간 제어가 필요하지 않은 경우 (!) 공차로 재생 해보십시오. 최대 키 프레임 간격보다 약간 큰 값으로 시도해 보는 것이 좋습니다.

그 값 (최대 키 프레임 간격)은 대부분 영화에 따라 다릅니다.

영화를 제어하고 정신 나간 영화 파일 크기로 살 수있는 경우 최대 키 프레임 간격을 1 (!)로 설정하여 내보내고 회전을 시도하십시오.

+0

아주 좋은 답변입니다! 감사. – MonsieurDart

관련 문제