跟我一塊兒玩轉「畫中畫」

做者:傑里米
閱讀時間:5~10minjavascript

以前在騰訊視頻刷劇時,偶然看到有一個畫中畫的功能很是好用,不懂就問:什麼是「畫中畫」?提及畫中畫,就不得不提起咱們常常乾的一件事兒,咱們想在PC瀏覽器上看電視的同時逛淘寶、刷微博、玩知乎...... 只有你想不到的,沒有我玩不順的!奈何咱們只有一塊屏幕(ps: 用擴展屏的大佬打擾了),這個時候就須要一個輔助英雄——畫中畫,來提升咱們桌面利用率並提升時間效率。java

何爲畫中畫

首先請容許我介紹下「畫中畫」:畫中畫(英文Picture-in-picture,縮寫PiP)是指將一個電視節目(或其餘畫面)顯示在整個畫面上,同時將另外一個或多個其餘畫面顯示在角落中,一般只播放主窗口的聲音 —— from wikigit

早在1976年蒙特利爾奧運會的電視報道中就出現了近似的畫中畫效果,其使用Quantel數字幀存儲設備在開幕式期間插入奧林匹克聖火的特寫照片。github

在瀏覽器中使用畫中畫

隨着咱們平常社交生活的豐富,咱們但願在瀏覽器上也用到畫中畫的功能。web

近兩年,瀏覽器廠商開始陸續支持畫中畫的功能,咱們先來看下瀏覽器中畫中畫的效果:chrome

使用畫中畫

瀏覽器支持狀況

下面介紹目前主流瀏覽器上畫中畫的實現狀態canvas

  • Safari - 已支持
  • Chrome - 已支持
  • Firefox - 測試階段
  • IE - 規劃階段

詳情請查看Implementation Statuspromise

Safari

早在2016年9月,Safari經過macOS Sierra中的WebKit API添加了Picture-in-Picture支持。相比chrome,safari在自帶的播放控件內加入了畫中畫模式的按鈕。瀏覽器

Chrome

  • 試驗性功能

2017年4月,Chrome經過使用原生Android API發佈Android O,能夠自動在移動設備上播放畫中畫視頻。 2018年10月,Chrome在PC 客戶端69版本加入畫中畫的特性,但在該版本中畫中畫是默認關閉的,若是想開啓該特性,須要在瀏覽器執行如下操做:bash

  1. 輸入chrome://flags並按下回車鍵
  2. 在搜索框依次搜索三個關鍵詞enable-experimental-web-platform-features(啓用正在開發的實驗性Web平臺功能)、enable-Surfaces-for-videos(啓用合成到Surface而不是視頻的VideoLayer)、enable-picture-in-picture(爲video開啓畫中畫特性)並將選項值置爲Enabled
  3. 重啓chrome瀏覽器
  4. 在含有視頻的頁面使用鼠標右擊視頻區域,點擊菜單欄中的「畫中畫」選項觀看視頻
  • 正式開啓

到了70版本已默認開啓該特性,安裝chrome擴展插件可進入畫中畫,進入畫中畫後,頁面選項卡會出現一個藍色的圖標,以提醒用戶該頁面正在播放視頻。

畫中畫圖標

支持webRTC的視頻流

Chrome 71中的畫中畫支持播放MediaStream對象的視頻(例如getUserMedia(),getDisplayMedia(),canvas.captureStream())。這意味着能夠顯示包含用戶網絡攝像頭視頻流的畫中畫窗口,便可以 顯示webRTC的視頻流。

FireFox

目前Firefox的畫中畫功能還在測試之中,須要Firefox超前測試版Nightly才能開啓畫中畫模式,具體步驟以下:

  1. 打開about:config設置頁
  2. 搜索media.videocontrols.picture-in-picture.enabled點擊切換,讓其置爲true
  3. 重啓瀏覽器
  4. 打開含有視頻頁面,開始播放視頻
  5. 在視頻區域鼠標右鍵,會出現畫中畫菜單
  6. 開啓畫中畫

須要注意的是,Chrome 與 Firefox 的畫中畫模式略有不一樣,Chrome 開啓畫中畫後,瀏覽器內的視頻將再也不播放,而 Firefox 則至關於啓用了雙屏播放,畫中畫和原標籤頁同步播放,並且目前的畫中畫功能甚至沒有關閉畫中畫視頻的選項,所以必須再次鼠標右鍵單擊才能關閉畫中畫功能。


開發者如何使用畫中畫

對於開發者而言,讓用戶體驗到畫中畫模式帶來的效果是最使人興奮的,感謝瀏覽器爸爸提供了相應的API供咱們開發者調用。因爲safari實現的時間太早,而谷歌又用本身的一套API,致使API目前還沒有標準化(好消息是畫中畫Web API的規範 已經在WICG草案階段中了,大致上和chrome的API規範一致,具體可猛戳此處),我將對目前已支持的瀏覽器(chrome和safari)分別介紹其Web API:

在chrome上運行

先來看一個示例(示例中的視頻源來自騰訊):

畫中畫-chrome示例

咱們來看上述示例中用到的屬性和方法:

  • document.pictureInPictureEnabled

該屬性用來判斷當前文檔是否支持使用畫中畫所示的功能。(不能理解爲瀏覽器是否支持,由於即使瀏覽器支持的狀況下,用戶禁用畫中畫功能也會返回false)

  • document.pictureInPictureElement

