iOS 10 - AVPlayer shows black screen when playing video

10,258

Solution 1

Thanks for your replies! I just found that, for some reason in iOS 10 the viewDidLayoutSubviews did not get called as it was in iOS 9. Actually I was setting the player layer's frame in the viewDidLayoutSubviews method. Since it didn't get called, I was not able to see the player on screen. What I did was, set the player layer's frame in the loadPlayer method above.And it works fine. Thanks! Hope this helps someone.

EDIT

This is the line of code that I moved from viewDidLayoutSubviews to my loadPlayer method and it worked:

self.playerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);

Solution 2

You need to retain your instance of AVPlayerItem i.e. as a property or an instance variable. The reference to the movie player is lost if you do not retain it. Even some time this rubish happens in ARC as well.Please make it property.

Solution 3

In my case this problem was because i started playing simultaneously with UIView.animate with view.layoutIfNeeded() in animation block.

The fix for that is to not animate layout changes when not needed and not animate when starting playing video.

Solution 4

The solutions on this page did not work for me.

I found another solution to this problem. In my case the video was being played in black but the sound was ok.

I discovered that changing the time slider to scrub the video would make the video appear.

So, my solution was to make the video go the the last frame, then to the first before playing:

Float64 duration = [self.player duration];    
[self.player goToTime:duration];
[self.player goToTime:0.0f];
Share:
10,258
badhanganesh
Author by

badhanganesh

Updated on June 04, 2022

Comments

  • badhanganesh
    badhanganesh almost 2 years

    Here I have a method that adds the video layer to the UIView that I have setup in IB:

     -(void)loadPlayer{
            self.asset = [AVAsset assetWithURL:url];
    
            AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:self.asset];
    
            self.player = [AVPlayer playerWithPlayerItem:item];
            self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
            self.playerLayer.contentsGravity = AVLayerVideoGravityResizeAspect;
            self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
    
            item.videoComposition = [AVVideoComposition videoCompositionWithPropertiesOfAsset:self.asset];
    
            [self.player pause];
            [self.player addObserver:self forKeyPath:@"status" options:0 context:nil];
    
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.videoLayer.layer addSublayer:self.playerLayer];
            });
    }
    

    The above method gets called in the viewDidAppear of the View Controller, so each time the current View Controller loads, the video should start to play.

    Here I check for the player status and play the asset if ready:

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

    The problem is that the view did appear, the video starts playing, but only the audio, not video. All I get is black screen in the place of video. Audio is playing back fine, but it does not seem to render the video frames for some reason unknown.

    This happens only on iOS 10 devices, the same code when run on a iOS 9 devices, works like a charm. The video shows up as expected.

    Is there anything that is changed in the AVFoundation framework for iOS 10 in terms of AVPlayer or so? Or is there anything that I am missing here, coz iOS 9 plays it good.

    If anyone has faced this issue, and if you have solved it, please post your solution. It would be helpful.

    Thanks.


    THE SOLUTION

    Thanks for your replies! I just found that, for some reason in iOS 10 the viewDidLayoutSubviews did not get called as it was in iOS 9. Actually I was setting the player layer's frame in the viewDidLayoutSubviews method. Since it didn't get called, I was not able to see the player on screen. What I did was, set the player layer's frame in the loadPlayer method above. And it works fine. Hope this helps someone.

    This is the line of code that I moved from viewDidLayoutSubviews to my loadPlayer method and it worked:

    self.playerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    
  • Matloob Hasnain
    Matloob Hasnain over 7 years
    I have got same error , But I am not sure It will help you. apologies
  • badhanganesh
    badhanganesh over 7 years
    Thanks, Matloob. I tried changing it to property before finding my solution. Didn't work. Please try my answer to see if it works.
  • badhanganesh
    badhanganesh over 7 years
    Thanks! I got the solution. Please check my answer.
  • Dominic
    Dominic almost 6 years
    Opinion and comment about why you are providing a link would be useful
  • Ilesh P
    Ilesh P almost 6 years
    It's not working for me. I got to crash in the "self.playerLayer.frame".
  • Anand Gautam
    Anand Gautam about 5 years
    @Bandhan Ganesh Pls suggest here : stackoverflow.com/questions/54745359/…