如何检测AVPlayer
何时正在播放?调用play()
函数和实际播放视频之间似乎有一点延迟。
答案 0 :(得分:7)
视频:
AVPlayer
有一个名为rate (Float)
的参数,如果rate
大于0.0,则会显示当前播放的视频。
您可以查看rate
是否!=0
:(如果玩家倒退,费率可能为负数)
if vidPlayer != nil && vidPlayer.rate != 0 {
println("playing")
}
答案 1 :(得分:7)
据我所知,我同意你的看法,调用play()
功能和实际播放视频之间会有一点延迟(换句话说,视频的第一帧有时间)已被渲染)。延迟取决于一些标准,如视频类型(视频点播或直播),网络条件......但幸运的是,我们能够知道视频的第一帧渲染时,我的意思是视频实际播放的时间
通过观察当前status
的{{1}}以及AVPlayerItem
时,它应该是已渲染的第一帧。
AVPlayerItemStatusReadyToPlay
顺便说一下,还有另一种解决方案,我们会在[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL];
-(void)observeValueForKeyPath:(NSString*)path ofObject:(id)object change:(NSDictionary*)change context:(void*) context {
if([self.playerItem status] == AVPlayerStatusReadyToPlay){
NSLog(@"The video actually plays")
}
}
处看到readyForDisplay
状态,它还会指示视频呈现的时间。但是,该解决方案存在Apple文档中提到的缺点
AVPlayerLayer
以下是示例代码
/*!
@property readyForDisplay
@abstract Boolean indicating that the first video frame has been made ready for display for the current item of the associated AVPlayer.
@discusssion Use this property as an indicator of when best to show or animate-in an AVPlayerLayer into view.
An AVPlayerLayer may be displayed, or made visible, while this propoerty is NO, however the layer will not have any
user-visible content until the value becomes YES.
This property remains NO for an AVPlayer currentItem whose AVAsset contains no enabled video tracks.
*/
@property(nonatomic, readonly, getter=isReadyForDisplay) BOOL readyForDisplay;
但是,self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
[self.playerLayer addObserver:self forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:NULL];
-(void)observeValueForKeyPath:(NSString*)path ofObject:(id)object change:(NSDictionary*)change context:(void*) context {
if([self.playerLayer isReadyForDisplay]){
NSLog(@"Ready to display");
}
}
应该返回YES,但是,作为文档,它不能保证。
我希望这会有所帮助。
答案 2 :(得分:0)
快捷键4
方法1
var rateObserver: NSKeyValueObservation?
self.rateObserver = myPlayer.observe(\.rate, options: [.new, .old], changeHandler: { (player, change) in
if player.rate == 1 {
print("Playing")
}else{
print("Stop")
}
})
// Later You Can Remove Observer
self.rateObserver?.invalidate()
方法2
myPlayer.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions(rawValue: NSKeyValueObservingOptions.new.rawValue | NSKeyValueObservingOptions.old.rawValue), context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "rate" {
if player.rate == 1 {
print("Playing")
}else{
print("Stop")
}
}
}
答案 3 :(得分:0)
您可能要检测两件事:
AVPlayerLayer
的{{1}}是在接收到第一帧时。isReadyForDisplay
的{{1}}是视频实际开始播放的时间。要检查这两种状态,可以使用可观察性。
您将在类中定义三个对象:
AVPlayerItem
播放器实现将如下所示:
readyToPlay
这里,上下文是简单的整数或枚举。
您可以通过覆盖var player: AVPlayer?
var playerItem: AVPlayerItem?
var playerLayer: AVPlayerLayer?
方法来处理事件。
guard let videoURL = URL(string: "<videoPath>") else {
return
}
asset = AVAsset(url: videoURL)
guard let asset = asset else {
return
}
playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: requiredAssetKeys)
guard let playerItem = playerItem else {
return
}
playerItem.addObserver(self,
forKeyPath: #keyPath(AVPlayerItem.status),
options: [.old, .new],
context: &playerItemContext)
player = AVPlayer(playerItem: playerItem)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.addObserver(self,
forKeyPath: #keyPath(AVPlayerLayer.isReadyForDisplay),
options: [.old, .new],
context: &playerLayerContext)
avpController.player = player
avpController.view.frame.size.height = playerView.frame.size.height
avpController.view.frame.size.width = playerView.frame.size.width
playerView.addSubview(avpController.view)
avpController.player?.play()
别忘了删除观察者。
observeValue