web-dev-qa-db-ja.com

AVPlayerの再生状態を確認する

AVPlayer再生が停止したか、最後に到達したかどうかを知る方法はありますか?

100
Egil

アイテムの最後に到達したことを通知する( Apple 経由):

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

再生を追跡するには、次のことができます。

addPeriodicTimeObserverForInterval:queue:usingBlock:またはを使用して、「AVPlayerオブジェクトの再生ヘッドの位置の変更を追跡する」 addBoundaryTimeObserverForTimes:queue:usingBlock:

例はアップルのものです:

// 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];
}];
57
Todd Hopkinson

あなたはそれを使って遊んでいると言うことができます:

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

Swift 3拡張機能:

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

IOS10には、このためのビルトインプロパティがあります:timeControlStatus

たとえば、この関数は、ステータスに基づいてavPlayerを再生または一時停止し、再生/一時停止ボタンを適切に更新します。

@IBAction func btnPlayTap(_ 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)
    }
}

2番目の質問については、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を使用する場合は、コントロールが組み込まれています。

37
Travis M.

rateNOT動画が再生中かどうかを確認する方法です(停止する可能性があります)。 rateのドキュメントから:

希望する再生速度を示します。 0.0は「一時停止」を意味し、1.0は現在のアイテムの自然な速度でプレイしたいという欲求を示します。

キーワード「再生したい」-1.0のレートは、ビデオが再生されているという意味ではありません。

IOS 10.0以降の解決策は、AVPlayerTimeControlStatusAVPlayerプロパティで確認できる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で示されます。

20
kgaidis

NSNotificationのより信頼性の高い代替手段は、プレイヤーのrateプロパティにオブザーバーとして自分自身を追加することです。

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

次に、観測レートの新しい値がゼロであるかどうかを確認します。これは、最後に到達したか、空のバッファーが原因でストールするなど、何らかの理由で再生が停止したことを意味します。

- (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;

18
maxkonovalov

Swiftの場合:

AVPlayer

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に変更されました。ビデオが逆方向に再生される場合、Julianのおかげで負になる可能性があるためです。指摘するため。
:これは上記の(Mazの)回答と同じように見えるかもしれませんが、Swift '!player.error'でコンパイラエラーが発生したため、確認する必要がありますSwiftで 'player.error == nil'を使用したエラーの場合(エラープロパティは 'Bool'タイプではないため)

AVAudioPlayer:

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

AVQueuePlayer:

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

Mazの回答に基づいたSwift拡張

extension AVPlayer {

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

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!

5
Mr Stanev

現在、Swift 5では、プレーヤーが再生中か一時停止中かを確認する最も簡単な方法は、。timeControlStatus変数を確認することです。

player.timeControlStatus == .paused
player.timeControlStatus == .playing
2
azemi

回答はObjective 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
}
0
iOS Lifee