我能够成功创建一个播放器,但对最初的黑屏感到恼火。我决定覆盖UIImageView并在播放器启动后隐藏它。这很有用,但我不想为我的所有视频创建和维护图像的麻烦。
我能够通过播放获得我想要的确切结果,并在实例化后立即暂停播放器。唯一的问题是,有时玩家的状态记录不正确,所以当我再次启动玩家时,状态被列为已经“正在播放”,即使播放器已暂停。
我开始考虑使用 AVPlayerItem seekToTime 但尚未找到任何可行的解决方案。是否有“非hacky”方式实现这一目标?
答案 0 :(得分:8)
如果您使用的是AVPlayerViewController
,则可以完美地使用播放器控制器的contentOverlayView
属性。这是播放器层和为此目的而公开的控件之间的UIView
:
首先,创建屏幕截图:
let asset = AVAsset(URL: URL(string: "")!) // link to some video
let imageGenerator = AVAssetImageGenerator(asset: asset)
let screenshotTime = CMTime(seconds: 1, preferredTimescale: 1)
if let imageRef = try? imageGenerator.copyCGImageAtTime(screenshotTime, actualTime: nil) {
let image = UIImage(CGImage: imageRef)
// see part 2 below
}
现在,将图像添加为播放器控制器中contentOverlayView
的子视图:
// in the same try block
let imageView = UIImageView(image: image)
let playerVC = AVPlayerViewController()
let playerItem = AVPlayerItem(asset: asset)
playerVC.player = AVPlayer(playerItem: playerItem)
self.presentViewController(playerVC, animated: true) {
playerVC.contentOverlayView?.addSubview(imageView)
// adjust the frame of your imageView to fit on the player controller's contentOverlayView
}
然后,当玩家开始播放资产或缓冲完成时,移除imageView
子视图。
答案 1 :(得分:2)
与您的播放器关联的AVPlayerLayer具有readyForDisplay属性。
您可以尝试让主机查看此值的观察者,并在设置为true后立即进行刷新。
第一帧准备好渲染时设置为true,因此在播放器有足够的数据播放并将其状态设置为readyToPlay之前。