Sitemap

Do you know how to force video loading in iOS Safari ?

9 min readAug 4, 2025
Press enter or click to view image in full size
Do you know how to force video loading in iOS Safari ?

Introduction

最近開發一個 image / video uploader,裡面有個基本訴求 — 當使用者選取檔案的當下要即時繪製對應的縮圖出來。這需求其實不難,透過現有支援的 Web API 便可以輕鬆完成。

其核心思想與步驟如下:

  1. 透過 Web API 先將使用者選取的 blob 格式轉換成 dataURL
  2. 利用 image 以及 video tag 讀取上一步驟取得的 dataURL。
  3. 掛上對應的監聽,在檔案完成 load 的當下透過 canvas 進行繪製。

如此一來,便可以隨心所欲的繪製出 crop / resize 的縮圖了。照理說…核心思想有了,那麼實作上應該沒什麼太大的問題才是,但是筆者卻在 iOS Safari 上踢到了鐵板~

Issue

在 iOS Safari 上筆者遇到的直接問題是 video 類型的檔案其縮圖的繪製時有時無。筆者自己在操作上若是一步一步走則基本上縮圖就會做不出來,然而若是動作快一些則有機會成功做出縮圖。

基本上這種不安定最是難除錯,總不可能每次都叫 user 各個動作銜接上要快一點才行。也因此困擾了筆者好一段時間。

Solution

由於要繪製 video 的縮圖必須要監聽 loadeddata event。待 event 觸發之後才能透過 canvas 的 drawImage() 進行繪製,而 iOS Safari 並不是可以很穩定的觸發該 event。

會造成這現象主要就是 iOS 的保護機制,除非有 user interaction 發生,不然 iOS Safari 不會輕易的去 load data,自然就無法觸發 loadeddata event 了。也就是說只要想出一個方法可以強迫 iOS Safari 進行 video loading 的行為便能迎刃而解了。

以下為對應的相關思路以及 code:

Apply autoplay to trigger video loading

筆者首先想到的便是 attribute — autoplay,這是唯一一個不需要 user interaction 就可以 trigger video play 的方法。而要讓 autoplay 可以作用的先決條件便是搭配 mute,如此一來便能有效的驅動 video loading。

<script type="module">
const video = document.createElement('video');

/* force loading */
video.autoplay = true;
video.muted = true;

video.src = 'your-video-path';
</script>

Avoid video fullscreen play

由於 iOS Safari 如果沒有特別設置的話,那麼 video play 的 default 行為便是會全螢幕播放,這對我們會造成困擾,畢竟此為非預期行為。要避免 fullscreen play 的方式便是透過 attribute — playsinline 的設置,如此便可以讓它原地播放。

<script type="module">
const video = document.createElement('video');

/* force loading */
video.autoplay = true;
video.muted = true;

/* avoid fullscreen play */
video.playsInline = true;

video.src = 'your-video-path';
</script>

Tell browser about video loading strategy

我們可以透過 attribute — preload 來告知瀏覽器是否該進行 preload,設定 auto 即表示該檔案可以被完整 download 即使 user 從頭到尾都沒有看過它。

<script type="module">
const video = document.createElement('video');

/* force loading */
video.autoplay = true;
video.muted = true;

/* avoid fullscreen play */
video.playsInline = true;

/* tell browser about video loading strategy */
video.preload = 'auto';

video.src = 'your-video-path';
</script>

Add stylesheet to hide <video />

既然要「藏」,就要藏得徹底一點,所以可以適時的設置一些 style 避免 video 露餡。

<script type="module">
const video = document.createElement('video');

/* force loading */
video.autoplay = true;
video.muted = true;

/* avoid fullscreen play */
video.playsInline = true;

/* tell browser about video loading strategy */
video.preload = 'auto';

/* Add stylesheet to hide <video /> */
video.style.visibility = 'hidden';
video.style.pointerEvents = 'none';

video.src = 'your-video-path';
</script>

<video>: The Video Embed element > preload

筆者在這裡用的分別是 visibility 以及 pointer-events 兩個屬性。透過這兩個屬性結合,讓 user 不僅看不到也摸不到。之所以不用 display 是因為這屬性很特別,在不同瀏覽器的詮釋可能會不同,若貿然設置 display: none,可能會 trigger 瀏覽器不要 loading,如此一來就違背本篇的初衷了。

Call <video /> method — load()

完成了上面這些設置後,基本上應該就可以正常驅動 video loading 了,如果擔心的話,還是可以多加上最後一道保險 — load()。直接 call video tag 原生提供的 method — load 來進行 trigger。

<script type="module">
const video = document.createElement('video');

/* force loading */
video.autoplay = true;
video.muted = true;

/* avoid fullscreen play */
video.playsInline = true;

/* tell browser about video loading strategy */
video.preload = 'auto';

/* Add stylesheet to hide <video /> */
video.style.visibility = 'hidden';
video.style.pointerEvents = 'none';

video.src = 'your-video-path';

video?.load?.();
</script>

Do not forget add 「loadeddata」event listener

最後亦是最重要的一步驟,就是不要忘記加上 loadeddata 這個 event listener。如此一來便可以在 video 完成基本的 loading 後立即觸發該 event 了。

<script type="module">
const video = document.createElement('video');

/* event listener */
video.onloadeddata = () => {
// do something you need
};

/* force loading */
video.autoplay = true;
video.muted = true;

/* avoid fullscreen play */
video.playsInline = true;

/* tell browser about video loading strategy */
video.preload = 'auto';

/* Add stylesheet to hide <video /> */
video.style.visibility = 'hidden';
video.style.pointerEvents = 'none';

video.src = 'your-video-path';

video?.load?.();
</script>

Conclusion

以上便是困擾我許久的除錯過程,簡單幾個小步驟便能有效地讓 iOS Safari 上的 video 進行 loading。

以上便是今天的分享,感謝大家的閱讀,希望所提供的分享對大家均有所助益~

Reference

--

--

Paul Li
Paul Li

Written by Paul Li

Paul is the lead programmer of the AMP project at Yahoo Taiwan and is always eager for modern web technologies. He is also focusing on UX for vivid user flow.

No responses yet