Picture-in-Picture Plugin (aka "floating" or "pinned")

Product(s)
Video Cloud
Brightcove Player
Role(s)
Player Developer
Task(s)
Create & Configure Players
Topic(s)
Playback
Type
Support Doc

In this topic, you will learn how to use the picture-in-picture (PIP) plugin to enable this mode for the Brightcove Player.

Overview

Picture-in-picture mode allows users to multitask. Once video playback has started, as the user scrolls down the page, picture-in-picture mode will reposition and pin the player to a corner of the web page.

Why it is called Picture-in-Picture

The behavior this plugin enables is also commonly referred to as "floating" or "pinned" behavior. Brightcove uses the term "picture-in-picture" because of adoption of this verbiage by Apple and Google for their native browsers. W3C standards also reference "picture-in-picture".

Player example

Start video playback. (You can then stop it). Scroll down the page to see the pip player in the right-hand corner of the web page. You can close the pip player or scroll back up to the full-size player.

See the Pen Picture-in-Picture Plugin by Brightcove Learning Services (@bcls1969) on CodePen.

Implement using Players module

To implement the Picture-in-Picture Plugin using the Players module, follow these steps:

  1. Open the PLAYERS module and either create a new player or locate the player to which you wish to add the plugin.
  2. Click the link for the player to open the player's properties.
  3. Click Plugins in the left navigation menu.
  4. Next, click Add a Plugin.
  5. For the Plugin Name enter pip.
  6. For the JavaScript URL, enter:
    https://players.brightcove.net/videojs-pip/1/videojs-pip.min.js
  7. For the CSS URL, enter:
    https://players.brightcove.net/videojs-pip/1/videojs-pip.css
  8. You do not have to enter any options for this plugin.
  9. Click Save.
  10. To publish the player, click Publish & Embed > Publish Changes.
  11. To close the open dialog, click Close.
  12. In an editor, open the HTML code for your web page with the player in it.
  13. The picture-in-picture plugin requires that your player is wrapped by a container element with the class set to vjs-pip-container. Your code should look similar to this:

    <div class="vjs-pip-container">
      <video-js id="myPlayerID"
        data-video-id="5701202551001"
        data-account="1752604059001"
        data-player="default"
        data-embed="default"
        class="video-js"
        width="640" height="360"
        controls></video-js>
      <script src="https://players.brightcove.net/1752604059001/default_default/index.min.js"></script>
    </div>

    If the <div> element above is not found as the parent of the player, the plugin will fail to initialize and you will get the following log warning:

    expected player to be a child of a "vjs-pip-container" element, cannot continue with picture-in-picture plugin

Implement using code

To implement the plugin using custom code, you will configure the following plugin properties:

  • scripts - JavaScript supplied for the plugin and will not change for different plugin implementations
  • stylesheets - CSS supplied to you for the plugin and will not change for different plugin implementations
  • plugin name - Always pip
  • plugin options - Contains an array of properties and values

