Video.js: Support for picture-in-picture API

Created on 26 Feb 2019  路  26Comments  路  Source: videojs/video.js

Most helpful comment

Yeah, this is definitely something we'll look into.

All 26 comments

Simple button subclass that works:

class PictureInPictureToggle extends Button {
    async handleClick(event) {
        let mediaElement = this.player_.el().firstChild();

        // disable button during picture-in-picture switch
        this.disable();

        // switch picture-in-picture mode
        try {
            if (mediaElement !== document.pictureInPictureElement) {
                // request picture-in-picture
                await mediaElement.requestPictureInPicture();
            } else {
                // exit picture-in-picture
                await document.exitPictureInPicture();
            }
        } catch (error) {
            // notify listeners
            this.player_.trigger('error', error);
        } finally {
            // switch completed
            this.enable();
        }
    }
}

It's now supported in the videojs-record plugin, e.g.

picture-in-picture

Demo: https://collab-project.github.io/videojs-record/examples/picture-in-picture.html

And it's really cool to see a video element flip to an external window so easily.

I think PiP should be part of video.js, not just a plugin.

Yes this should be a good feature .

Yeah, this is definitely something we'll look into.

Put together a really rough version to test just using the airplay icon works in Safari and Chrome not Firefox.
~~~
(function(vjs) {
var pipPlugin = function(options) {

    var player = this;

    // Needed if the player is loaded multiple times before being disposed
    if (!player.el()) {
        return;
    }

    // VIDEO EL::
    var video = player.player().el().getElementsByTagName('video')[0];

    if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function" || ('pictureInPictureEnabled' in document)) {

        var pipToggle = videojs.getComponent("Button");
        var pipButton = videojs.extend(pipToggle, {
            constructor: function(player, options) {

                pipToggle.call(this, player, options);
                this.controlText("Picture-in-Picture"); 

            },
            handleClick: function() {

                if(('pictureInPictureEnabled' in document)){

                    video.requestPictureInPicture();

                }else{

                    video.webkitSetPresentationMode('picture-in-picture');

                }                   

            },
            buildCSSClass: function() {

                return "vjs-icon-airplay vjs-control vjs-button";

            }
        });
        videojs.registerComponent("pipToggle", pipButton);

        // WAIT FOR LOAD::
        player.on('loadeddata', function() {

            var pipToggleBtn = player.controlBar.addChild('pipToggle', {});
            player.controlBar.el().insertBefore(pipToggleBtn.el(), player.controlBar.fullscreenToggle.el());

        });

    }

};
vjs.registerPlugin('pipPlugin', pipPlugin);

})(window.videojs);
~~~

@gkatsev What is the status for this feature? I'd love to see built-in support for PiP in video.js.

This week I'll be working on an actual roadmap for Video.js. This will definitely be on it. Unfortunately, I can't promise that it'll be prioritized over other work that we want or need to do.

@gkatsev Thanks for the update.
I'll be happy to review the Picture-in-Picture PR if needed.

Any updates on this....
I see it in players like https://plyr.io/ and i believe it should be here first....

