DASH 影片沒有聲音怎麼辦?MPD 排查
DASH 下載出來沒聲音,十之八九是踩到同一個坑:影片和音訊是兩條獨立的軌道,你只把影片軌道拖回家了。這篇照 MPD 的實際處理流程拆解,告訴你聲音是在哪一步弄丟的、怎麼撈回來。
先理解:DASH 為什麼把聲音弄丟
MPD 不是「一條 URL 拉一個檔案」那麼簡單。它是一棵 XML 樹,用 AdaptationSet 把影片、音訊、字幕分成不同群組,每組裡再按位元率/畫質掛多個 Representation。看結構就懂了:
MPD
├── AdaptationSet: Video
│ └── Representation 1080p
│ ├── init segment(fMP4 頭,含編解碼器設定)
│ ├── segment-001.m4s
│ ├── segment-002.m4s
│ └── ...
└── AdaptationSet: Audio
└── Representation 128kbps
├── init segment
├── segment-001.m4s
├── segment-002.m4s
└── ...
↓
FFmpeg WASM 合併
↓
output.mp4
這和 HLS 完全是兩種脾氣。HLS 通常把音影片塞進同一個 TS 分片,你拉分片就能拼出有聲的;DASH 走 fMP4,音影片分開傳,下載時必須同時抓兩條軌道再合併。你的工具只認影片軌道的話,出來就是一部默劇。兩者差異對比見 影片嗅探 — 支援的影片格式,MPD 的 AdaptationSet、Representation、SegmentTemplate 完整層級拆解見 DASH 深度篇。
快速處理
照這個順序先走一遍,能解決大多數情況:
- 打開原影片頁面,讓影片播起來(很多網站不播放就不發 MPD)。
- 用 FlowPick 偵測 MPD 清單。
- 在軌道列表裡同時勾選影片軌道和音訊軌道。
- 挑一條和影片畫質匹配的音訊(語言、位元率對上就行)。
- 等合併步驟跑完,再打開聽聲音。