To add the plugin to your code, follow these steps:

  1. Add the styles for the pip plugin.
    <link href="https://players.brightcove.net/videojs-pip/1/videojs-pip.css" rel="stylesheet">
  2. Add the JavaScript file to include the pip plugin.
    <video-js id="myPlayerID"
      data-video-id="5701202551001"
      data-account="1752604059001"
      data-player="default"
      data-embed="default"
      class="video-js"
      width="640" height="360"
      controls></video-js>
    <script src="https://players.brightcove.net/1752604059001/default_default/index.min.js"></script>
    
    <!-- Script for the picture-in-picture plugin -->
    <script src="https://players.brightcove.net/videojs-pip/1/videojs-pip.min.js"></script>
  3. Wrap the player embed code in a container element with the class set to vjs-pip-container. The picture-in-picture plugin requires that your player is wrapped by this container element.

    <div class="vjs-pip-container">
        <video-js id="myPlayerID"
          data-video-id="5701202551001"
          data-account="1752604059001"
          data-player="default"
          data-embed="default"
          class="video-js"
          width="640" height="360"
          controls></video-js>
        <script src="https://players.brightcove.net/1752604059001/default_default/index.min.js"></script>
      </div>
    
            <!-- Script for the picture-in-picture plugin -->
            <script src="https://players.brightcove.net/videojs-pip/1/videojs-pip.min.js"></script>

    If the <div> element above is not found as the parent of the player, the plugin will fail to initialize and you will get the following log warning:

    expected player to be a child of a "vjs-pip-container" element, cannot continue with picture-in-picture plugin
  4. Add custom script code which does the following:
    • When the player is ready, gets a reference to the Brightcove player. In this example, we are creating a variable named myPlayer and assigning it a reference to the player.
    • Initializes the picture-in-picture plugin.
    videojs.getPlayer('myPlayerID').ready(function() {
      // When the player is ready, get a reference to it
      var myPlayer = this;
      // Initialize the picture-in-picture plugin
      myPlayer.pip();
    });

    For details, see the codepen example above.

Options

You may pass in an options object to the plugin upon initialization. This object may contain any of the following options:

allowOnMobile

  • allowOnMobile:
    • Type: boolean
    • Default: false
    • By default, picture-in-picture mode will not work on Android or iOS mobile devices. The reason for this is because these CSS fixed positioning does not work on zoomable devices with multiple viewports in the same way it does on desktop devices.

      If you want to enable pip on supported mobile devices, you can do so with this option. There are some cases where you might want to enable support:

      • The integrator is willing to take on the responsibility of managing positioning for picture-in-picture player mode.
      • The website using the player is unlikely to be zoomed.
      • Zooming has been disabled using a user-scalable=no directive. Using this directive will make position: fixed behave as it does on desktops, but it is not specifically recommended because it can be an accessibility concern.
        <meta name="viewport" content="width=device-width, user-scalable=no">
    • Example:

      // Allow mobile (iOS and Android) devices to enter PIP mode.
            player.pip({allowOnMobile: true});

closeable

  • closeable:
    • Type: boolean
    • Default: true
    • By default, picture-in-picture mode can be disabled by the user by clicking the X button in the top, right corner of the player. This feature can be disabled by passing false for this option.
    • Example:

      // Do not allow the user to close the PIP mode player.
            player.pip({closeable: false});

scale

  • scale:
    • Type: number
    • Default: 2 / 3
    • The scaling factor applied to the player when it is in picture-in-picture mode. This value must be a number greater than zero and less than or equal to 1.
    • Example:

      // Detach the player, but do not change its size.
            player.pip({scale: 1});
    • Example 2:

      // Detach the player, and change its size to 1/2.
            player.pip({scale: 0.5});

height and width

  • height and width:
    • Type: number
    • Default: null
    • By default, the plugin will scale down the player's dimensions by a factor determined by the scale option. However, providing a height (or width) will override the default scaling and set the size of the scaled-down player explicitly.

      If only one dimension is provided, the other will be scaled down to maintain the aspect ratio. If both dimensions are provided, the player will be set to the exact, specified size - allowing a change in aspect ratio.

    • Example:

      // Detach the player and set its width to 300 pixels. Scale its height to
            // maintain its current aspect ratio.
            player.pip({width: 300});

posX

  • posX:
    • Type: string
    • Default: "right"
    • The horizontal alignment of the player when it is in picture-in-picture mode - either "right" or "left".

    • Example:

      // When the player is in PIP mode, align it to the left side of the viewport.
            player.pip({posX: 'left'});

posY

  • posY:
    • Type: string
    • Default: "bottom"
    • The vertical alignment of the player when it is in picture-in-picture mode - either "top" or "bottom".

    • Example:

      // When the player is in PIP mode, align it to the top of the viewport.
            player.pip({posY: 'top'});

