旋轉手機會讓 HLS 播放重新開始嗎?排查尺寸變化、全螢幕與播放器重建

區分手機方向變化造成的正常版面調整與真正的 HLS 重新載入;只有播放器確實需要重建時,才安全地還原播放狀態。

手機轉成橫向時,如果 HLS 影片暫停、跳播或重新載入,光憑旋轉動作還無法判斷原因。響應式版面可能只是改變尺寸;應用程式可能換掉了 <video> 元素;進入全螢幕也可能觸發另一種狀態變化;頁面也可能真的重新載入了媒體來源。

先確認究竟發生了什麼。比較直向與橫向時,盡量維持同一個獲授權測試串流、播放器版本、瀏覽器、播放位置與網路。不要只因旋轉一次手機就認定是瀏覽器缺陷,也不要在直播中不加判斷地還原舊時間戳。

驗證方法 — 2026 年 9 月 28 日: 我們查閱 MDN 關於 Screen Orientation API、視窗方向媒體查詢、HTMLMediaElement.currentTime、play() 與全螢幕的文件,也執行了確定性的 Node.js 測試夾具,涵蓋合成的尺寸變化、元件重建與狀態還原情境。這只代表文件查核與夾具邏輯測試:沒有測試實體手機、特定行動版 HLS 引擎或實際串流。夾具:scripts/test-hls-orientation-fixture.cjs。

區分版面變化與播放器重新啟動

不同訊號通常指向不同層面:

觀察到的情況可能代表什麼接下來要檢查什麼
播放器尺寸改變,但媒體時間持續前進響應式版面或影片尺寸調整CSS/版面與 resize 處理邏輯
screen.orientation 觸發 change 事件瀏覽器回報方向變化檢查事件處理器是否也改動播放器狀態
影片節點或播放器執行個體 ID 改變框架或應用程式重新掛載播放器元件 key、條件式呈現、路由狀態
重新請求了播放清單,媒體時間也接近歸零媒體來源重新載入或播放器重新初始化src 指派、播放器 load() 呼叫、effect 相依項目
播放暫停,但沒有新的播放清單請求暫停策略、可見度處理、瀏覽器行為或使用者操作記錄 paused、頁面可見度、全螢幕與媒體事件

CSS 的 orientation 媒體特性描述的是視窗形狀,並不能證明某個實體裝置感測器事件導致播放重新啟動。JavaScript 確實需要方向通知時,在支援的環境中優先使用 Screen Orientation API 的 change 事件,而非已棄用的 orientationchange。通常只要調整容器尺寸,不必重建影片元素。

修改程式碼前,先替播放器加入診斷記錄

進行簡短且獲授權的測試時,記錄帶有時間戳記的事件序列:

  1. screen.orientation.type 以及視窗寬高(若環境支援)。
  2. 穩定的應用程式播放器執行個體 ID,以及實際 <video> 節點是否更換。
  3. currentSrc 或已遮蔽資訊的來源識別、currentTime、paused、readyState 與 networkState。
  4. resize、visibilitychange、fullscreenchange、pause、playing、waiting、emptied、loadstart 與 loadedmetadata 事件。
  5. 是否重新請求了播放清單或媒體。只記錄已遮蔽資訊的主機/路徑類別;切勿儲存簽章查詢參數、Cookie 或授權要求標頭。

旋轉前記錄一次,等版面穩定後再記錄一次。如果影片節點與媒體來源都沒變,也沒有新的載入流程,就先調查版面或緩衝,不要急著歸因為播放器重啟。如果節點變了,找出替換它的呈現分支;如果媒體來源重新指派,便沿著對應程式碼路徑追查。

分開測試旋轉、全螢幕與頁面重新載入

用小型測試矩陣逐項排查,不要反覆旋轉再憑感覺判斷:

測試只改變什麼比較哪些證據
播放時從直向轉為橫向視窗/裝置方向節點識別、媒體時間、新請求、暫停狀態
暫停時從橫向轉為直向保持暫停意圖,只改變方向播放器是否意外開始播放或跳轉
不旋轉裝置,只進出全螢幕全螢幕狀態全螢幕 Promise/事件與媒體來源連續性
調整桌面瀏覽器視窗大小版面尺寸應用程式邏輯與行動裝置是否有不同反應
明確重新載入頁面文件生命週期新播放器執行個體與新的媒體來源請求是否符合預期

不要把模擬器或桌面瀏覽器的視窗模擬描述成實體裝置測試。如果你無法接觸出問題的手機/瀏覽器組合,應註明僅查核文件或尚未測試,並向回報者索取瀏覽器版本、作業系統版本、裝置類別及已遮蔽資訊的事件記錄。

盡可能維持媒體元素穩定

讓 CSS 調整播放器外框尺寸,同時保留同一個媒體元素與 HLS 執行個體。避免把方向相關值設為框架 key,或放進會讓播放器元件卸載的條件分支。除非引擎有明確記載的限制,否則也不要在每次 resize 時重建播放器。

確實無法避免拆除播放器時,只保存能安全還原的狀態:媒體來源識別、原先是否暫停、支援時的音軌/畫質偏好,以及最近觀察到的媒體時間。重新掛載媒體來源後,先等待中繼資料與可 seek 範圍,再確認目標時間是否仍有效。currentTime 是 seek 位置,不是直播內容的永久識別;播放器重建期間,直播 DVR 視窗可能已移動或過期。依產品預期,將目標限制在目前可用範圍,或回到直播邊緣。

只有在先前狀態與產品行為確實適合續播時,才呼叫 play()。它回傳的 Promise 可能遭拒絕,因此要處理失敗,並保留可用的播放按鈕。進入全螢幕同樣是非同步操作,也可能遭拒絕;應根據實際全螢幕事件更新介面,不要假設要求一定成功。

常見錯誤

  • 每次 resize 都重建播放器: 旋轉及瀏覽器工具列變化會觸發版面事件,但不表示媒體來源需要重新載入。
  • 使用會變動的元件 key: 綁定寬度/方向的 key 可能主動替換整個影片子樹。
  • 只監聽舊方向事件: 支援時使用現代 Screen Orientation API;若不需要方向資訊,也要保留合宜的降級處理。
  • 無條件 seek 到直播的舊時間: 目前直播視窗可能已不再包含該位置。
  • 呼叫 play() 卻不處理 Promise: 使用者手勢要求或瀏覽器策略可能阻止自動恢復播放。
  • 假設是全螢幕造成旋轉: 分開測試進出全螢幕與方向變化。
  • 直接分享完整要求記錄: URL 查詢參數與標頭可能含有憑證,分享前務必遮蔽。

簡潔的錯誤回報

回報裝置與作業系統、瀏覽器/版本、播放器/引擎版本、串流類型(VOD 或直播/DVR)、開始時的播放狀態與精確測試步驟。說明影片節點或播放器執行個體是否更換、播放清單請求是否重新開始,以及 currentTime、paused 或可 seek 範圍是否改變。請遮蔽串流 URL、金鑰、權杖、Cookie 與私人主機名稱。如果只是根據文件推論、沒有在指定裝置重現,也要清楚說明。

也可參考行動裝置 HLS 播放指南、應用程式切至背景或鎖定螢幕後的 HLS 播放排查,以及自動播放遭封鎖時的診斷方法。

第一手參考資料

關鍵不是「直向還是橫向」,而是「只有版面改變,還是播放器/媒體來源的生命週期也變了」。先確認這條界線,再判斷是否需要還原播放狀態。