影片直連下載失敗怎麼辦?MP4、WebM 排查

排查影片直連回傳 403、404、CORS、空檔案、格式不支援、無法斷點續傳等問題,附帶 curl 診斷程式碼。

影片直連就是那種「一個 URL 一個檔案」的下載:MP4、WebM、MOV、MKV,點開就能播放,拿到網址就能存。跟 M3U8、MPD 那種要拼分片再合併的串流完全是兩回事。這篇文章把直連下載最常見的坑一個一個過,配上 curl 指令幫你定位到底卡在哪。

先搞清楚:直連和串流不是一回事

直連下載失敗的原因,一半以上是把串流的思考方式套到直連上。先分清這兩類東西:

直連檔案HLS / DASH 串流
結構單一檔案清單 + 成百上千分片
下載一個請求搞定逐片下載再合併
失敗特徵整包失敗(403/404/空檔案)部分分片失敗、合併後花畫面無聲
排查方向請求標頭、網址有效性、格式清單、分片、金鑰、合併

所以下面這些症狀基本只屬於直連。如果你的影片其實是 HLS 或 DASH 串流,先去對應文章:M3U8(HLS)下載失敗排查DASH 下載後無聲排查。直連的偵測與格式範圍見 影片嗅探 — 支援的影片格式影片嗅探 — 直接影片檔案

快速處理

先照這套流程走一遍,能解決八成問題:

  1. 打開影片實際播放的網頁,播放幾秒,確保影片真的有載入。
  2. 打開 FlowPick 擴充功能,從資源清單裡挑影片檔案,別選縮圖或封面。
  3. 確認右側預覽能正常播放,格式無誤後點下載。

如果還是不行,照下面的症狀對號入座。擴充功能裡怎麼選檔案、怎麼存目錄,見 使用方法 — 下載單一資源

症狀一:403 Forbidden

現象:下載立刻失敗,或直接用瀏覽器打開這個網址也是 403。

直連影片很少真的「沒權限」,大多是請求標頭不對。源站常見的驗證有:

  • Referer 驗證:要求請求來自特定頁面,空的 Referer 或陌生來源直接拒絕。
  • Cookie / 登入狀態:沒帶登入 Cookie,或登入狀態已過期。
  • 臨時權杖:URL 裡帶 ?token=xxx&expires=yyy,過期後回傳 403。
  • 地區 / IP 限制:CDN 依出口 IP 決定給不給。

先抓出直連網址,用 curl 重現一下(把網址換成你自己的):

# 不帶任何標頭的裸請求,看回傳什麼
curl -s -o /dev/null -w "裸請求: %{http_code}\n" "https://cdn.example.com/videos/lesson1.mp4"

# 帶上頁面 Referer 再試
curl -s -o /dev/null -w "帶Referer: %{http_code}\n" \
  -H "Referer: https://www.example.com/course/123" \
  "https://cdn.example.com/videos/lesson1.mp4"

如果帶上 Referer 就好了,代表是防盜連驗證。在瀏覽器擴充功能裡解決:擴充功能運行在來源頁面上下文,Referer 和 Cookie 自動帶上,v1.1.1 之後的版本還內建了防盜連代理,預覽和下載都會自動補齊請求標頭並驗證回應,不會把 HTML 錯誤頁當影片存下來。線上工具沒有這個能力——它運行在自己的網域下,帶不了目標網站的 Cookie。升級方法見 安裝指南 — 擴充功能更新,防盜連代理的細節見 FlowPick v1.1.1 更新

症狀二:404 網址過期或檔案已刪除

現象:之前明明能下,今天 404;或別人發的直連下不了。

常見三種情況:

  • 臨時簽名 URL 過期:很多雲端儲存(阿里雲 OSS、騰訊雲 COS 等)的直連帶有效期,過幾分鐘到幾小時就失效。
  • 檔案被清理:上傳者刪了檔案,或 CDN 快取被清掉。
  • 拿到了錯誤的網址:複製的是播放頁網址,不是檔案直連。

驗證一下網址本身是不是活的:

curl -sI "https://cdn.example.com/videos/lesson1.mp4" | head -n 8

看回傳的狀態碼和 Content-Type。如果 Content-Typetext/html,代表這個網址指向的是一個網頁而不是影片。網址真的失效就沒辦法——回到原影片頁面重新偵測一次,拿新的直連再下。

症狀三:CORS 跨網域攔截

現象:線上工具報 CORS 錯誤,或下載出來的檔案是壞的。

這是線上工具特有的問題。線上工具跑在 flowpick.com 自己的網域下,瀏覽器同源政策會攔住跨網域讀取。擴充功能不一樣,它拿的是擴充功能權限,不受同源政策限制,偵測範圍也更廣。兩者差異見 線上工具 — 與擴充功能的區別影片嗅探 — 擴充功能與線上工具的偵測差異

解決辦法就一句:別用線上工具下直連,改用擴充功能。擴充功能在影片原頁面裡工作,Referer、Cookie、跨網域問題一次全解決。