This is on the team's backlog but, unfortunately, there's a lot of work that is higher priority (https://github.com/videojs/http-streaming/milestone/3 and more).
When the core team gets started on this, we'll definitely post here.
However, until that happens, if anyone wants to work on this, feel free to ping me here on on our slack and I can help go over the requirements for it. (If I have time, I'll write out a spec in this issue but may not get around to it without a nudge).

@gkatsev I'd love to help actually. Please write down requirements in this issue and I'll start working on it.

Below is the req for it. I think it can be done in at least 4 stages, it's better to have it done in many PRs rather than one giant PR. Also, I'd wait a couple of days before starting so that people can add comments on the req below (feel free to add comments yourself as well) and I'll update as necessary.


I think this can be done in a few stages:

  1. add the correct API methods
  2. support both the spec and custom implementations (this is for Safari as they aren't spec compliant yet)
  3. support the auto pip and disable pip options
  4. add in a control bar button

add the correct API methods

The spec is here: https://wicg.github.io/picture-in-picture
There's also a good writeup on the google dev website https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture

  • [x] add requestPictureInPicture methods

    • [x] player.js: should just do a techGet (as the native methods returns a promise, we want to be able to return it as well). We should also track whether we're in PiP or not similar to fullscreen.

    • [x] tech.js: should be a no-op or throw an error (this is for when it's used by a tech that doesn't implement pip

    • [x] html5.js: this should call the native method and respond handle the returned promise properly

  • [x] add exitPictureInPicture methods

    • [x] player.js: should call document.exitPictureInPicture

  • [x] player.js: add isInPictureInPicture which returns whether we're in a PiP right now or not
  • [x] should fail gracefully when on a browser with no support
  • [x] make sure that you can listen to the PiP events (enterpictureinpicture, leavepictureinpicture) on the player

support both the spec and custom implementations (this is for Safari as they aren't spec compliant yet)

Safari has their own implementation. For it, we need to update the requestPictureInPicture and exitPictureInPicture methods appropriately.
Safari's API is here: https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_9_0.html#//apple_ref/doc/uid/TP40014305-CH9-SW18

  • [ ] html5: requestPictureInPicture should call either the spec version of the safari version using feature detection
  • [ ] player.js: exitPictureInPicture should do a techCall if we're in safari, via feature detection
  • [ ] html5.js: add exitPictureInPicture method for safari
  • [ ] trigger custom PiP events (enterpictureinpicture, leavepictureinpicture) if we're in safari

support the auto pip and disable pip options

Add autoPictureInPicture and disablePictureInPicture as allowed options in html5.js.

add in a control bar button

This button should function similarly to the fullscreen toggle button

Also, feel free to drop by our slack for more real-time chat :)

I've started implemented Picture-in-Picture. You should see some PRs popping up soon.

For info, I wrote https://developers.google.com/web/updates/2018/10/watch-video-using-picture-in-picture ;)

@beaufortfrancois hahaha, I totally didn't make the connection, super appreciate the help!

what's the status of this? does 7.6.0 contain all functionality?

7.6 contains the button and the WICG-specced API. It won't work in Safari currently, but that could be added at a later date (or safari could ship the WICG API).

hello guys , thanks a lot for this feature, but i think we need to show subtitle in picture-in-picture mode

image

@osamaalnuimi Subtitles are not supported yet in Picture-in-Picture in Chrome. They are in Safari though.
You can star bug at https://bugs.chromium.org/p/chromium/issues/detail?id=854935

Thanks for the answer @beaufortfrancois!

At some point, video.js will need to switch over to native text tracks when captions in PiP is supported (or at least switch to native tracks when using the PiP). Right now, native support is severely lacking (something I'm trying to fix).

@gkatsev I noticed the PiP button is always visible but disabled in browsers that do no support it. Is this intentional? I find it kind of confusing and rather hide it in places where it's unsupported. I can do this manually of course but I wonder why a non-functional button is part of the controlbar in some browsers.

Yeah, I think it's an oversight, it makes sense to leave it out on browsers that don't support it at all and have it be disabled if the iframe/page disables it.

So is there a method for disabling picture in picture? I'm not seeing anything here: https://docs.videojs.com/tutorial-options.html

@MrWiLofDoom you can pass in the following option to hide the button: https://github.com/videojs/video.js/pull/6002#issuecomment-510620446

Please add:

{
  controlBar: { 
    'pictureInPictureToggle': false
  }
}

to the docs at: https://docs.videojs.com/docs/guides/options.html -- Ah, found it here: https://docs.videojs.com/docs/guides/components.html

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SolmazKh picture SolmazKh  路  4Comments

kitsunde picture kitsunde  路  4Comments

kocoten1992 picture kocoten1992  路  4Comments

victorpfm picture victorpfm  路  4Comments

shivamg705 picture shivamg705  路  4Comments