13

20190323110604.png

浏览器画中画模式

浏览器画中画功能允许用户在一个小的叠加窗口中弹出网页中播放的视频 🎥,Chrome 版本大于 71 均默认开启该功能。下面简单介绍一下该 API 如何使用 📖

准备工作

首先要有个 video,以及一个 btn ⏹ 用来 toggle 画中画功能

<video id="video" src="./mix3.mp4" controls autoplay></video>
<button id="toggle">toggle</button>

js 部分

js 部分很简单,只需要调用 video 元素的 requestPictureInPicture 方法即可,然后再调用 document 对象下的 exitPictureInPicture 方法就可以关闭画中画功能了 💻

另外,document 对象下的 pictureInPictureElement 指向画中画功能生效的那个 video 元素,如果没有开启画中画,那么返回值是 null

还有就是上述两个 API 都是异步的,始终返回 Promise

const btn = document.querySelector('#toggle')
const vid = document.querySelector('#video')

async function handleToggle() {
    try { // 捕获 async-await 错误 ❌
        if (vid !== document.pictureInPictureElement) { // 判断当前 PictureInPicture 是否已经开启并是否指向该 video
            await vid.requestPictureInPicture() // 调用 API 开启功能 ⭕️
        } else {
            await document.exitPictureInPicture() // 调用 API 关闭功能 ⛔️
        }
        this.disabled = true // toggle 按钮避免频繁触发
    } catch (error) {
        // error handler 错误处理 ❌
    } finally {
        this.disabled = false
    }
}

btn.addEventListener('click', handleToggle)

这样就完成了,效果如下:

fff.gif

相关事件

如果需要监听是否开启或关闭画中画功能,可以使用下面两个事件:

vid.addEventListener('enterpictureinpicture', function() { console.warn('on') })
vid.addEventListener('leavepictureinpicture', function() { console.warn('off') })

20190323101959.png

如果需要监听画中画尺寸 resize 操作:

let pipWindow

vid.addEventListener('enterpictureinpicture', function (event) {
    pipWindow = event.pictureInPictureWindow // 获取当前 pip 窗口 👀
    console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`) // width height 属性获得宽高
    pipWindow.addEventListener('resize', onPipWindowResize)
})

vid.addEventListener('leavepictureinpicture', function (event) {
    pipWindow.removeEventListener('resize', onPipWindowResize)
})

function onPipWindowResize(event) {
    console.log(`> Window size changed to ${pipWindow.width}x${pipWindow.height}`)
    // chrome 建议根据 window 尺寸大小动态调节 video 质量
}

检查是否可用

可能浏览器不支持画中画功能,即便是浏览器支持,可能用户手动关闭或 CFP 的禁止导致无法使用该功能 🚫

检查浏览器是否支持:

if (!('pictureInPictureEnabled' in document)) {}

检查是否可用:

if (!document.pictureInPictureEnabled) {}

根据上述判断来动态添加画中画功能按钮:

if ('pictureInPictureEnabled' in document) {
    // 支持的情况显示按钮
    setPipButton()
    videoElement.addEventListener('loadedmetadata', setPipButton)
    videoElement.addEventListener('emptied', setPipButton)
} else {
    // 不支持的情况隐藏按钮
    pipButtonElement.hidden = true
}

function setPipButton() {
    pipButtonElement.disabled = (videoElement.readyState === 0) || !document.pictureInPictureEnabled || videoElement.disablePictureInPicture
}

流媒体的支持

另外画中画功能还支持流媒体。如用户的摄像头、用户屏幕实时共享以及 canvas 🤒:

摄像头的支持:

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });
video.play()

// Later on, video.requestPictureInPicture();

屏幕实时共享:

const video = document.createElement('video');
video.muted = true;
video.srcObject = await navigator.mediaDevices.getDisplayMedia({ video: true });
video.play();

// Later on, video.requestPictureInPicture();

canvas:

const canvas = document.createElement('canvas');
// Draw something to canvas.
canvas.getContext('2d').fillRect(0, 0, canvas.width, canvas.height);

const video = document.createElement('video');
video.muted = true;
video.srcObject = canvas.captureStream();
video.play();

// Later on, video.requestPictureInPicture();

获取用户屏幕用到了 screenCapture API

20190323104620.png

当然这需要用户点击同意才可获得授权

20190323104206.png

共享过程中会有个 banner 点击停止共享即可停止录制

20190323104401.png

DEMO 见:https://webrtc.github.io/samp...

与画中画结合的效果可以看这个 demo:

https://developer.mozilla.org...

fff.gif


JS菌
6.4k 声望2k 粉丝