症狀四:下載到的是空檔案或打不開

現象:下載「成功」,但檔案只有幾 KB,或播放器打不開。

十有八九是選錯對象了:選中的不是影片檔案,而是 HTML 頁面、縮圖、封面圖或預覽介面的回應。這類回應的特徵是體積很小,且 Content-Typetext/htmlimage/*

用 curl 看這個網址到底回傳什麼:

curl -sI "https://cdn.example.com/cover/lesson1.jpg"
# 看 Content-Type 和 Content-Length

如果指向的是 text/html,那它只是個網頁。回到擴充功能,從資源清單裡選 video/mp4video/webm 這類 video/* 類型的項目,再確認右側預覽能播放後再下載。如果檔名帶亂碼或不帶副檔名,下載後手動補上 .mp4 再試。

症狀五:無法暫停、無法斷點續傳

現象:下載能開始,但點了暫停再繼續,又從 0 開始;或根本沒有暫停按鈕。

這跟伺服器支不支援 HTTP Range 有關。Range 允許用戶端只請求檔案的一部分,暫停續傳就靠它。伺服器沒開 Range,瀏覽器就只能整檔下載,自然沒法斷點繼續。

測一下伺服器支不支援:

curl -s -o /dev/null -w "Range請求: %{http_code}\n" \
  -H "Range: bytes=0-1023" \
  "https://cdn.example.com/videos/lesson1.mp4"
# 206 = 支援 Range,可以斷點續傳
# 200 = 回傳了完整檔案,代表不支援 Range

回傳 206 代表支援;回傳 200(完整檔案)則不支援。不支援也照樣能下載,只是不能斷點繼續,網路不好的時候建議一次下完別中斷。這是伺服器能力問題,不是工具問題。

症狀六:格式或編碼不支援

現象:檔案下下來了,體積正常,但播放器報「格式不支援」或黑畫面。

先分清容器編碼兩個概念:.mp4 是容器,裡面裝的可能是 H.264,也可能是 H.265/HEVC 或 AV1。容器支援不等於編碼支援,播放器要能解碼裡面那層編碼才能放出來。常見坑:

情況表現處理
MP4 內是 H.265/HEVC老播放器黑畫面轉成 H.264 或換播放器
WebM 內是 AV1硬體解碼不支援轉成 H.264/VP9
高畫質直連很大瀏覽器記憶體吃緊見下一節

偵測和下載直連時 FlowPick 會讀出編碼資訊。如果確認是編碼不支援,用 格式轉換 轉成相容性更好的 H.264 MP4 即可。你的播放器到底支援什麼,可以參考 瀏覽器相容性

症狀七:大檔案或瀏覽器卡住

現象:幾百 MB 的直連下載到一半頁面卡死,或下載完後瀏覽器明顯變卡。

瀏覽器裡存檔案要過記憶體。FlowPick 優先走 File System Access API(選目錄後串流寫入,不佔記憶體),不支援時退回 StreamSaver 或 Blob。其中 Blob 模式要把整個檔案先裝進記憶體,大檔案就可能卡住。Blob 模式的具體硬限制見 已知限制 — Blob 模式硬限制,對應的已知問題見 已知限制 — 大檔案 Blob 下載可能卡住

對策:

  • 優先選「選擇儲存目錄」,觸發 File System Access API,大檔案也能串流寫。
  • 沒這個按鈕的瀏覽器(或行動裝置),把影片切到較低畫質再下。
  • 真的要下大檔案,一次只下這一個,別同時掛一堆下載。

診斷工具速查

F12 打開開發者工具,照這張表快速定位:

想確認什麼面板做法
直連請求回傳幾Network篩選 mp4 / webm,看 Status 欄
回傳的是不是影片Network看回應標頭的 Content-Type 是否為 video/*
有沒有帶 Referer/CookieNetwork → 請求 → Headers看 Request Headers
是不是被 CDN 限速Network看單一請求的耗時和下載速度

如果你懷疑是瀏覽器環境問題,在 Console 裡跑這段產生環境報告,回饋時貼出來:

const report = {
  ua: navigator.userAgent,
  fsa: 'showDirectoryPicker' in window,
  sab: typeof SharedArrayBuffer !== 'undefined',
  coi: self.crossOriginIsolated,
  storage: await navigator.storage?.estimate().catch(() => null),
  ts: new Date().toISOString(),
}
console.log(JSON.stringify(report, null, 2))

報告只含瀏覽器環境資訊,不涉及任何瀏覽記錄或個人資料。

什麼時候真的下不了

  • DRM 保護:Widevine / PlayReady / FairPlay 加密的內容,FlowPick 明確不支援,也不做破解。
  • 登入或付費牆:不登入/不購買就拿不到直連網址的內容。
  • 介面私有化:影片資料走私有協定或需要應用內簽名,不發普通直連。
  • 網址永久失效:源站已刪除檔案。

這些是設計上不支援,不是 bug。遇到就換個思路:錄影或聯絡內容方取得授權。更完整的邊界清單見 已知限制

相關文件