Reputation: 2280
I am able to successfully create a player but was annoyed with the initial black screen. I decided to overlay a UIImageView and hide it once the player started. This worked, but I didn't want the hassle of creating and maintaining images for all my videos.
I was able to achieve the exact results I wanted by playing and immediately pausing the player after instantiating it. The only issue was that sometimes the state of the player was getting recorded incorrectly, so when I went to start the player again, the status was listed as already "playing" even though the player was paused.
I starting looking into using AVPlayerItem seekToTime but haven't found any feasible solutions. Is there a "non hacky" way of achieving this?
Upvotes: 15
Views: 3877
Reputation: 42459
If you're using an AVPlayerViewController
, this is a perfect use of the player controller's contentOverlayView
property. This is a UIView
between the player layer and the controls exposed exactly for this purpose:
First, create the screenshot:
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
}
Now, add the image as a subview of the contentOverlayView
in the player controller:
// 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
}
Then, remove the imageView
subview when the player starts playing the asset, or when buffering completes.
Upvotes: 11
Reputation: 2737
The AVPlayerLayer associated with your player has a readyForDisplay property.
You can try to make your host view an observer for this value, and do a refresh as soon as it is set to true.
It is set to true when the first frame is ready to be rendered, so before the player has enough data to play and set its status to readyToPlay.
Upvotes: 3