programing

AVP Player의 재생 상태 확인

topblog 2023. 6. 2. 20:03
반응형

AVP Player의 재생 상태 확인

그들이 그들을 죽었는지 아닌지 알 수 있는 방법이 있습니까?AVPlayer재생이 지연되었거나 끝에 도달했습니까?

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

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

스위프트 3 확장:

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

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

예를 들어 이 기능은 상태에 따라 vPlayer를 재생하거나 일시 중지하고 재생/일시 중지 버튼을 적절하게 업데이트합니다.

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

두 번째 질문과 관련하여, vPlayer가 끝에 도달했는지 확인하려면 알림을 설정하는 것이 가장 쉽습니다.

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

Apple을 통해 항목의 끝에 도달하는 알림을 받는 방법

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

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

addPeriodicTimeObserverForInterval:queue:usingBlock: 또는 addBoundaryTimeObserverForTimes:queue:usingBlock:를 사용하여 "AVPlayer 객체에서 플레이헤드 위치 변경 추적".

예는 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];
}];

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

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

키워드 "재생 욕구" - 속도가 비디오가 재생 중임을 의미하지는 않습니다.

이후의 은 iOS 10.0을 사용하는 입니다.AVPlayerTimeControlStatus은 서관찰수있에서 관찰할 수 .AVPlayer timeControlStatus소유물.

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

통해 를 알 수 .func addPeriodicTimeObserver(forInterval interval: CMTime, queue: DispatchQueue?, using block: @escaping (CMTime) -> Void) -> Any

은 현재 을 록은현플시반환다니로 합니다.CMTime 그서비면자의 .lastTime) 및 (블록에서 수신한 시간) 및currentTime(블록이 방금 보고한 시간) 플레이어가 재생 중인지 또는 정지 상태인지 알 수 있습니다.를 들어, 만약에 들어만, 약를.lastTime == currentTime그리고.rate != 0.0그러면 플레이어가 정지합니다.

은 다른사지바와같이한, 끝여확부다것인다표니같시로 표시됩니다.AVPlayerItemDidPlayToEndTimeNotification.

Swift의 경우:

AV Player:

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

업데이트:
player.rate > 0상태가 로 변경됨player.rate != 0왜냐하면 비디오가 반대로 재생되면 줄리안이 지적해준 덕분에 부정적일 수 있기 때문입니다.
참고: 위 (Maz) 답변과 동일하게 보일 수 있지만 Swift에서 '!player.error'는 컴파일러 오류를 제공하므로 Swift에서 'player.error == nil'을 사용하여 오류를 확인해야 합니다. (오류 속성이 'Boole' 유형이 아니기 때문에)

AV 오디오 플레이어:

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

AVQuePlayer:

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

보다 안정적인 대안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.0case, 정확히 무엇이 재생을 중지하게 했는지 알기 위해 다음과 같은 검사를 수행할 수 있습니다.

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;

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

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

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

extension AVPlayer {

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

Maxkonov의 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!

목표 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
}
player.timeControlStatus == AVPlayer.TimeControlStatus.playing

플레이어가 다음과 같은 타이머로 재생 중인지 확인할 수 있습니다.

let playerObserver = self.player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main, using: { [weak self] time in
        if self?.player.timeControlStatus == .playing {
            debugPrint("#player - info: isPlaying")
            self?.playButton.isSelected = true
        } else if self?.player.timeControlStatus == .paused {
            debugPrint("#player - info: isPaused")
            self?.playButton.isSelected = false
        } else if self?.player.timeControlStatus == .waitingToPlayAtSpecifiedRate {
            debugPrint("#player - info: isWaiting") //Buffering
        }
    })

언급URL : https://stackoverflow.com/questions/5655864/check-play-state-of-avplayer

반응형