AVPlayer의 재생 상태 확인


답변:


57

항목 끝에 도달하기위한 알림을 받으려면 ( 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];
}];

부울 플래그를 던져 플레이 상태를 확인할 수 있습니다.
moonman239

예를 들어를 사용하여 플레이어의 항목을 변경 -replaceCurrentItemWithPlayerItem:하고 제대로 처리하지 않으면 알림이 문제를 일으킬 수 있습니다 . 나에게 더 안정적인 방법은 AVPlayerKVO를 사용하여의 상태 를 추적 하는 것입니다. 자세한 내용은 아래 내 대답을 참조하십시오. stackoverflow.com/a/34321993/3160561
maxkonovalov

2
오류 알림도 필요하십니까? AVPlayerItemFailedToPlayToEndTimeNotification
ToolmakerSteve

332

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

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

Swift 3 확장 :

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

29
반드시 그런 것은 아니지만 파일 오류로 인해 플레이어가 멈춘 상황을 처리하지 않습니다. 내가 어려운 길을 알아 낸 것 ...
Dermot

7
Dermot가 말했듯이 비행기 모드에서 무언가를 시도하면 AVPlayer 속도는 여전히 1.0으로 설정됩니다. 이는 재생 의도를 의미하기 때문입니다.
phi

4
AVPlayer를 그냥하지 전무뿐만 아니라 속도를 확인하는 것이 : 0이 아닌 것을 확인, 오류 속성이 있습니다
제임스 캠벨

23
@Dermot 시나리오를 방지하기 위해 답변이 업데이트되었습니다. 그래서 이것은 실제로 작동합니다.
jomafer 2015-06-03

2
역 (비디오 영상을 재생할 때 작동하지 않음 - [AVPlayer setRate:-1.0]) 때문에, -1.0덜 0보다
줄리안 F. Weinert

49

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를 사용하는 경우 컨트롤이 기본 제공됩니다.


iOS 10 이상에서 사용하기 쉬움
technerd

2
@objc FUNC didPlayToEnd () 스위프트 4.2
숀 Stayns

21

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.


18

보다 신뢰할 수있는 대안 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;


끝까지 도달하지 못했다는 알림도 필요하다고 생각합니다 AVPlayerItemFailedToPlayToEndTimeNotification. 이 오류가 발생하면 종료 시간에 도달하지 않습니다. 또는 maz의 답변을 읽고 코드에 확인을 추가하십시오 player.error != nil.이 경우 오류로 인해 재생이 "종료되었습니다".
ToolmakerSteve

BTW, NSNotification 사용에 대해 "신뢰할 수 없음"을 발견 한 것은 무엇 AVPlayerItemDidPlayToEndTimeNotification입니까?
ToolmakerSteve

ToolmakerSteve, 귀하의 메모에 감사 드리며 제 답변에 오류 검사를 추가했습니다. 신뢰할 수없는 알림-컬렉션보기에서 반복적이고 재사용 가능한 플레이어보기를 구현하는 동안 직접 문제를 발견했으며 KVO는 서로 다른 플레이어의 알림이 서로 간섭하지 않고 모든 것을 더 로컬로 유지할 수있게했기 때문에 상황을 더 명확하게했습니다.
maxkonovalov

17

대한 스위프트 :

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
   }
}

2
AVPlayer! = AVAudioPlayer
quemeful

2
주의 사항 : 위에서 언급 한 모든 것은이 질문보다 2 년 전에 나타난 답변입니다.
Dan Rosenstark

1
@Yar 나는 또한 위의 답변을 upvoted 알고 있지만 이것은 신속하고 Swift에서는 '! player.error'가 나를 위해 작동하지 않았으므로 bool 유형에만 허용되므로 답변을 추가했습니다. 죄송합니다. 이 스택 오버플로 앱 :)
Aks

내 우려는 player.error가 실제로 얼마나 잘 작동하는지 모르겠다는 것입니다.
Dan Rosenstark

1
역 (비디오 영상을 재생할 때 작동하지 않음 player.rate = -1.0) 이하 0보다이기 때문에 -1.0,
줄리안 F. Weinert

9

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

extension AVPlayer {

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

6

maxkonovalov의 답변의 Swift 버전은 다음과 같습니다.

player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.New, context: nil)

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == "rate" {
        if let rate = change?[NSKeyValueChangeNewKey] as? Float {
            if rate == 0.0 {
                print("playback stopped")
            }
            if rate == 1.0 {
                print("normal playback")
            }
            if rate == -1.0 {
                print("reverse playback")
            }
        }
    }
}

maxkonovalov 감사합니다!


안녕하세요 Mr Stanev, 답변 주셔서 감사합니다. 이것은 나를 위해 작동하지 않습니다 (일명 콘솔에 아무것도 인쇄하지 않습니까?)
Cesare

신경 쓰지 nil마세요. 작동합니다 – 내 플레이어는 그랬습니다 ! 하지만 뷰가 언제 시작되는지 알아야합니다 (끝이 아님). 그렇게 할 방법이 있습니까?
Cesare

3

현재 swift 5에서 플레이어가 재생 중인지 또는 일시 중지되었는지 확인하는 가장 쉬운 방법은 .timeControlStatus 변수 를 확인하는 입니다.

player.timeControlStatus == .paused
player.timeControlStatus == .playing

1

답은 목표 C입니다.

if (player.timeControlStatus == AVPlayerTimeControlStatusPlaying) {
    //player is playing
}
else if (player.timeControlStatus == AVPlayerTimeControlStatusPaused) {
    //player is pause
}
else if (player.timeControlStatus == AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate) {
    //player is waiting to play
}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.