[ios] AVPlayer의 재생 상태 확인

AVPlayer재생이 중단 되었는지 또는 끝에 도달 했는지 알 수있는 방법이 있습니까?



답변

항목 끝에 도달하기위한 알림을 받으려면 ( Apple을 통해 ) :

[[NSNotificationCenter defaultCenter]
      addObserver:<self>
      selector:@selector(<#The selector name#>)
      name:AVPlayerItemDidPlayToEndTimeNotification
      object:<#A player item#>];

재생을 추적하려면 다음을 수행 할 수 있습니다.

사용하여 “트랙은 AVPlayer를 오브젝트의 재생 헤드의 위치 변화” 큐 : addPeriodicTimeObserverForInterval usingBlock : 또는 addBoundaryTimeObserverForTimes : 큐 : usingBlock : .

Apple의 예 :

// Assume a property: @property (retain) id playerObserver;

Float64 durationSeconds = CMTimeGetSeconds([<#An asset#> duration]);
CMTime firstThird = CMTimeMakeWithSeconds(durationSeconds/3.0, 1);
CMTime secondThird = CMTimeMakeWithSeconds(durationSeconds*2.0/3.0, 1);
NSArray *times = [NSArray arrayWithObjects:[NSValue valueWithCMTime:firstThird], [NSValue valueWithCMTime:secondThird], nil];

self.playerObserver = [<#A player#> addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
    // Passing NULL for the queue specifies the main queue.

    NSString *timeDescription = (NSString *)CMTimeCopyDescription(NULL, [self.player currentTime]);
    NSLog(@"Passed a boundary at %@", timeDescription);
    [timeDescription release];
}];


답변

다음을 사용하여 재생 중인지 알 수 있습니다.

AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
    // player is playing
}

Swift 3 확장 :

extension AVPlayer {
    var isPlaying: Bool {
        return rate != 0 && error == nil
    }
}


답변

iOS10에는 현재이를위한 속성이 내장되어 있습니다 : timeControlStatus

예를 들어,이 함수는 상태에 따라 avPlayer를 재생하거나 일시 중지하고 재생 / 일시 중지 버튼을 적절하게 업데이트합니다.

@IBAction func btnPlayPauseTap(_ sender: Any) {
    if aPlayer.timeControlStatus == .playing {
        aPlayer.pause()
        btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
    } else if aPlayer.timeControlStatus == .paused {
        aPlayer.play()
        btnPlay.setImage(UIImage(named: "control-pause"), for: .normal)
    }
}

두 번째 질문은 avPlayer가 끝났는지 알기 위해 가장 쉬운 방법은 알림을 설정하는 것입니다.

NotificationCenter.default.addObserver(self, selector: #selector(self.didPlayToEnd), name: .AVPlayerItemDidPlayToEndTime, object: nil)

예를 들어 동영상이 끝날 때 동영상의 시작 부분으로 되 감고 일시 중지 버튼을 재생으로 재설정 할 수 있습니다.

@objc func didPlayToEnd() {
    aPlayer.seek(to: CMTimeMakeWithSeconds(0, 1))
    btnPlay.setImage(UIImage(named: "control-play"), for: .normal)
}

이러한 예제는 자체 컨트롤을 만드는 경우 유용하지만 AVPlayerViewController를 사용하는 경우 컨트롤이 기본 제공됩니다.


답변

rate비디오가 재생 중인지 확인하는 방법 이 아닙니다 (멈출 수 있음). 문서에서 :rate

원하는 재생 속도를 나타냅니다. 0.0은 “일시 중지됨”을 의미하고 1.0은 현재 항목의 자연스러운 속도로 재생하려는 욕구를 나타냅니다.

키워드 “재생 욕구”- 비율이 1.0동영상이 재생되고 있음을 의미하지는 않습니다.

iOS 10.0 이후의 해결책은 속성에서 AVPlayerTimeControlStatus관찰 할 수있는 것을 사용 하는 것 AVPlayer timeControlStatus입니다.

iOS 10.0 (9.0, 8.0 등) 이전의 솔루션은 자체 솔루션을 롤링하는 것입니다. 비율은 0.0비디오가 일시 중지되었음을 의미합니다. 시 rate != 0.0는 비디오 중 하나를 재생을 의미 하거나 정지되었습니다.

다음을 통해 플레이어 시간을 관찰하여 차이를 확인할 수 있습니다. func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any

블록은에서 현재 플레이어 시간을 반환 CMTime하므로 lastTime(블록에서 마지막으로 수신 currentTime한 시간 )과 (블록이 방금보고 한 시간)을 비교하면 플레이어가 플레이 중인지 정지되었는지 여부를 알 수 있습니다. 예를 들어, 경우 lastTime == currentTimerate != 0.0다음 플레이어는 정체하고있다.

다른 사람들이 언급했듯이 재생이 완료되었는지 확인하는 것은로 표시됩니다 AVPlayerItemDidPlayToEndTimeNotification.


답변

보다 신뢰할 수있는 대안 NSNotification은 자신을 플레이어의 rate재산에 관찰자로 추가하는 것 입니다.

[self.player addObserver:self
              forKeyPath:@"rate"
                 options:NSKeyValueObservingOptionNew
                 context:NULL];

그런 다음 관찰 된 속도의 새 값이 0인지 확인합니다. 즉, 빈 버퍼로 인해 종료 또는 중단과 같은 어떤 이유로 재생이 중지되었음을 의미합니다.

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSString *,id> *)change
                       context:(void *)context {
    if ([keyPath isEqualToString:@"rate"]) {
        float rate = [change[NSKeyValueChangeNewKey] floatValue];
        if (rate == 0.0) {
            // Playback stopped
        } else if (rate == 1.0) {
            // Normal playback
        } else if (rate == -1.0) {
            // Reverse playback
        }
    }
}

예를 들어 rate == 0.0, 재생이 중지 된 원인을 정확히 알기 위해 다음을 확인할 수 있습니다.

if (self.player.error != nil) {
    // Playback failed
}
if (CMTimeGetSeconds(self.player.currentTime) >=
    CMTimeGetSeconds(self.player.currentItem.duration)) {
    // Playback reached end
} else if (!self.player.currentItem.playbackLikelyToKeepUp) {
    // Not ready to play, wait until enough data is loaded
}

그리고 플레이어가 끝에 도달하면 중지하는 것을 잊지 마십시오.

self.player.actionAtItemEnd = AVPlayerActionAtItemEndPause;


답변

대한 스위프트 :

AVPlayer :

let player = AVPlayer(URL: NSURL(string: "http://www.sample.com/movie.mov"))
if (player.rate != 0 && player.error == nil) {
   println("playing")
}

업데이트 : 비디오가 반대로 재생되면 Julian 이 지적한 덕분에 부정적 일 수 있기 때문에
player.rate > 0조건이 변경되었습니다 . 참고 : 이것은 위 (Maz의) 대답과 동일하게 보일 수 있지만 Swift에서 ‘! player.error’는 나에게 컴파일러 오류를 제공하므로 Swift에서 ‘player.error == nil’을 사용하여 오류를 확인해야합니다. (오류 속성 때문에 ‘Bool’유형이 아님)player.rate != 0

AVAudioPlayer :

if let theAudioPlayer =  appDelegate.audioPlayer {
   if (theAudioPlayer.playing) {
       // playing
   }
}

AVQueuePlayer :

if let theAudioQueuePlayer =  appDelegate.audioPlayerQueue {
   if (theAudioQueuePlayer.rate != 0 && theAudioQueuePlayer.error == nil) {
       // playing
   }
}


답변

maz의 답변을 기반으로 한 신속한 확장

extension AVPlayer {

    var isPlaying: Bool {
        return ((rate != 0) && (error == nil))
    }
}