1. 程式人生 > >iOS 10 Safari 視訊播放新政策

iOS 10 Safari 視訊播放新政策

提醒:本文最後更新於 788 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

隨著 iOS 10 的正式釋出,Safari 也迎來了大量更新,例如新增了對 ES6、CSP2.0、Shadow DOM 等功能和特性的支援。本文為大家介紹 iOS10 自帶 Safari 瀏覽器在視訊播放政策上的最新變化。首先劃出重點:1)iOS 10 Safari 支援特定視訊自動播放;2)iOS 10 Safari 支援視訊內聯播放。想了解更多細節的同學請接著往下看。

之前的政策?

在 iPhoneOS 3(沒錯,當時 iOS 還不叫 iOS)Safari 開始支援 <video> 標籤時,蘋果人為設定了很多限制,例如視訊無法自動播放 —— 甚至連 Meta 資訊預載入都被禁用。顯然,這是為了避免給使用者造成高額流量費用而作出的妥協,順便還能節省使用者手機電量。

隨著視訊的普及,在 iOS 8 中,蘋果放寬了對 Safari 視訊播放的限制:允許使用 preload="metadata" 來預載入視訊 Meta 資訊。但僅此而已,Safari 中的 <video> 元素仍然無法自動播放,也無法內聯播放 —— 這意味著視訊只能在使用者主動操作後才能播放,且播放時必須全屏。

至於「使用者主動操作」具體指的是哪些行為,蘋果官方有詳細的說明:

  • 點選視訊播放按鈕;
  • 觸發 touchendclickdoubleclickkeydown 事件,且在事件處理函式中直接呼叫 video.play() 方法。顯然,button.addEventListener('click', () => { video.play(); })
    滿足要求;而 video.addEventListener('canplaythrough', () => { video.play(); }) 不滿足要求;

值得注意的是,上面討論的是 iOS 自帶 Safari 的視訊播放政策。對於 iOS APP 而言,開發者在給 webview 設定 mediaPlaybackRequiresUserActionallowsInlineMediaPlayback 屬性之後,頁面中的 <video> 標籤就可以通過 autoplaywebkit-playsinline 屬性來啟用自動播放和內聯播放功能。

iOS 10 新政策

隨著視訊的進一步普及,在 iOS 10 中,蘋果終於進一步放鬆了 Safari 視訊播放政策。

自動播放

iOS 10 Safari 允許自動播放以下兩種視訊:

  • 無音軌視訊;
  • 無聲音視訊(設定了 muted 屬性);

對於這兩種型別的視訊,可以通過 <video autoplay>video.play() 兩種方式來自動播放,無需使用者主動操作。但是,如果它們在播放時變得有聲音(獲取了音軌,或者 muted 屬性被取消),Safari 會暫停播放。

通過 <video autoplay> 自動播放的視訊元素還需要滿足一個條件:在可視區域內。同樣,如果它們在播放時因為頁面滾動等原因導致不可見,Safari 也會暫停播放。

通過 video.play() 自動播放的視訊元素無需可見。video.play() 返回的是 Promise,如果不滿足自動播放條件,會觸發 reject 行為。

內聯播放

在 iOS 10 Safari 中,通過 <video playsinline> 可以讓視訊內聯播放。設定了 playsinline 屬性的視訊在播放時不會自動全屏,但使用者可以點選全屏按鈕來手動全屏;沒有設定 playsinline 的視訊會在播放時自動全屏。無論是否設定 playsinline 屬性,退出全屏後視訊都會繼續播放。

playsinline 屬性在 iOS 10 之前需要寫成 webkit-playsinline,它的瀏覽器廠商字首在 iOS 10 中被移除。但是目前 iOS 微信還不支援去掉字首的寫法,兩個屬性最好都加上。

顯然,<video autoplay> 必須和 playsinline 屬性一起使用。也就是說,只有預設內聯播放的視訊才有可能自動播放,這一點很容易理解。

一些典型應用

根據蘋果公司的文章:GIF 相比 H.264 編碼的視訊,頻寬佔用為十二倍,電池消耗為兩倍。沒有聲音的 <video> 元素很適合用作網頁背景,取代 GIF:

<video autoplay loop muted playsinline>
    <source src="image.mp4">
    <source src="image.webm" onerror="fallback(parentNode)">
    <img src="image.gif">
</video>

<script>
function fallback(video) {
    var img = video.querySelector('img');
    if (img) {
        video.parentNode.replaceChild(img, video);
    }
}
</script>

這段程式碼使用 <video> 來替代 GIF 動畫,並考慮了降級。但在 iOS 10- Safari 中,由於視訊無法自動並內聯播放,體驗很差。要解決這個問題,可以使用 CSS 的 Media Queries:

<style>
#either-gif-or-video video { display: none; }
@media (-webkit-video-playable-inline) {
    #either-gif-or-video img { display: none; }
    #either-gif-or-video video { display: initial; }
}
</style>

<div id="either-gif-or-video">
  <video src="image.mp4" autoplay loop muted playsinline></video>
  <img src="image.gif">
</div>

由於沒有聲音的 <video> 元素可以通過呼叫 video.play() 來自動播放,並且 <video> 元素不需要插入到 DOM 中,我們還可以使用 <canvas> 來做為視訊播放的容器,這樣就可以方便地修改視訊畫面了。示意程式碼如下:

var video;
var canvas;

function startPlayback() {
    if (!video) {
        video = document.createElement('video');
        video.src = 'image.mp4';
        video.loop = true;
        video.addEventListener('playing', paintVideo);
    }
    video.play();
}

function paintVideo() {
    if (!canvas) {
        canvas = document.createElement('canvas');
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        document.body.appendChild(canvas);
    }
    canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
    if (!video.paused) {
        requestAnimationFrame(paintVideo);
    }
}

startPlayback();

--EOF--

提醒:本文最後更新於 788 天前,文中所描述的資訊可能已發生改變,請謹慎使用。