简介:面向 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:先认脸再动手
很多翻车都出在没分清手上这条链接属于哪一类。三类流的下载难度差着量级,工具能不能处理,往往在点下“下载”之前就能判断出来。
| 类型 | 页面特征 | 你拿到的第一个东西 | 主要难点 |
|---|---|---|---|
| 直链 MP4 | <video 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/dash+xml、video/mp2t、video/mp4等)。 - 命中清单后递归解析,把 master playlist 里所有码率变体列出来,交给界面让你选,或者按预设策略自动挑最高一档。
- 对选中的 media playlist 并发拉取分片,默认会开几路并行,这个并发数在偏好设置里可以调,网络差的时候降到 2~3 路反而更稳。
- 分片落地后按序拼接,读取每片的解码时间戳,重新生成一条连续的时间线,再做 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 --verbose=4 "/Applications/Downie 3.app" # 让系统评估这个可执行文件是否被允许运行 spctl -a -vvv -t exec "/Applications/Downie 3.app"codesign -dv输出的Authority列表如果只有一行adhoc,说明这是重签过的包,功能可能残缺;正常应该是完整的证书链加上TeamIdentifier。spctl的预期输出是accepted加source=Notarized Developer ID,rejected就说明公证没过。这两条命令不解决任何功能问题,但能让你在花了半小时排查“为什么下不了”之前,先排除掉包本身有问题这种可能。
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 常见码率 | 一小时约合体积(HEVC) |
|---|---|---|---|
| 720p | 2~3 Mbps | 1.2~2 Mbps | 0.6~0.9 GB |
| 1080p | 4~8 Mbps | 2.5~5 Mbps | 1.1~2.2 GB |
| 2160p | 15~25 Mbps | 8~15 Mbps | 3.6~6.7 GB |
同样是 1080p,4 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 aresample=async=1让音频重采样对齐。这种修法会破坏音频的原始精度,只在确实救不回来的时候用。
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 language=chi 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带METHOD=AES-128),工具拿不到密钥就会静默放弃。
解决:先在内置浏览器里点播放,让画面动起来几秒再回主界面。如果播放正常但依然抓不到,去开发者工具里看一眼清单里有没有EXT-X-KEY行,有的话说明这条流是加密分发的,工具侧解决不了,别在这上面耗时间。
5.2 下载完成音画不同步
现象:画面和声音差半秒到两秒,越往后差得越多,拖进度条之后更明显。
原因:分片时间戳不连续,拼接时按原始 PTS 硬拼,误差累积。或者源流本身是变帧率的,合并后按固定帧率解释。
解决:先按 4.2 节那条命令重封一遍,八成能解决。仍然不行就用ffprobe看两条流的时长差:
# 分别输出视频流和音频流的时长,差值超过 0.2 秒基本就是拼接问题 ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 input.mp4 ffprobe -v error -select_streams a:0 -show_entries stream=duration -of csv=p=0 input.mp4两个数差得多,说明有一路分片丢了或者重复了,只能重下。
5.3 4K 下下来播放器黑屏
现象:文件体积对得上,播放器打开有声音没画面,或者干脆全黑。
原因:4K 那档多半是 HEVC 编码,老版本播放器、部分剪辑软件的解码器不认。另一种可能是选了只含视频轨的变体,音频在另一条流里没合并进来。
解决:先用ffprobe确认编码和轨道数,codec_name=hevc且只有一条流,就是播放器问题加音轨缺失的双重打击。换播放器能验证,要长期用还是转成 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 stream=index,codec_type,codec_name,width,height,r_frame_rate,bit_rate \ -of csv=p=0 input.mp4正常的输出应该能看到两行:一行video带分辨率和帧率,一行audio带码率。只有一行就说明有轨丢了,bit_rate是个离谱的小数字说明码率异常。这个检查十秒钟,比事后发现三十个文件全都没声音要划算得多。
清单文件跑批的做法也简单:把 URL 一行一个存成list.txt,配合 3.4 节的归档脚本,一条流水线就是“导入列表 → 队列跑完 → 归档脚本按月分目录 → ffprobe 抽检”。整个流程里唯一需要人盯着的是格式列表那一步,其余都能挂后台。
有个模板变量值得单独说:如果你经常下同一系列的内容,把序号变量放进文件名,配合归档脚本的月份目录,一年下来目录结构会非常干净,找某一期时不用回忆是哪天下的。
血泪教训是去年一次批量归档,图省事没做校验,等要剪的时候才发现其中十几期只有视频轨——那批源站把音频放在独立的 DASH 流里,工具选中的变体恰好只含视频。从那以后我每次批量跑完都强制走一遍 ffprobe 抽检,哪怕只有五个文件也照跑。希望帮到你。
本文还有配套的精品资源,点击获取