B站下载的视频画质模糊怎么办:不是大会员的事

下完的视频画面发糊,你会先怀疑什么?

我第一反应是会员。B站那几档画质门槛摆在那儿,1080P 以上要大会员,下载下来看着就像「权限不够所以给你降了画质」。

那天不是。我拿 ffprobe 量了一遍那个文件:

codec_name=av1
width=1920  height=1078
bit_rate=583155
duration=15429s (4.3小时)  size=1.27GB

分辨率是 1920,码率只有 583 kbps。一个 4.3 小时的视频给 583 kbps,这个数字自己就说不通了。

我第一眼猜的也是「源视频打码」

我以为问题在源视频。张工把文件发我的时候,我看了眼截图就下了结论:画面里人脸糊,是 UP 主自己打了码。

这个判断只对了一半。人脸确实是人家打的码,但整幅画面发糊是另一码事,跟打码无关。我把原因归错地方了。

先记住这个错。往下看你会看到真正的凶手,它跟打码一点关系没有。

同一个视频,B站存了三份

顺手把可用的格式全列出来:

yt-dlp -F "视频链接"

同一个 BV 号,同一个分辨率,三种编码摆在那儿:

格式 ID 编码 码率 4.3 小时大小
30080 avc1(H264) 1220 kbps 2.19 GiB
30077 hev1(HEVC) 704 kbps 1.26 GiB
100026 av01(AV1) 585 kbps 1.05 GiB

三份都是 1920。分辨率一样,体积差一倍多。 B站给的是同一清晰度的三个版本,不是清晰度三档。

alt:同一分辨率的三份文件对照表,H264 码率 1220 kbps、HEVC 704 kbps、AV1 585 kbps,底部标出工具默认选了码率最低的 AV1 那份
alt:同一分辨率的三份文件对照表,H264 码率 1220 kbps、HEVC 704 kbps、AV1 585 kbps,底部标出工具默认选了码率最低的 AV1 那份

这里插一句。我最初是先看了截图才去列格式的,顺序反了。先量参数,再看画面——画面会骗人,参数不会。人脸打了码你会以为整幅都糊,但码率 583 这个数字不会跟你讲什么,它就摆在那儿。

那下载工具为什么偏偏挑了最差的那份?

工具的默认写法,是按编码效率排的

大多数人用的是这一行:

-f "bv*+ba/b"

这行的意思是:挑最好的画质,再拼一条音频流。

bv* 里那个星号是「所有画质档位里最好的那个」。但"最好"这个判断权交给了工具,而工具比的是编码效率,不是码率。

AV1 是新编码,同样清晰度压出来更小,yt-dlp 就认为它质量更好,排到了最前面。它不知道 B站 这份 AV1 是低码率版本——编码先进,码率反而最低。

把同一段 15 秒切出来比了一遍:

AV1   691 KB
H264  1.9 MB

差 2.8 倍。画面糊成什么样,不用我形容。

还有个附带效果:AV1 的硬件解码兼容性差,播放器不支持就直接花屏、绿块。糊和花是一起来的。

这两件事最容易混。先分开:花屏绿块是解码问题,换播放器能好;整体发糊、细节一坨,是码率问题,换什么都没用。我那个文件属于后者,看了三遍才反应过来不是播放器的事。

怎么一眼看出它挑了哪份

下完先别急着看进度条。文件名后面会带格式 ID,目录列表里就能看到:

find downloads -name "*.mp4*" | head -20
02 - ...p02 6-10.mp4                2.16G
03 - ...p03 11-16.f30080.mp4.part  906M

带 80 结尾的那个 f30080,就是格式 30080,H264 那份。文件名干干净净什么都不带的,多半是走了一个没名的流。

这一步比看播放器里的「1080P」标签准。那个标签只告诉你分辨率,不告诉你码率。想看真参数,还是 ffprobe:

ffprobe -v quiet -print_format json -show_streams 视频.mp4

三个字段就够:codec_name 看编码,width×height 看分辨率,bit_rate 看码率。

批量体检更省事,一行过完整个目录:

find downloads -name "*.mp4" | head -30
grep -c f30080 下载记录.txt

第二条数的是这批下载里有多少个文件带上了 H264 的格式 ID。批量下几十集的时候,我只看这一个数——数不对就是选错了,不用逐个点开看。

改一处就够了

问题出在格式选择串。别让它自己选,点名要 avc1:

# 默认(最高画质)
"bv*[vcodec^=avc1]+ba/bv*[vcodec^=hev1]+ba/bv*+ba/b"

# 1080P 档
"bv*[height<=1080][vcodec^=avc1]+ba/bv*[height<=1080]+ba/b[height<=1080]"

vcodec^=avc1 是「编码必须以 avc1 开头」。后面的斜杠是备选链——有些视频压根没上 avc1,有它兜着就不会直接失败。

alt:改前后的格式选择串对照,上半段是工具按编码效率自动排序拿到低码率 AV1,下半段是点名要 avc1 后拿到 H264,底部是改完日志输出的格式 ID 30080
alt:改前后的格式选择串对照,上半段是工具按编码效率自动排序拿到低码率 AV1,下半段是点名要 avc1 后拿到 H264,底部是改完日志输出的格式 ID 30080

再下一遍,日志里这行变了:

Downloading 1 format(s): 30080+30280

30080 就是上表那个 1220 kbps 的 H264。同一秒切出来的片段,体积从 691 KB 变 1.9 MB。

代价是文件大了一倍。想要小体积,就在选画质那一步明确要 AV1。但得知道自己在换什么。

这三个 ID 是 B站自己定的,跟 yt-dlp 无关。B站哪天改了编号规则我没深究,到时候按码率排也一样。

工具报"下载成功",不等于下对了

这段我最想记下来。

下载器全程没报错,进度条走到 100%,文件能播,音画对得上。它报的是成功的。 只是成功下回来的东西不是你以为的那份。

同一类坑我写过好几次:手动推送按钮撞上 6 小时去重那篇,界面显示推送成功,实际一个请求都没发出去。还有WebP 压缩参数实测表,压图之前我不信默认质量值,从 q95 一路压到 q60 才敢定下 q82。

工具的默认值是别人的猜测。"最高画质"这个说法最会骗人——它是个排序结果,不是实测结论。

发表评论