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 的态度。法律和技术底线详见 流媒体下载合法性指南。