viewable

  • viewable:
    • Type: number
    • Default: 0.8
    • The threshold at which the player is considered viewable. In other words, when this percentage of the total player area (height and width) is visible in the browser's viewport, it is considered viewable.

      For example, with the default of 0.8, the player is not considered viewable unless 80% of it is visible in the viewport. The viewable value must be a number greater than or equal to 0 and less than or equal to 1.

    • Example:

      // If more than half the player is outside of the viewport, activate PIP mode.
            player.pip({viewable: 0.5});

manualContainerSize

  • manualContainerSize:
    • Type: boolean
    • Default: false
    • By default, a player with this plugin enabled will keep the physical dimensions of the special container element in sync with the player's dimensions. However, this behavior may not work for all use-cases, so it can be disabled by setting this option to true.

      When doing so, the container element will behave like a normal block element. This means that users of the plugin will need to manage its size on their own.

      This option can also be set in the embed code via the boolean data-manual-container-size attribute on the container. Its presence will set this option to true. Note that any value passed to the plugin will take precedence over any value defined in the embed code.

    • Example:

      // Implementation will handle sizing the container.
            player.pip({manualContainerSize: true});
    • Example using the data-manual-container-size attribute on the container:

      <div class="vjs-pip-container" data-manual-container-size>
        <video-js class="video-js vjs-default-skin">
        </video-js>
      </div>

Using the options

You have two ways you can utilize the option:

  1. In Studio's PLAYERS > PLUGINS section.
  2. Using JavaScript with the player.

Using Studio

In Studio, edit the player to which you wish to supply options and return to the Plugins section. Click on pip in the name list. Now, using proper JSON format, list the option (in quotation marks), followed by the appropriate value. If the values are string, they must be in quotes. If they are numeric or boolean, quotes cannot be included:

Players module plugin
Players module plugin

Using JavaScript

To implement the options in code, you create an object, assign desired options their respective values, then pass the options object when calling the plugin:

videojs.getPlayer('myPlayerID').ready(function() {
  // When the player is ready, get a reference to it
  var myPlayer = this,
      options = {};

  options.scale = 0.5;
  options.posX = "left";
  // Initialize the picture-in-picture plugin
  myPlayer.pip(options);
});

Methods

The following methods let you interact with the picture-in-picture plugin:

Method Description
pip.enable() Enable automatic picture-in-picture behavior
pip.disable() Disable automatic picture-in-picture behavior
pip.toggle() Manually activate or deactivate picture-in-picture mode based on the current state
pip.activate() Manually put the player into picture-in-picture mode
pip.deactivate() Manually take the player out of picture-in-picture mode

Events

The following events are fired from the picture-in-picture plugin:

Event Description
beforepipactive Fires before pip mode is activated
pipactive Fires after pip mode is activated
beforepipinactive Fires before pip mode is deactivated
pipinactive Fires after pip mode is deactivated
beforepipenabled Fires before the videojs-pip plugin is enabled
pipenabled Fires after the videojs-pip plugin is enabled
beforepipdisabled Fires before the videojs-pip plugin is disabled
pipdisabled Fires after the videojs-pip plugin is disabled

Changelog

4 Dec 2018

v1.0.4

  • Bug fix: Do not include loscore in the bundles
  • Bug fix: Fixed an issue where allowOnMobile was not respected
  • Bug fix: Remove the postinstall script to prevent install issues
  • Update using plugin generator v7.2.0

3 Aug 2018

v1.0.3

  • Bug Fix: Set viewable option when instantiating plugin

11 Jun 2018

v1.0.2

  • Fix a rare race condition where a PIP player that was initialized late could trigger the PIP behavior upon initialization; now, it will wait for user activity before allowing PIP mode to activate

25 May 2018

v1.0.1

  • Fixed Picture-in-Picture mode for responsive players

26 Mar 2018

v1.0.0

  • Allow the player to switch into picture-in-picture mode where it is detached from the page and fixed to the viewport.