답변:
항목 끝에 도달하기위한 알림을 받으려면 ( 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];
}];
-replaceCurrentItemWithPlayerItem:
하고 제대로 처리하지 않으면 알림이 문제를 일으킬 수 있습니다 . 나에게 더 안정적인 방법은 AVPlayer
KVO를 사용하여의 상태 를 추적 하는 것입니다. 자세한 내용은 아래 내 대답을 참조하십시오. stackoverflow.com/a/34321993/3160561
AVPlayerItemFailedToPlayToEndTimeNotification
다음을 사용하여 재생 중인지 알 수 있습니다.
AVPlayer *player = ...
if ((player.rate != 0) && (player.error == nil)) {
// player is playing
}
Swift 3 확장 :
extension AVPlayer {
var isPlaying: Bool {
return rate != 0 && error == nil
}
}
- [AVPlayer setRate:-1.0]
) 때문에, -1.0
덜 0보다
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 == currentTime
와 rate != 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;
AVPlayerItemFailedToPlayToEndTimeNotification
. 이 오류가 발생하면 종료 시간에 도달하지 않습니다. 또는 maz의 답변을 읽고 코드에 확인을 추가하십시오 player.error != nil
.이 경우 오류로 인해 재생이 "종료되었습니다".
AVPlayerItemDidPlayToEndTimeNotification
입니까?
대한 스위프트 :
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
}
}
player.rate = -1.0
) 이하 0보다이기 때문에 -1.0,
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 감사합니다!
nil
마세요. 작동합니다 – 내 플레이어는 그랬습니다 ! 하지만 뷰가 언제 시작되는지 알아야합니다 (끝이 아님). 그렇게 할 방법이 있습니까?
답은 목표 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