Invoke Picture in Picture playback (iOS)

Learn how to enable users to toggle Picture in Picture functionality in your iOS app.


With Picture in Picture mode, users can watch video while using other apps. For example, one of your users can continue watching one of your videos while writing an email.



Requirement

  • iOS 14+ (iPhone)
  • iOS 13+ (iPad)


Implementation


JWPlayerViewController

When using a JWPlayerViewController, the button to toggle Picture in Picture mode is automatically added to the top-right of the player view if the device supports the feature.


JWPlayerView

Picture in Picture functionality can also be accessed through JWPlayerView using the pictureInPictureController property. If Picture in Picture mode is not supported by the device, the property will return nil. Otherwise, the property will return an AVPictureInPictureController object which can be used to start and stop Picture in Picture mode.


  1. Get JWPlayerView’s AVPictureInPictureController instance using the pictureInPictureController property.

    // Get the AVPictureInPictureController using JWPlayerView’s pictureInPictureController property
    guard self.pictureInPictureCotroller = playerView.pictureInPictureController else {
    	// Will be nil if Picture in Picture is not supported on current device
    	return
    }
    
    // Get the AVPictureInPictureController using JWPlayerView’s pictureInPictureController property
       AVPictureInPictureController *pictureInPictureController = self.playerView.pictureInPictureController;
        // Check if the Picture in Picture controller is nil. If it is,
        // Picture in Picture is not supported on this device.
    if (pictureInPictureController != nil) {
    
    }
    

  1. Create an observer to monitor if Picture in Picture is enabled. Sometimes Picture in Picture mode will be temporarily disabled even if the device supports Picture in Picture.
    // Create an observer to monitor whether or not Picture in Picture is currently available.
    pipPossibleObservation = pictureInPictureController.observe(\AVPictureInPictureController.isPictureInPicturePossible,
                                                                       options: [.initial, .new]) { [weak self] _, change in
    // Make changes depending on whether Picture in Picture is possible or not, such as enabling a button to toggle Picture in Picture mode.         
    }
    
    // Create an observer to monitor whether or not Picture in Picture is currently available.
        [pictureInPictureController addObserver:self forKeyPath:@"isPictureInPicturePossible" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:NULL];
                                                                       - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context
    {
        if ([object isEqual:self.pictureInPictureController] && [keyPath isEqualToString:@”isPictureInPicturePossible”]) {
            // Make changes depending on whether Picture in Picture is possible or not, such as enabling a button to toggle Picture in Picture mode. 
        }
    }
    

  1. Add a toggle to start and stop Picture in Picture mode.
    @IBAction func togglePictureInPictureMode(_ sender: UIButton) {
       if pictureInPictureController.isPictureInPictureActive {
           pictureInPictureController.stopPictureInPicture()
       } else {
           pictureInPictureController.startPictureInPicture()
       }
    }
    
    - (IBAction)togglePictureInPictureMode:(id)sender {
        if (pipController.isPictureInPictureActive) {
            [pictureInPictureController stopPictureInPicture];
        } else {
            [pictureInPictureController startPictureInPicture];
        }
    }
    

πŸ“˜

See Apple's AVPictureInPictureController documentation for more information.



FAQ

How can automatic Picture in Picture be prevented?

In iOS 14.2 and above, Picture in Picture mode starts automatically when the app is placed in the background.

To disable this behavior, set canStartPictureInPictureAutomaticallyFromInline = false through JWPlayerView's pictureInPictureController property.

class ViewController: JWPlayerViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        if #available(iOS 14.2, *) {
            playerView.pictureInPictureController?.canStartPictureInPictureAutomaticallyFromInline = false
        }
    }
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    if (@available(iOS 14.2, *)) {
        self.playerView.pictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = YES;
    }
}