【茶包射手日記】某些 YouTube 影片無法在某些網頁內嵌播放
| | 0 | |
YouTube 支援在網頁內嵌 IFrame,讓你可在自家網頁直接播放 YouTube 影片,我的部落格文章有時也會用。
最近幫忙查了一起案例,某些 YouTube 影片無法在某些網頁內嵌播放,必須單獨在 YouTube 開啟才能看。只有某些影片不能播,而且相同的網頁可能放在 A 網站 OK,放在 B 網站不行。
用以下 HTML 重現問題。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>YouTube Embedded Player</title>
</head>
<body>
<iframe src="https://www.youtube.com/embed/K1uuK4QdvGY"></iframe>
</body>
</html>
網頁放到 JSBin 可內嵌播放。
存成本機檔案用瀏覽器開啟不行。
用 VSCode Live Server 不行。
掛到本機 IIS 又可以。
本機 IIS 但不用 locahost 改用 127.0.0.1 則又不行。
這堆測試結果搞到我都暈了,摸不到頭緒。事情的轉機在於:我做了一個實驗,把原本可正常內嵌播放的 localhost:80 用 devtunnel 導成對外 HTTPS,影片就不能播放了。同時有正常版跟異常版活體就好辦了,問題八成為網站送出的 HTTP Header 有關,對照 devtunnels 與本機 IIS 送出的 Header,經交叉比對並用 ASPX 模擬,我找到關鍵 - devtunnel 的回應包含 Referrer-Policy: same-origin 而原本 IIS 沒有,這是無法內嵌播放的關鍵:
用以下 ASPX 程式可重現問題:
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Response.Headers.Add("Referrer-Policy", "same-origin");
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Embedded YouTube Video</title>
</head>
<body>
<iframe src="https://www.youtube.com/embed/K1uuK4QdvGY"></iframe>
</body>
</html>
以上程式加了 Response.Headers.Add("Referrer-Policy", "same-origin");
會無法播放,拿掉便正常,反覆驗證後,確認這是問題根源無誤。
有了關鍵字,很快找到相關文件及解法。比較完整的是這篇:Youtube iframe 嵌入錯誤: 「無法播放影片 在 YouTube 上觀看」 by 琳的備忘手札
簡單總結:
- 有音樂版權宣告的 YouTube 影片需要正確傳送 Referrer (至少要有 origin) 才能在 IFrame 內嵌播放,這解釋了為什麼問題只發生在特定影片跟特定網站(設了 Referrer-Policy 禁發 Referrer)
- 內嵌頁面必須對外公開(YouTube 可存取得到,localhost 是特例),且 Domain 不可以是 IP
- 我們可透過
<meta name="referrer" content="strict-origin-when-cross-origin" />
或 IFrame 的 referrerpolicy 屬性 覆寫 HTTP Header 設定 - Referrer Policy 有以下選項,說明如下:(感謝 GPT 提供)
- no-referrer
不發送任何 Referer 資訊,隱私保護最大化 - no-referrer-when-downgrade
從 HTTPS 網站請求 HTTP 資源時不發送 Referer,其他情況下發送完整的 Referer。瀏覽器的預設值,適用於大多數情況 - same-origin
對同一來源(域名)內部請求發送 Referer,跨來源請求不發送。保護跨來源請求隱私,但允許內部來源間共享 Referer 資訊 - origin
發送來源基本資訊(不包含路徑),適用需要基本來源資訊但不需要詳細路徑資訊時 - strict-origin
發送來源的基本資訊,但僅 HTTPS 網站請求 HTTPS 資源時發送,從 HTTPS 請求 HTTP 資源時不發送。適用需要在 HTTPS 連接中保護隱私,但允許同等安全層級的來源資訊共享 - origin-when-cross-origin
相同來源時發送完整的 Referer,跨來源請求只發送來源基本資訊。適用在跨來源請求中隱藏詳細資訊,但允許內部來源的詳細資訊共享 - strict-origin-when-cross-origin
相同來源請求發送完整 Referer,跨來源 HTTPS 請求發送來源基本資訊,HTTPS 請求 HTTP 資源則不發送任何資訊。適用最高級別的隱私保護,確保從安全來源到非安全來源不發送任何資訊 - unsafe-url
無論何種請求都發送完整的 Referer,包括 URL 的整個路徑,不建議使用。
- no-referrer
因此,本案例只需改寫成 <iframe src="https://www.youtube.com/embed/K1uuK4QdvGY" referrerpolicy="no-referrer-when-downgrade"></iframe>
應該就能過關了。我則學到一些 HTML 新知識。
Some YouTube videos may not play in embedded iframes due to Referrer-Policy settings. Specifically, the “same-origin” policy can block playback. Solutions include adjusting the referrer policy using meta tags or iframe attributes.
Comments
Be the first to post a comment