該屬性返回當前文檔內存在的畫中畫元素對象,若是不存在返回null,不然返回video element

  • video.requestPictureInPicture()

這個API是真正去請求視頻進入畫中畫模式的,結果會返回一個promise,在promise成功回調中拿到一個pipWindow對象,這個對象包含:

{ width, height, resize }
複製代碼

width和height分別是視頻進入畫中畫窗口的寬高,resize能夠監聽一個事件回調,在畫中畫窗口發生變化時觸發。

① 爲什麼API掛載到video上而不是document上?

由於一個頁面可能會存在多個video,因此須要指定觸發畫中畫的video元素。

② 那麼什麼狀況下API會調用失敗?

  1. 系統不支持畫中畫
  2. 因爲限制性功能策略,不容許document使用畫中畫。
  3. 視頻元數據未加載(videoElement.readyState === 0)
  4. 視頻文件只有音頻
  5. video元素設置了disablePictureInPicture新屬性
  6. 畫中畫的請求調用不是經過用戶手勢事件(例如按鈕點擊)處理的,此處須要注意像mouseovermouseentermousemovemouseleavescrollonload等事件都不算用戶手勢事件。
  • document.exitPictureInPicture()

當咱們想主動退出畫中畫,能夠調用這個API,其結果也會返回一個promise。

① 爲什麼API掛載到document而不是video上?

由於目前一個頁面最多僅容許一個video顯示在畫中畫窗口上。對於開發者而言,不須要退出畫中畫的是哪一個video,所以只須要掛載到document上就能夠了。

  • onenterpictureinpicture和onleavepictureinpicture

當咱們想監聽video是否真正進入/退出畫中畫時,有時候進入/退出畫中畫並非咱們經過調用requestPictureInPicture/exitPictureInPicture來觸發的,好比用戶經過chrome插件讓視頻進入畫中畫,這個時候須要監聽這兩個事件,來獲取一些有用的信息並進行上報之類的行爲。

在safari上運行

因爲safari早在2016年就原生支持了畫中畫,所以API和chrome是徹底不一致的。在safari裏咱們能夠把「畫中畫」理解爲播放模式的概念,safari中的播放模式只有三種,分別是inlinepicture-in-picturefullscreen

咱們先來看一個簡單的示例:

畫中畫-safari示例

從上面示例能夠看出,畫中畫相關屬性和方法都是掛載到具體的視頻元素上。

咱們來看上述示例中用到的屬性和方法:

  • video.webkitSupportsPresentationMode(mode)

該方法是檢測video元素所支持的「演示模式」(通常理解爲播放模式),這裏傳參mode支持三個有效值:picture-in-pictureinlinefullscreen

通常有兩種方式來判斷是否支持畫中畫。第一種就是上述示例所介紹的,第二種即:

let supportsPiP = false;
try {
    supportsPiP = video.webkitSupportsPresentationMode('picture-in-picture');
} catch(e) {
    supportsPiP = false;
}
複製代碼

若是webkitSupportsPresentationMode傳入無效值,會拋出error,以下所示:

輸入無效值

  • video.webkitPresentationMode

這個屬性值返回的其實就是上面播放模式的三個有效值之一。能夠用該屬性判斷當前video所處的模式是否爲畫中畫。

  • video.webkitSetPresentationMode(mode)

這個方法能夠設置當前模式,當mode='picture-in-picture',就等效於chrome中的video.requestPictureInPicture()。當mode='inline',就等效於chrome中的document.exitPictureInPicture()。須要注意的是,在safari裏調用此方法進入/退出畫中畫,都沒有返回值,固然也不會報錯。

  • onwebkitpresentationmodechanged

當前播放模式發生變化時能夠經過這個事件監聽,不管是進入/退出畫中畫,都會觸發此事件的監聽回調。須要注意的是這裏不會返回畫中畫窗口下的對象信息(包括窗口width、height等)

不管在safari/chrome,若是畫中畫內播放的是實時音視頻流,瀏覽器會在退出畫中畫時暫停掉視頻的播放,須要在退出畫中畫後手動觸發視頻流繼續播放。

polyfill兼容

根據目前畫中畫的支持狀況,這裏有一個畫中畫polyfill庫能夠兼容到chrome和safari


自動畫中畫

在WICG Picture-in-Picture草案中提到了自動畫中畫的特性:

「 某些頁面的video元素想要自動進入/退出畫中畫,例如,當用戶在Web應用程序與其餘應用tab之間來回切換時,視頻Web應用程序將受益於一些自動畫中畫行爲。但很遺憾,用戶手勢目前是作不到的,因此就須要Auto Picture-in-Picture了!」

咱們只須要給video元素加入一個新屬性autopictureinpicture

<video autopictureinpicture></video>
複製代碼

這意味着不須要開發者手動調用方法來執行畫中畫的行爲,當頁面文檔隱藏時,最近設置了autopictureinpicture屬性的video元素就會自動進入Picture-in-Picture(若是容許畫中畫的話),當頁面文檔可見時,畫中畫中的視頻元素會自動離開。


參考文檔

讓 Chrome 與 Firefox 實現系統級視頻畫中畫效果

Picture-in-Picture

github.com/WICG/pictur…

developers.google.com/web/updates…


關注【IVWEB社區】公衆號獲取每週最新文章,通往人生之巔!

相關文章
相關標籤/搜索