Downie 3实战:HLS/DASH网页视频下载、分片合并与音画同步修复
发布时间:2026/10/23 19:03:05 锦皓数字建站

简介面向 macOS 用户的 Downie 3 应用包定位于网页视频下载与本地化研究场景适合需要保存 1080p、4K 等清晰度视频或希望了解这类下载工具内部资源组织方式的读者。压缩包共 432 个文件约 29.87MB以 nib、strings、png、dylib、html、plist 等为主分别对应界面布局、多语言文本、图标素材、动态库、帮助页面与配置信息并含有 ffmpeg、rtmpdump 等组件相关文件。已有 483 人学习下载。其目录保留了较完整的应用资源结构可用于查看菜单与窗口布局、多语言字符串、扩展与更新模块以及下载引擎依赖的组织方式为汉化适配、资源提取和同类工具结构分析提供参照。需注意该包为编译后的应用资源不包含可读源码。1. 网页里那个视频为什么“另存为”只得到一个几百 K 的文件上个月又有人问我同一个问题网页里放着一段课程回放右键“存储为”下来的却是个两百来 KB、后缀是 .m3u8 的文本文件双击打不开拖进播放器一片黑。这不是操作问题是网页视频这套工具链本身的分发方式决定的——真正播放的内容根本不在那个video标签的src里。Downie 3 就是冲这个场景做的 macOS 下载工具。它把页面加载过程中散落出去的媒体请求收集起来认出哪些是视频流、哪些是音频流再按索引把分片拉回本地拼成一份能直接播放、能拖进剪辑软件的完整文件支持画质和音轨挑选、字幕抓取、批量队列。适合谁需要把网页里的教程、会议回放、素材留档并且要求落地文件能离线播、能二次处理的人。如果你只是偶尔存一次、不介意画质和音轨混乱浏览器自带的录制也能凑合但要做归档和批量后面几章的参数才真正省时间。2. 拆开嗅探逻辑网页视频的三种承载方式与合并链路2.1 直链、HLS、DASH先认脸再动手很多翻车都出在没分清手上这条链接属于哪一类。三类流的下载难度差着量级工具能不能处理往往在点下“下载”之前就能判断出来。类型页面特征你拿到的第一个东西主要难点直链 MP4video src...mp4直接可见一个完整的 .mp4基本没有注意码率即可HLS地址里出现.m3u8几 KB 的 UTF-8 播放列表分片多、可能多层嵌套、音视频分离DASH地址里出现.mpd一份 XML 清单音轨视频轨分开下必须合并HLS 要分两层看。上层是 master playlist里面用#EXT-X-STREAM-INF列出好几档码率每档指向一个 media playlist下层才是真正的播放列表一串几秒长的.ts或者.m4s分片每行前面带#EXTINF标时长。所谓“下载”本质是把这些分片按顺序拉下来、按时间戳重新排好、再封装成一个文件。DASH 的思路类似只是清单换成了 XML音轨和视频轨几乎一定是分开的两条流落地前必须 mux。认脸的办法很土但有效在浏览器的开发者工具里筛 Media 类型的请求看最先出现的那个不是分片的请求多半就是清单。清单文件通常只有几 KB分片动辄几百 KB 到几 MB大小一看就分得开。2.2 Downie 3 的处理链路监听、选变体、拉分片、封装它的工作方式不是“解析网页源码找链接”而是在一个内置的轻量浏览器视图里把页面真正加载一遍同时监听所有出站的媒体请求。页面自己触发播放、加载清单的那一刻请求就被截住了。这条路子对现在这种靠脚本动态拼接地址的页面更稳但也带来一个副作用页面不开始播它就看不见——这一点在排查章节还会再提。一次完整的下载大致走这么几步加载 URL等页面发出媒体请求按Content-Type归类application/vnd.apple.mpegurl、application/dashxml、video/mp2t、video/mp4等。命中清单后递归解析把 master playlist 里所有码率变体列出来交给界面让你选或者按预设策略自动挑最高一档。对选中的 media playlist 并发拉取分片默认会开几路并行这个并发数在偏好设置里可以调网络差的时候降到 23 路反而更稳。分片落地后按序拼接读取每片的解码时间戳重新生成一条连续的时间线再做 demux mux封装成 MP4 或 MOV。若开启后处理再走一遍转码不开就直接交付封装结果速度快很多。第 4 步是整条链路的胜负手。分片拼接不是简单地cat到一块那样得到的文件时长和音画同步基本都会出问题。正规做法是让解复用器逐片读出 PTS/DTS再让复用器按新时间线写容器头。这也是为什么有些工具下完的文件用播放器能播、拖进度条却乱跳——时间线没重建干净。2.3 三个真正影响结果的开关界面上的选项不少但对成品质量有实质影响的就三个开关取值对结果的影响画质策略最高 / 询问 / 上限锁定决定从 master playlist 里挑哪一档变体锁定上限能避免误下 4K 撑爆硬盘字幕处理自动抓取 / 外挂 srt / 内封抓的是页面自带的字幕轨不是硬字幕硬字幕只能靠画面 OCR工具帮不上后处理仅封装 / 转码仅封装几秒完成画质无损转码为了兼容某些老播放器代价是时间和画质我一般把画质策略设成“询问”因为批量下载时自动挑最高经常下出一堆几百 MB 的 4K 文件而实际用途只是拿来对字幕。硬盘和带宽都不便宜尤其是要连续下几十期的时候。3. 从安装到落地一条链接走完提取、选流、命名3.1 装到应用目录并确认包完整从压缩包解出来的.app直接双击运行也能跑起来但位置在下载目录里之后用 Spotlight 找不到、系统更新也容易出岔子。标准做法是拖进/Applications。第一次打开如果被系统拦下去“系统设置 → 隐私与安全性”里放行即可别去关全局的 Gatekeeper。装完先花十秒确认这个包没被二次打包过# 查看签名链确认 Authority 一栏是完整的开发者签名而不是 ad-hoc codesign -dv --verbose4 /Applications/Downie 3.app # 让系统评估这个可执行文件是否被允许运行 spctl -a -vvv -t exec /Applications/Downie 3.appcodesign -dv输出的Authority列表如果只有一行adhoc说明这是重签过的包功能可能残缺正常应该是完整的证书链加上TeamIdentifier。spctl的预期输出是accepted加sourceNotarized Developer IDrejected就说明公证没过。这两条命令不解决任何功能问题但能让你在花了半小时排查“为什么下不了”之前先排除掉包本身有问题这种可能。3.2 单条链接的完整操作先在内置浏览器里把页面打开、让视频真正播起来几秒再回主界面。顺序反了经常什么都抓不到。复制页面 URL粘进地址栏回车等页面加载完。点一下播放按钮看到画面动起来就暂停此时请求已经发出去了。界面上会出现识别到的媒体条目点开格式列表能看到每一档变体的分辨率、编码、预估体积。选一档设定输出目录开始。进度到 100% 后不要立刻关窗口等“处理中”这步走完——合并和封装是在这一步做的提前关会得到一个只有视频轨没有音频轨的半成品。第 3 步那个格式列表是整篇里最值得多看两眼的地方。同一页面经常同时挂着 1080p 的 H.264 和 4K 的 HEVC前者兼容性好、体积小后者清晰但对播放器和剪辑软件都有要求。列表里如果某一档的体积明显偏小比如 4K 却只有 20 MB那多半是只包含视频轨或者码率被压过别贪那个分辨率。3.3 批量与浏览器联动一次要下十几期的时候一条条粘是纯浪费时间。把 URL 一行一个写进文本文件直接从菜单里导入列表队列会自己跑。真正省事的做法是装浏览器扩展在页面上点一下图标当前页就直接丢进 Downie 的队列连复制粘贴都省了。批量跑的时候有两个细节一是把并发下载数调到 2别贪多同时开五六个任务在多数家用带宽下总耗时反而更长二是提前把输出目录设成一个独立的文件夹别和已有的素材混在一起后面归档脚本才好写。3.4 输出目录与命名模板命名模板支持插变量常用的几个变量含义建议标题页面标题必选但注意标题里可能有/和:模板会自动替换日期下载日期加在开头方便按时间排序分辨率如 1080p同一内容下了多档时用来区分序号队列中的位置批量时防止重名覆盖我自己的模板是日期-标题-分辨率落地后文件名形如2024-06-12-某课程第 3 讲-1080p.mp4。按日期开头的好处是访达里默认按名称排序就是时间顺序找起来不用翻。下载目录攒到几十个文件之后手动分类就没意义了挂个脚本按月归档#!/usr/bin/env bash set -euo pipefail # 下载落地目录与归档根目录按实际路径改 SRC$HOME/Movies/Downie DST$HOME/Movies/Archive # 只处理成品文件跳过处理中的临时文件 find $SRC -maxdepth 1 -type f \( -iname *.mp4 -o -iname *.mkv -o -iname *.mov \) -print0 | while IFS read -r -d f; do # 用文件修改时间生成 YYYY-MM 子目录 d$(date -r $f %Y-%m) mkdir -p $DST/$d # -n 防止同名覆盖重名会自动加后缀 mv -n $f $DST/$d/ done-print0配read -d 是为了扛住文件名里的空格和中文这是 macOS 上跑批量脚本最容易踩的一脚。date -r取的是文件修改时间不是创建时间因为合并后的成品修改时间才是落地时间。mv -n保证重名时不覆盖宁可多出一份也不丢文件。4. 画质、音轨与容器把“要不要 4K”变成可判断的参数4.1 码率、编码、容器三件事别混三个词经常被当成一件事说实际各管一摊。容器是外壳MP4、MOV、MKV决定能装几条轨编码是压缩方式H.264、HEVC、AV1决定解码开销和兼容性码率是每秒塞多少数据直接决定体积和画质上限。分辨率H.264 常见码率HEVC 常见码率一小时约合体积HEVC720p23 Mbps1.22 Mbps0.60.9 GB1080p48 Mbps2.55 Mbps1.12.2 GB2160p1525 Mbps815 Mbps3.66.7 GB同样是 1080p4 Mbps 和 8 Mbps 在静止画面上几乎看不出差别但一到快速运动的镜头低码率那档就会出现明显的块状糊。判断办法不是看分辨率数字是看格式列表里给出的码率低于 3 Mbps 的 1080p 要心里有数。容器这块MP4 兼容性最好剪辑软件、播放器、手机都能吃MKV 能装更多轨但部分播放器不认。默认选 MP4 就够除非你要保留多条音轨和字幕轨一起分发。4.2 HLS 合并后的时间戳修正分片拼出来的文件偶尔会出现音画不同步或者进度条拖到某个位置就卡住。原因通常是分片之间的 PTS 不连续——有些站点为了防盗链会把时间戳重置拼接时就产生了一段跳跃。这时候不用重下重新封一遍就能救回来# 让 ffmpeg 重新生成缺失的时间戳而不是沿用分片里的原始值 ffmpeg -fflags genpts -i input.mp4 -c copy -movflags faststart output.mp4-fflags genpts是关键它让解复用器在遇到时间戳断层时按帧率补算而不是直接照搬。-c copy表示不重新编码所以整个过程只做读写速度取决于硬盘几分钟就能跑完一小时的片子。-movflags faststart把索引挪到文件头网页播放器可以边下边播本地播放器拖进度条也会更跟手。如果加了genpts还是不同步那就是音频采样率和视频帧率对不上得单独处理音轨-af aresampleasync1让音频重采样对齐。这种修法会破坏音频的原始精度只在确实救不回来的时候用。4.3 字幕与音轨外挂还是内封抓下来的字幕默认是外挂 srt改起来方便但发给别人容易漏。要固化进文件的话用 MP4 的mov_text格式内封# 把外挂字幕封进 MP4不重新编码视频和音频 ffmpeg -i input.mp4 -i subtitle.srt \ -c:v copy -c:a copy -c:s mov_text \ -metadata:s:s:0 languagechi output.mp4-c:v copy -c:a copy保证视频音频原样搬过去只有字幕轨是新写的秒级完成。-metadata:s:s:0给第一条字幕轨打语言标签播放器才会在菜单里显示“中文”而不是“字幕 1”。MKV 容器用-c:s srt兼容面更宽。多音轨的情况类似先ffprobe看清楚哪条是原声哪条是配音再用-map 0:a:1指定保留哪一条。不定-map的话默认只留第一条多音轨素材经常就这么静悄悄丢了一条。5. 常见问题排查五条现场记录与对应动作5.1 链接粘进去一直停在“等待中”现象地址栏回车后页面能正常显示但媒体条目始终不出现或者只闪一下就没了。原因多数是页面在用户交互之后才发出媒体请求——播放按钮绑了脚本不点就不请求。另一种情况是清单走了加密#EXT-X-KEY带METHODAES-128工具拿不到密钥就会静默放弃。解决先在内置浏览器里点播放让画面动起来几秒再回主界面。如果播放正常但依然抓不到去开发者工具里看一眼清单里有没有EXT-X-KEY行有的话说明这条流是加密分发的工具侧解决不了别在这上面耗时间。5.2 下载完成音画不同步现象画面和声音差半秒到两秒越往后差得越多拖进度条之后更明显。原因分片时间戳不连续拼接时按原始 PTS 硬拼误差累积。或者源流本身是变帧率的合并后按固定帧率解释。解决先按 4.2 节那条命令重封一遍八成能解决。仍然不行就用ffprobe看两条流的时长差# 分别输出视频流和音频流的时长差值超过 0.2 秒基本就是拼接问题 ffprobe -v error -select_streams v:0 -show_entries streamduration -of csvp0 input.mp4 ffprobe -v error -select_streams a:0 -show_entries streamduration -of csvp0 input.mp4两个数差得多说明有一路分片丢了或者重复了只能重下。5.3 4K 下下来播放器黑屏现象文件体积对得上播放器打开有声音没画面或者干脆全黑。原因4K 那档多半是 HEVC 编码老版本播放器、部分剪辑软件的解码器不认。另一种可能是选了只含视频轨的变体音频在另一条流里没合并进来。解决先用ffprobe确认编码和轨道数codec_namehevc且只有一条流就是播放器问题加音轨缺失的双重打击。换播放器能验证要长期用还是转成 H.264# 转成 H.264 并保留原分辨率crf 20 在画质和体积之间比较平衡 ffmpeg -i input.mp4 -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k output.mp4转码是纯 CPU 活一小时 4K 素材在笔记本上跑小半天很正常别指望快。5.4 下下来的文件比预期小很多现象明明选了最高画质落地文件只有几十 MB画面糊得厉害。原因master playlist 里的“最高档”未必真的是最高有些站点会把 4K 放在单独的清单里或者用不同的路径也可能你选中的那档本身就是低码率预览流真正的高码率要另外触发。解决回到格式列表逐档对比码率而不是只看分辨率标签。列表里如果有两档都是 1080p选码率高的那档。实在拿不准就先下一小段试看确认清晰度再批量跑。5.5 中断后重下从零开始现象网络抖了一下任务失败重新开始进度条从 0 走之前下的白费。原因部分站点的分片响应不带Content-Length工具没法判断已下载的片段是否完整只好整条重来。解决这类流直接交给 ffmpeg 去拉它支持从断点续传分片# 直接对清单地址拉流-c copy 不重新编码断线后重跑会从已完成的片段继续 ffmpeg -protocol_whitelist file,http,https,tcp,tls \ -i https://example.com/path/master.m3u8 \ -c copy -bsf:a aac_adtstoasc output.mp4-protocol_whitelist是必须加的白名单不声明的话 ffmpeg 会拒绝走网络协议。-bsf:a aac_adtstoasc处理的是 HLS 里 AAC 音频的 ADTS 头不加的话封进 MP4 后部分播放器会没声音。这条命令不挑画质拉的是清单里默认那一档需要指定变体得先手动改清单内容。6. 进阶把下载接进归档流顺手做一次校验批量下载和归档这件事真正省时间的不是工具本身是下完之后那一步校验。我现在的习惯是每批跑完立刻做一次抽检# 一次性输出编码、分辨率、帧率、码率和轨道类型异常值一眼能看出来 ffprobe -v error \ -show_entries streamindex,codec_type,codec_name,width,height,r_frame_rate,bit_rate \ -of csvp0 input.mp4正常的输出应该能看到两行一行video带分辨率和帧率一行audio带码率。只有一行就说明有轨丢了bit_rate是个离谱的小数字说明码率异常。这个检查十秒钟比事后发现三十个文件全都没声音要划算得多。清单文件跑批的做法也简单把 URL 一行一个存成list.txt配合 3.4 节的归档脚本一条流水线就是“导入列表 → 队列跑完 → 归档脚本按月分目录 → ffprobe 抽检”。整个流程里唯一需要人盯着的是格式列表那一步其余都能挂后台。有个模板变量值得单独说如果你经常下同一系列的内容把序号变量放进文件名配合归档脚本的月份目录一年下来目录结构会非常干净找某一期时不用回忆是哪天下的。血泪教训是去年一次批量归档图省事没做校验等要剪的时候才发现其中十几期只有视频轨——那批源站把音频放在独立的 DASH 流里工具选中的变体恰好只含视频。从那以后我每次批量跑完都强制走一遍 ffprobe 抽检哪怕只有五个文件也照跑。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。