子母畫面 (PiP) 可讓使用者在浮動視窗中觀看影片 (一律顯示在其他視窗上方),方便他們留意 在其他網站或應用程式互動時觀看
有了 Picture-in-Picture Web API,即可啟動及控制 網站中影片元素的子母畫面。前往我們的 官方的子母畫面範例。
背景
2016 年 9 月起,Safari 透過 WebKit API 新增子母畫面支援功能 。六個月後,Chrome 就會自動播放 在 Android O 版本中,使用 原生 Android API。六個月後,我們宣布將 標準化 Web API (與 Safari 相容的功能),讓 能夠建立及控管子母畫面功能的完整體驗, 我們到了!
進入程式碼
進入子母畫面模式
讓我們先從影片元素著手,以及使用者與影片互動的方式 例如按鈕元素
<video id="videoElement" src="https://example.com/file.mp4"></video>
<button id="pipButtonElement"></button>
只有在回應使用者手勢時,才要求子母畫面。
videoElement.play()
傳回的 promise。因為保證不會
會傳播使用者手勢。請改為呼叫 requestPictureInPicture()
,
按一下 pipButtonElement
上的處理常式,如下所示。您的責任
來處理使用者按下兩次的情形。
pipButtonElement.addEventListener('click', async function () {
pipButtonElement.disabled = true;
await videoElement.requestPictureInPicture();
pipButtonElement.disabled = false;
});
問題解決後,Chrome 就會將影片縮小成一個小視窗, 使用者即可四處移動及放置其他視窗上方
大功告成!做得好!您值得我們繼續閱讀 度假。不幸的是,情況並不一定。但 可能拒絕 可能原因如下:
- 系統不支援子母畫面。
- 由於限制限制,文件無法使用子母畫面 權限政策。
- 尚未載入影片中繼資料 (
videoElement.readyState === 0
)。 - 影片檔案只能播放音訊。
- 新的
disablePictureInPicture
屬性會顯示在影片元素上。 - 並非透過使用者手勢事件處理常式 (例如按鈕點擊) 發出該呼叫。 從 Chrome 74 版開始,僅適用於 子母畫面。
下方的「功能支援」一節將說明如何根據 這些限制。
讓我們新增 try...catch
區塊來擷取這些潛在錯誤,並讓
讓使用者知道自己接下來會發生什麼事
pipButtonElement.addEventListener('click', async function () {
pipButtonElement.disabled = true;
try {
await videoElement.requestPictureInPicture();
} catch (error) {
// TODO: Show error message to user.
} finally {
pipButtonElement.disabled = false;
}
});
無論影片元素為子母畫面或 不行: 會觸發事件並呼叫方法。反映了 子母畫面視窗 (例如播放、暫停、跳轉等),而且也可以 在 JavaScript 中以程式輔助方式變更狀態
離開子母畫面
現在讓我們讓按鈕切換鈕進入及退出子母畫面模式。三
就必須先檢查唯讀物件 document.pictureInPictureElement
做為影片元素如果不是,我們會傳送輸入申請書
。否則,我們會請致電給對方
document.exitPictureInPicture()
,這代表影片會重新出現在
原始分頁請注意,這個方法也會傳回承諾。
...
try {
if (videoElement !== document.pictureInPictureElement) {
await videoElement.requestPictureInPicture();
} else {
await document.exitPictureInPicture();
}
}
...
監聽子母畫面活動
作業系統通常會將子母畫面限制在一個視窗中,因此 Chrome 的實作模式會遵循這個模式。也就是說,使用者只能在 一次只播放一個子母畫面影片。您應預期使用者會離開 即使您並未提出要求,也能使用子母畫面功能。
新的 enterpictureinpicture
和 leavepictureinpicture
事件處理常式可讓您
為使用者打造個人化體驗例如瀏覽
影片目錄和聊天室訊息。
videoElement.addEventListener('enterpictureinpicture', function (event) {
// Video entered Picture-in-Picture.
});
videoElement.addEventListener('leavepictureinpicture', function (event) {
// Video left Picture-in-Picture.
// User may have played a Picture-in-Picture video from a different page.
});
自訂子母畫面視窗
Chrome 74 支援的 您可以使用 Media Session API 來控制子母畫面視窗。
![子母畫面視窗中的媒體播放控制項](https://developer.chrome.google.cn/static/blog/watch-video-using-picture-in-picture/image/media-playback-controls-b73d819a65211.png?authuser=19&hl=zh-tw)
根據預設,子母畫面一律會顯示「播放/暫停」按鈕。
視窗,除非影片正在播放 MediaStream 物件 (例如 getUserMedia()
、
getDisplayMedia()
、canvas.captureStream()
),或是影片有 MediaSource
時間長度設為 +Infinity
(例如即時動態饋給)。如果畫面中確實顯示播放/暫停按鈕
是否一律會顯示,請為「播放」兩個選項設定一些媒體工作階段動作處理常式和
「Pause」(暫停)媒體事件,如下所示。
// Show a play/pause button in the Picture-in-Picture window
navigator.mediaSession.setActionHandler('play', function () {
// User clicked "Play" button.
});
navigator.mediaSession.setActionHandler('pause', function () {
// User clicked "Pause" button.
});
顯示「上一首」和「下一首」視窗控制項也是一樣的設定 這些應用程式的媒體工作階段動作處理常式會在子母畫面中顯示 你就能處理這些動作
navigator.mediaSession.setActionHandler('previoustrack', function () {
// User clicked "Previous Track" button.
});
navigator.mediaSession.setActionHandler('nexttrack', function () {
// User clicked "Next Track" button.
});
如要瞭解實際運作方式,請參閱官方的媒體工作階段範例。
設定子母畫面視窗大小
針對影片進入及離開畫面時調整畫質 您必須確定子母畫面視窗的大小, 通知使用者手動調整視窗大小。
以下範例說明如何取得 建立或調整子母畫面視窗。
let pipWindow;
videoElement.addEventListener('enterpictureinpicture', function (event) {
pipWindow = event.pictureInPictureWindow;
console.log(`> Window size is ${pipWindow.width}x${pipWindow.height}`);
pipWindow.addEventListener('resize', onPipWindowResize);
});
videoElement.addEventListener('leavepictureinpicture', function (event) {
pipWindow.removeEventListener('resize', onPipWindowResize);
});
function onPipWindowResize(event) {
console.log(
`> Window size changed to ${pipWindow.width}x${pipWindow.height}`
);
// TODO: Change video quality based on Picture-in-Picture window size.
}
我建議不要直接在大小調整事件中跟隨大小變更事件,因為每次稍做變更 調整子母畫面視窗大小會觸發獨立的事件,並可能導致 如果每次調整大小時執行消耗大量資源的作業,會導致效能問題。於 換句話說,調整大小作業會不斷重複觸發事件 可迅速獲取資源建議您採用常見的技術,像是 以處理此問題。
功能支援
系統可能不支援子母畫面 Web API,因此你必須偵測
提供漸進式增強功能即使瀏覽器支援
使用者關閉或權限政策停用。幸好,您可以使用
新的布林值 document.pictureInPictureEnabled
來判斷這一點。
if (!('pictureInPictureEnabled' in document)) {
console.log('The Picture-in-Picture Web API is not available.');
} else if (!document.pictureInPictureEnabled) {
console.log('The Picture-in-Picture Web API is disabled.');
}
套用到影片的特定按鈕元素時 處理子母畫面按鈕的顯示設定。
if ('pictureInPictureEnabled' in document) {
// Set button ability depending on whether Picture-in-Picture can be used.
setPipButton();
videoElement.addEventListener('loadedmetadata', setPipButton);
videoElement.addEventListener('emptied', setPipButton);
} else {
// Hide button if Picture-in-Picture is not supported.
pipButtonElement.hidden = true;
}
function setPipButton() {
pipButtonElement.disabled =
videoElement.readyState === 0 ||
!document.pictureInPictureEnabled ||
videoElement.disablePictureInPicture;
}
MediaStream 影片支援
播放 MediaStream 物件的影片 (例如 getUserMedia()
、getDisplayMedia()
、
canvas.captureStream()
) 也在 Chrome 71 中支援子母畫面。這個
代表您可以顯示有使用者網路攝影機的子母畫面視窗
影片串流、多媒體影片串流
甚至畫布元素請注意,
影片元素不一定要附加至 DOM 才能進入
子母畫面,如下所示。
在子母畫面視窗中顯示使用者的網路攝影機
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();
在子母畫面視窗中顯示畫布元素
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();
結合 canvas.captureStream()
與 Media Session API 即可
執行個體是在 Chrome 74 中建立音訊播放清單視窗。歡迎造訪官方網站
音訊播放清單範例。
![子母畫面視窗中的音訊播放清單](https://developer.chrome.google.cn/static/blog/watch-video-using-picture-in-picture/image/audio-playlist-a-picture-4c2f236920dae.jpeg?authuser=19&hl=zh-tw)
範例、示範和程式碼研究室
歡迎查看官方的子母畫面範例,體驗子母畫面功能 網頁 API。
我們將帶你體驗示範和程式碼研究室。
後續步驟
首先,請參閱導入狀態頁面,瞭解 API 目前已在 Chrome 和其他瀏覽器中實作。
以下是不久後可能會出現的異動:
- 網頁開發人員將可新增自訂子母畫面控制項。
- 系統會提供新的 Web API,以便在浮動視窗中顯示任意
HTMLElement
物件。
瀏覽器支援
Chrome、Edge、Opera 和 Safari 皆支援子母畫面 Web API。 詳情請參閱 MDN。
資源
- Chrome 功能狀態:https://www.chromestatus.com/feature/5729206566649856
- Chrome 實作錯誤:https://crbug.com/?q=component:Blink>Media>PictureInPicture
- 子母畫面 Web API 規格:https://wicg.github.io/picture-in-picture
- 規格問題:https://github.com/WICG/picture-in-picture/issues
- 範例:https://googlechrome.github.io/samples/picture-in-picture/
- 非官方子母畫面 polyfill:https://github.com/gbentaieb/pip-polyfill/
感謝 Mounir Lamouri 和 Jennifer Apacible 的傑出表現 子母畫面和本文說明。感謝各位的貢獻 進行標準化作業。