照這個流程還啞,就按下面的症狀對號入座。
症狀一:只選了影片軌道
表現:下載飛快,檔案幾 MB 到幾十 MB,播放器打開有畫面沒聲音。
最常見,沒有之一。DASH 下載器預設按位元率降序排軌道,很多人只勾了最上面那行 1080p,沒注意到再往下的「Audio」是另一組。用 ffprobe 一句話確認檔案裡到底有沒有音訊流:
ffprobe -hide_banner output.mp4
輸出裡只有 Stream #0:0: Video、沒有 Stream #0:1: Audio,就是這個問題。回到 MPD,把音訊軌道一起勾上再下。FlowPick 會自動匹配同語言、位元率最高的音訊軌,不用你手動算。
症狀二:MPD 裡壓根沒有音訊軌道
表現:軌道列表裡翻遍了都沒有音訊,或者只有一條「無聲」的影片流。
MPD 是動態產生的,同一個影片在不同地區、不同登入狀態下拿到的清單可能不一樣。常見三種:
- 地區限制:某個地區只下發影片軌道,或只下發某一種語言。
- 登入狀態:沒登入時 MPD 裡沒有音訊
AdaptationSet,登入後才冒出來。 - 請求頭:部分網站靠 Referer/Cookie 決定要不要給你音訊軌。
把 MPD 位址摳下來用 curl 驗證(位址換成你自己的):
curl -sL -H "Referer: https://www.example.com/watch/123" \
"https://cdn.example.com/master.mpd" > master.mpd
# 看清單裡到底有沒有音訊 AdaptationSet
grep -c 'AdaptationSet.*type="audio"' master.mpd
# 輸出 0 = 真沒有音訊軌;>0 = 有,是沒勾上(回到症狀一)
輸出 0 的話,回到原影片頁面、保持登入狀態,用擴充功能重新偵測。AdaptationSet、Representation、SegmentTemplate 這些節點具體長什麼樣,MPD 入門 講得比教科書清楚。
症狀三:CORS / 403 / 404
表現:影片軌下得動,音訊分片一拉就 403/404,或者線上工具直接報 CORS。
線上工具跑在 flowpick.com 域名下,帶不上目標站的 Cookie 和原頁面 Referer,來源端一驗證就攔——這是防盜連,不是沒聲音本身。處理方式:
- 有防盜連的網站,改用擴充功能,在原影片頁面裡操作,Referer/Cookie 自動帶上。
- v1.1.1+ 的擴充功能自帶防盜連代理,預覽和下載會自動補 Referer 和 Cookie,還會在存檔前檢查回應,避免把 HTML 錯誤頁存成媒體。
- 音訊分片 URL 帶
?token=xxx&expires=yyy的,幾分鐘就過期,趁熱下,別中途去吃飯。
症狀四:音訊分片下載不全
表現:軌道都勾了,合併後還是沒聲音或聲音斷斷續續,控制台裡能翻到幾個音訊分片的失敗記錄。
音影片是分開下的,影片全下完了,音訊可能還剩一兩片沒到位,合併時只能帶殘的進去。先確認到底是不是分片掉了:
# 逐個探音訊分片的 HTTP 狀態(把 URL 換成你的)
for i in $(seq 1 200); do
url="https://cdn.example.com/audio/seg-$i.m4s"
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
echo "seg-$i.m4s -> $status"
done
出現 403/404/5xx,就是有分片拉不到。對策:
- 網路會抖的話把並行數調低(2-3),減少掉包重試壓力,音訊軌本來就沒幾個分片,慢點無所謂。
- 個別分片 5xx 的,等一會兒重下,來源端可能正在做 CDN 回源。
- 一直斷在同一片,多半是臨時 Token 過期,回原頁面重新偵測拿新 MPD。
並行數與效能的關係見 下載引擎架構 — 並行數與效能的關係,重試和退避邏輯見 下載引擎架構 — 重試機制。
症狀五:檔案大小正常但沒聲音
表現:檔案不小,ffprobe 裡音訊流也在,但播放就是沒聲音,或音畫對不上。
這種一般不是下載問題,是合併或編碼環節的事:
| 表現 | 原因 | 處理 |
|---|---|---|
| 有音訊流但播放無聲 | 混合器沒把音訊配對好(H.265 影片 + 異常音訊標識) | 換輸出格式,或用 ffmpeg 命令列重裝一遍 |
| 音畫不同步 | SegmentTimeline 時間戳不連續 | 用 FFmpeg 重新編碼修復 |
| VLC 能播、系統播放器不能播 | 播放器缺解碼器(VP9/AV1/Opus) | 換 VLC / PotPlayer,不是檔案問題 |
用 ffmpeg 把音訊單獨抽出來,驗證它本身是不是好的:
ffmpeg -i output.mp4 -map 0:a -c copy audio.m4a
# 抽出來的 audio.m4a 能正常播放 → 音訊沒壞,問題在合併環節
FFmpeg WASM 的轉封裝原理見 格式轉換 — FFmpeg WASM 轉封裝,音影片合併流程見 格式轉換 — 音影片分離合併。
症狀六:DRM 保護
表現:MPD 裡有 <ContentProtection>,或播放前要載入 Widevine/PlayReady 的 CDM 模組。
這種下不了,FlowPick 明確拒絕處理——這是特性不是 bug。DRM 是版權方用硬體級加密鎖死的,聲稱能解 DRM 的下載器要嘛在撒謊要嘛違法。別浪費時間和磁碟。法律與技術底線見 串流下載合法性指南。
診斷工具速查
F12 打開開發人員工具,幾個高頻檢查點:
| 檢查 | 面板 | 操作 |
|---|---|---|
| MPD 有沒有被請求 | Network | 過濾框輸入 mpd,重新整理頁面播放影片 |
| 音訊分片狀態碼 | Network | 過濾框輸入 .m4s,看 Status 欄和 size |
| 請求帶了什麼頭 | Network → 選中請求 → Headers | 看 Request Headers 的 Referer/Cookie 在不在 |
| 合併報錯 | Console | 搜 ffmpeg 或 wasm |

環境資訊有疑問的,可以在 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)
- 需要破解登入或付費牆的內容
- MSE 自訂分片、不發原生 MPD 的網站
- 私無損或單獨加密的多音軌串流
這些是設計上不支援,不是 bug。碰到這些,正確的行為是報錯而不是靜默產出壞檔案——這也是 FlowPick 的態度。法律與技術底線詳見 串流下載合法性指南。