5

Every time, when I try to playing a megabyte video using AVPlayer, it initially shows a white screen for a second and then starts the video.

Why is this happening if the video is already cached? Is there a way to stop this from happening, so that it goes straight to the video without displaying a white screen?

I tried using AVPlayer's isReady to check the status of AVPlayer and play video only when it's ready, but it still displays the white screen.

Also every time when I try to get the video duration of the video that's about to play through AVPlayer I keep getting 0.0 seconds initially, so I am not able to add a timer to the video either because I can't get the video duration because it keeps displaying a white screen for a second.

dandan78
  • 13,328
  • 13
  • 64
  • 78
Adp
  • 253
  • 3
  • 11

4 Answers4

4

Firstly, AVPlayer doesn't show any white screen, its your background which is white. So, basically your AVPlayer is starting late. I guess you press a UIButton and then it loads the file in AVPlayer and immediately start playing it. Thats where the problem is. It may take some time for the AVPlayer to buffer enough data and be ready to play the file. Using KVO, it is possible to be notified for changes of the player status.

So first you need to disable the play button, load the AVPlayer and add an observer:

play.enabled = NO;
player = [AVPlayer playerWithURL:URL];
[player addObserver:self forKeyPath:@"status" options:0 context:nil]; 

Then enable it after checking AVPlayerStatusReadyToPlay:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change context:(void *)context {
    if (object == player && [keyPath isEqualToString:@"status"]) {
        if (player.status == AVPlayerStatusReadyToPlay) {
            play.enabled = YES;
        }
    }
}
blancos
  • 1,576
  • 2
  • 16
  • 38
  • what if i want to get the duration of the video? I tried doing CMTimeGetSeconds(player.currentItem.duration) when the status was AVPlayerStatusReadyToPlay, but it just gave me the output "nan". – Adp Apr 29 '15 at 20:54
  • As I said, it may take some time for track to get loaded. For duration you can use AVAsset duration property. It is available as soon as you load the asset. – blancos Apr 30 '15 at 06:25
  • Did this get deprecated, because this stopped working all of a sudden. The observeValueForKeyPath method isnt getting called at all anymore, and I didn't change any code – Adp May 03 '15 at 19:01
  • @blancos is correct, if you get get the white screen, you need to to make sure your background is another playLayer is in, needs to be black as in `view.backgroundColor = .black` – Lance Samaria Nov 07 '21 at 18:10
3

I know this is an old question, but I get the same issue even when properly detecting when the AVPlayer is ready to play.

I wanted it to play over an image so that there was a smooth transition between an initial static image, and then moving video.

The trick for me was to set a clear background with:

AVPlayerViewController *controller = [[AVPlayerViewController alloc] init];
[controller.view setBackgroundColor:[UIColor clearColor]];

This way, if I toggle the visibility of the player when it's ready to play, I never see a black or white screen, because the player has a clear background, making for a smooth transition!

Andre
  • 4,417
  • 8
  • 32
  • 37
0

Blancos is right. AVPlayer is taking time to achieve state AVPlayerStatusReadyToPlay. So, initialize the player with url and play it only when it is AVPlayerStatusReadyToPlay.

player = [AVPlayer playerWithURL:URL];  
[player addObserver:self forKeyPath:@"status" options:0 context:nil];   

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                    change:(NSDictionary *)change context:(void *)context   
{  
    if (object == player && [keyPath isEqualToString:@"status"]) {  
        if (player.status == AVPlayerStatusReadyToPlay) {  
            player.play()  
        }  
    }  
}
0

I had the same problem. To avoid adding a KVO, I just set the AVPlayer up when the url is set like so...

var urlToUse: NSURL?
{
    didSet
    {
        guard let urlToUse = urlToUse else { return }
        replayPlayer = AVPlayer(URL: urlToUse)
    }
}

That way the AVPlayer status will be ready when needed.

FromTheStix
  • 429
  • 5
  • 10