2017-09-08 4 views
0

こんにちは私はローカルビデオストリーミングを含むアプリケーションで作業しています。ユーザーが一時停止状態でスクラブしているときにコールバックまたは通知を探しています。私は次のようにすでにAVPlayerのためのオブザーバーを追加しました:AVPlayerを認識する方法は一時停止状態であり、ユーザーはスクラブを行っています

[self.avPlayerController.player addObserver:self forKeyPath:@"status" options:0 context:NULL]; 
[self.avPlayerController.player addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionOld context:NULL]; 

しかし、プレーヤーが一時停止し、ユーザースクラビングされたときにオブザーバーは呼び出されません。私はちょうどユーザーがスクラブを終了したとき、またはユーザーが進行状況バーに触れるときを検出したい。どんな助けもありがとう。ありがとう。

答えて

1

観察するとratestatusがうまくいくはずです - 観測コールバックは私のコードで呼び出されるので、私もあなたのために働くと思います。私は問題は、ビデオが一時停止しているときにだけ呼び出され、ユーザーがそれをスクラブしたときではないということです。だから私はそれに答えます。

おそらく観察したいことはcurrentTimeとなります。私は自分で試してみましたが、AVPlayerまたはそのcurrentItemを観察しようとすると、KVOは呼び出されません。私は少しの研究をしましたが、これは単純に機能しません(this SO question参照)。あなたはそれを行う別の方法を見つける必要があります。 1つの方法は、タイマーを追加し、タイマーの状態を定期的にチェックすることです。 rateまたはtimeControlStatussee this answer)を見ると組み合わせると、ビデオが一時停止していても、currentTimeがユーザーによって変更されていることがわかります。

私はあなたがスウィフトコードを読んで気にしない、これは最初のアプローチになります願っています:

class ViewController: UIViewController { 

    let player = AVPlayerViewController() 
    var timer: Timer? = nil 
    var previousTime: Double = 0 
    var stopped = false 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 

     present(player, animated: true, completion: { 
      self.player.player = AVPlayer(url: URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")!) 
      self.player.player?.play() 
      self.player.player?.addObserver(self, forKeyPath: "rate", options: .new, context: nil) 
      self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { (timer) in 
       let currentTime = self.player.player?.currentTime().seconds ?? 0 
       if self.previousTime != currentTime && self.stopped { 
        print(">>> User scrubbing") 
       } 
       self.previousTime = currentTime 
      }) 
     }) 
    } 

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
     if keyPath == "rate" && (change?[NSKeyValueChangeKey.newKey] as? Float) == 0 { 
      print(">>> stopped") 
      stopped = true 
     } else if keyPath == "rate" && (change?[NSKeyValueChangeKey.newKey] as? Float) == 1 { 
      print(">>> played again") 
      stopped = false 
     } 
    } 
} 

第二のアプローチ、私が好む1、AVPlayerをサブクラス化し、そのseek(to:toleranceBefore:toleranceAfter:completionHandler:)メソッドをオーバーライドしています。このメソッドは、ユーザーがビデオをスクラブするときにAVPlayerViewControllerによって呼び出されます。この時点で、ユーザーがスクラビングしていることがわかります(ビデオの再生中にユーザーがスクラブしたときにも呼び出されますが、演奏)。

class CustomAVPlayer: AVPlayer { 
    override func seek(to time: CMTime, toleranceBefore: CMTime, toleranceAfter: CMTime, completionHandler: @escaping (Bool) -> Void) { 
     super.seek(to: time, toleranceBefore: toleranceBefore, toleranceAfter: toleranceAfter, completionHandler: completionHandler) 

     // if you don't call this method directly, it's called only by the 
     // AVPlayerViewController's slider during scrubbing 
     print(">> user scrubbing") 
    } 
} 
+0

私は本当に助けてくれた2番目のアプローチを使用しました。 –

+0

ユーザーが2番目の方法でスクラビングを停止したときに表示されます。 –

+0

私が恐れているのは、ユーザーがスライダに触れていることを検出したいのであって、彼女がそれを動かすのではなく、私が示唆したアプローチのいずれによっても可能ではないということです。どちらも現在の時間を変更することに頼っていますが、ユーザがスライダに触れながらスライダに触れてもスライダに触れないようにしている場合、ユーザがスライダを再び動かすまで、seekメソッドは再び呼び出されません。 –

関連する問題