
下载B站视频这件事说难也难说简单也简单。我关注B站视频下载这个需求好几年了每隔一段时间就会有人问怎么把B站视频存下来。平台的定位是流媒体在线播放官方没有提供像样的离线下载入口视频画面也被切割成音视频分离的分片。这就导致你在网页端右键另存为、或者用录屏软件硬录得到的东西要么是残缺的要么是画质音质双重受损。不过别急到今天为止仍然有两条非常稳的路子一条纯浏览器操作零基础也能跟下来一条是命令行工具适合批量下载、追求最高画质的场景。我两个都在近期的实际下载中测过包括4K HDR内容、番剧、课程、带弹幕的视频下面把完整的操作过程、参数细节和踩坑记录都放出来你可以直接照着抄。先说好这些方法仅供个人学习、备份、二次剪辑参考发布和传播请务必遵循版权规则。1. 为什么下载B站视频这么麻烦平台机制决定了玩法在给方案前我觉得有必要把为什么B站视频下载这么麻烦这件事讲清楚。理解了底层的机制你后面遇到任何异常情况都能自己判断而不是只靠死记步骤。B站目前的播放架构采用的是DASH动态自适应流媒体方案。简单说一个视频在服务器端不是存成一个完整的MP4文件而是被分割成视频轨和音频轨两条独立的流。视频轨通常编码为AVCH.264或HEVCH.265音频轨则多为AAC。播放器在网页端工作时会先向接口请求一个索引文件B站内部叫playurl拿到音视频分片的URL列表然后同时拉取两条轨道在浏览器本地完成实时混流播放。这意味着什么呢意味着你如果在开发者工具里抓到的是一个大文件那不是完整视频只是其中的一条轨道。早期B站还存在过低码率时代一个文件就是全集后来全面切换DASH之后情况变了——这就是为什么很多人用网页另存为、资源嗅探下载下来的文件要么只有画面没有声音要么只有声音没有画面而且大概率还是个m4s后缀的碎片文件需要自己手动合并。另外一个麻烦点是防盗链机制。视频流地址并不是公开固定的接口在返回分片URL时会附带一个带过期时间的签名参数同时服务端校验请求头里的Referer和User-Agent。你哪怕手动拿到了一个分片地址丢到浏览器新标签页里直接访问大概率会得到403。因为少了正确的Referer来源验证。这也是抓流方案里最容易被卡住的地方后文我会专门说怎么处理。理解了这两点你就能明白任何下载B站视频的方法本质上都在做三件事获取解析后的视频流地址带签名、带有效期正确携带身份信息和请求头绕过防盗链校验把下载下来的音视频轨按时间轴合并成可播放的完整文件下面这两个方法第一个适合手工操作、快速备份单个视频第二个适合批量、自动化、追求高画质的场景。我逐个讲。2. 方法一浏览器开发者工具抓流零安装零依赖这个方法最大的优势是不需要装任何软件也不需要面对命令行你只需要一个Chrome或Edge浏览器再加一个ffmpeg工具用于合并音视频。整个过程大概五分钟左右就能解决一个视频。2.1 具体操作步骤第一步打开B站视频页面按F12键打开开发者工具。切到Network网络面板然后在筛选栏里输入m4s或者video再把筛选类型选为Media。第二步点击页面上的播放按钮让视频开始播放。你会发现Network面板里不断刷出以302开头的请求或者一堆类似videoplayback这样的条目。随便点开一条在Response Headers响应头里能看到Content-Type: video/webm或video/mp4在Preview预览标签页里还能看到一个可播放的小画面。这就是视频轨。第三步找到视频轨请求之后在请求条目上右键选择Copy再选Copy as cURL。把复制出来的内容保存到一个文本文件里稍后用。用同样的方式找到音频轨请求也复制成cURL保存。怎么区分音轨和视频轨最直观的办法是看响应头里的那个Content-Type另外可以看请求URL的长度和参数音频轨分片的体积通常比视频轨小很多而且从文件名上看B站的m4s流命名里视频轨一般是30216之类的高端口音频轨是30280。第四步打开命令行终端。如果你用的是Windows建议直接使用PowershellmacOS和Linux用户用自带的Terminal即可。把刚才复制的那串cURL命令粘贴进去。但直接粘贴执行往往会出错因为cURL命令很长而且包含大量请求头。我的建议是先安装一个叫curl的工具Windows 10以上系统自带然后手动把cURL命令整理成下面的格式curl -o video.m4s 完整视频流地址 -H User-Agent: Mozilla/5.0 -H Referer: https://www.bilibili.com/注意这里我们需要把复制的完整请求中的cURL命令里那个网址以及它的Referer和User-Agent保留下来。其余不少请求头是浏览器自动处理的比如Accept-Encoding如果带上反而会出现乱码问题。保留这三个核心的就能通过了。第五步等视频轨和音频轨都下载完成后用ffmpeg合并。ffmpeg是一个开源的多媒体处理工具官方版本直接去ffmpeg.org下载按系统选择即可Windows用户下载之后需要把bin目录加到环境变量里。合并命令ffmpeg -i video.m4s -i audio.m4s -c copy output.mp4执行完之后你会得到一个既有画面又有声音的output.mp4编码格式不变合成过程不用重新编码速度极快一个十分钟的视频几秒钟就完成了。这是因为-c copy选项只是把音视频轨按时间轴容器封装进MP4不做转码所以画质音质零损耗。2.2 为什么网上很多抓流教程到了合并这步就失败了我在不同电脑上测试过这套流程发现新手最常见的翻车点不在抓流而在合并阶段。很多人下载下来后发现文件名带个.m4s后缀然后直接双击根本打不开就会认为自己操作错了。实际上m4s是一种流媒体分片格式系统播放器通常不会识别需要我们先把它改名为video.mp4、audio.mp4再丢给ffmpeg或者命令里直接用-f mp4指定格式ffmpeg -f mp4 -i video.m4s -f mp4 -i audio.m4s -c copy output.mp4还有一类情况下载时长超过30分钟的长视频时B站的分片会被切分成多个片段Network里会看到多个视频轨请求。这时候你需要把全部视频分片先合并成一个完整视频轨再把全部音频分片合并成一个完整音频轨最后再混流。合并分片用ffmpeg的concat协议ffmpeg -f concat -safe 0 -i filelist.txt -c copy video_full.m4sfilelist.txt里按顺序写上所有分片的路径file 1.m4s file 2.m4s file 3.m4s2.3 这个方法的主要局限浏览器抓流虽然不需要额外安装下载工具但要同时下载多P视频例如一个合集几十集时操作成本就会变得非常高。每集都要重复播放—抓流—复制—下载—合并的流程手会点废。另外如果你没有登录B站账号网页端默认最高清晰度只有1080P高码率和4K、HDR这类高质量片源都需要大会员身份才能访问而这个方案的接口请求里如果没有带上你的登录凭证也就拿不到那些超清流。所以抓流方案更适合偶尔下几个视频收藏的场景。下面说的第二个方法就是为正儿八经把B站视频当作资料库来用的人准备的。3. 方法二yt-dlp命令行方案批量下载、高画质一把梭如果你平时需要下载几十个甚至上百个视频或者对画质有极致追求那yt-dlp绝对是你绕不开的名字。yt-dlp是youtube-dl项目的分支目前维护极其活跃对B站的支持在持续跟进远超我见过的任何图形化下载软件。我实测用它在B站下载4K HDR视频的流程非常顺畅下面完整展开。3.1 安装和基础配置安装yt-dlp本身不复杂。Windows用户可以直接去GitHub Release页面下载yt-dlp.exe放在一个固定目录然后把目录加入环境变量macOS用户直接一句命令brew install yt-dlpLinux用户sudo apt install yt-dlp装好之后在终端输入yt-dlp --version确认安装成功。如果你平时不用命令行这里可以先练习一次复制命令-粘贴到终端-回车的流程因为后面所有操作都是这个节奏。yt-dlp对B站的支持依赖认证信息。B站网页端判断登录状态用的是Cookie里的SESSDATA字段。所以第一步我们需要获取个人Cookie。打开B站网页并保持登录状态按F12打开开发者工具切到Application应用程序面板在左侧找到Cookies点开https://www.bilibili.com然后从列表里找到SESSDATA项复制它的Value值。拿到SESSDATA之后有两种方式传给yt-dlp。一种是直接命令行指定另一种是写入配置文件。我更推荐后者因为这样以后每次使用都不需要重复粘贴Cookie而且更安全yt-dlp --add-header Cookie:SESSDATA你复制的值 视频地址如果想写进配置文件在用户主目录下创建yt-dlp.confWindows路径是C:\Users\你的用户名\yt-dlp.confmacOS/Linux是~/.config/yt-dlp/config内容--add-header Cookie:SESSDATA你复制的值每行一个参数yt-dlp启动时会自动读取。3.2 基础下载命令与参数解析假设我现在要下载一个B站视频最简单的命令yt-dlp https://www.bilibili.com/video/BV1xxxxxxyt-dlp会自动分析页面解析出所有可用的画质和音质然后默认选择最高画质进行下载并把音视频轨自动合并输出为单个MP4文件。这是它相比手动抓流最舒服的地方——合并过程是自动完成的。如果你想指定画质使用-f参数。B站常见格式标识符有标识符含义bv*最佳视频轨视频部分选择最高码率ba*最佳音频轨音频部分选择最高码率b两者合并的最佳组合bestvideo[height1080]bestaudio最高1080P画质组合137140手动指定视频轨和音频轨的format_id我平时最常用的画质参数组合是yt-dlp -f bestvideo[height1080][extmp4]bestaudio/best[height1080] 视频地址这段参数的意思是优先选择不超过1080P高度的MP4格式视频轨加上最高音质的音频轨如果找不到了就回退到1080P以内的单文件。使用--list-formats参数可以查看具体视频支持的所有格式yt-dlp --list-formats 视频地址输出结果里每一行对应一个可用的流可以看到清晰的格式ID、分辨率、编码类型AVC/HEVC/AV1、码率等信息。用这个列表你可以精确指定想要的格式。比如HDR内容通常编码为HEVC或AV1分辨率是4K或更高。直接默认参数下载yt-dlp一定会选画质最高的但对于一些老设备或剪辑软件高规格编码反而兼容性差。这时候手动指定格式就很有必要yt-dlp -f bestvideo[height2160][extmp4]bestaudio/best 视频地址3.3 批量下载与弹幕、字幕的配套能力单集下载很简单批量下载才是yt-dlp真正的舞台。B站的许多UP主会上传合集这类页面URL一般是/video/BV1xxxx后面会带?p1、?p2这样的分P参数。yt-dlp会自动识别所有分P并依次下载。如果你想下载整个合集/系列可以配合--playlist-start、--playlist-end来指定范围yt-dlp -f bv*ba/b --playlist-start 1 --playlist-end 10 合集视频地址这个命令会从第1P按顺序下载到第10P。如果你需要收藏弹幕yt-dlp也支持。加上--write-subs参数可以下载CC字幕加上--write-auto-subs可以下载自动生成的字幕。B站的弹幕则要通过--write-subs配合--sub-langs来下载yt-dlp -f bv*ba/b --write-subs --sub-langs deng --convert-subs srt 视频地址不过实操中我发现yt-dlp对B站弹幕的解析并不是总完美。遇到这种情况我会单独用B站弹幕API接口来抓后面避坑章节会详细展开。批量下载时推荐给你的--download-archive参数。它可以记录哪些视频已经下载过了yt-dlp -f bv*ba/b --download-archive archive.txt 合集视频地址下次再执行同样的下载命令已经存在于archive.txt里的视频会被自动跳过不会重复下载。尤其适合持续更新的番剧或者课程系列可以做到增量更新。3.4 下载进度恢复与中断处理B站视频动辄几个小时的电竞直播录播动辄几个GB网络一波动就容易中断。yt-dlp原生支持断点续传如果下载意外中断再次执行同样命令yt-dlp会检测到未完成的.part文件自动从断开的位置继续下载不需要重头再来。但还有一个细节值得留意——当你下载了很多视频突然卡在某个视频上反复报错这时候大概率是那个视频的接口返回异常或格式选择出了问题。我的习惯是加上--ignore-errors参数让yt-dlp自动跳过无法解析的文件继续往后下载yt-dlp -f bv*ba/b --download-archive archive.txt --ignore-errors 合集视频地址实测一个几百P的收藏夹中途总会有几个视频因为版权、区域限制、失效而无法下载加了这个参数之后整个下载流程不会再被单个失败视频卡住。4. 实测中的三大高频坑从排查到根因一次说透无论用哪个方法实际下载过程中总会遇到各种莫名其妙的问题。下面是我认为最典型、最常见的三个我把排查链路完整写出来而不是只丢一个答案。这样你遇到变体问题时也有了判断方向。4.1 401/403报错Cookie和请求头的身份证明问题这是下载B站视频时最常看到的报错之一。表现为yt-dlp开始解析后报ERROR: unable to download video data: HTTP Error 401: Unauthorized或者403: Forbidden。排查的第一步先检查SESSDATA是否过期。B站的Cookie有效期不固定如果长时间没登录SESSDATA会失效。解决办法是重新打开浏览器登录B站重新复制SESSDATA替换进去。如果排除了Cookie过期问题还出现403那要检查是不是同时带了多个Cookie字段冲突。B站网页端会下很多Cookie如果你在yt-dlp配置里同时写了SESSDATA和buvid3这些内容但配置格式没写对比如多个Cookie直接用分号拼接进一个字段就会导致服务端解析失败。正确的做法是在配置文件里只保留SESSDATA或者从浏览器原样复制整个Cookie请求头放在--add-header里。注意整个Cookie头格式是Cookie: 名值; 名2值2多个键值对之间用分号加空格分隔。排查链路总结确认SESSDATA正确复制且未过期重新登录最保险确认配置文件中Cookie格式是Cookie:keyvalue; key2value2确认请求的URL没有复制错不要用about:blank是因为B站视频URL有些带?spm_id_from这类参数不影响但Base主地址必须正确确认你是不是在海外网络环境下访问B站有地区限制策略部分地区IP访问视频流接口会返回403这种情况需要修改IP地区才能解决但个人用户遇到少4.2 音画不同步、合并后没有声音DASH流的双轨陷阱通过抓流方案手动下载最容易出现的就是合并后的视频没有声音或者声音和画面时间轴完全对不上。这不一定是操作错了很多时候是下载到的音频轨和视频轨不在同一个时间切片上。B站的DASH流在返回分片时每个分片的时长并不是严格固定的而且音频轨的视频编号可能比视频轨的高比如音频轨30280、视频轨30216两者需要按StartTime对齐。用ffmpeg的-c copy命令合并时直接封装进MP4容器时间轴信息是保留的理论上不会错位。但如果碰到音画错位那大概率是播放器解码问题或者是同一个视频有多个时间段的DASH流混在一起。解决音画不同步最稳妥的一套命令是这样的ffmpeg -i video.m4s -i audio.m4s -c:v copy -c:a copy -copyts -start_at_zero output.mp4-copyts会保留原始时间戳-start_at_zero把起始时间归零。这样合出来的文件基本不会出现错位。如果你遇到了只有画面没声音的情况先检查audio.m4s文件大小是不是只有几十KB如果是说明你下载的不是完整音频轨而是音频流的一个起始片段需要回到Network面板刷新页面、完整播放一遍让所有的音频分片都请求出来再抓。我自己踩过的一个坑是某些UP主上传的视频本身就是音视频分离后二次合成的网页播放时也有轻微的音画延迟。这种视频你下载后用专业播放器打开正常但用网页播放器预览时却会出现偏移。所以如果遇到音画不同步先用系统播放器比如VLC、PotPlayer测试排除源视频本身的问题再判断是自己合并出错。4.3 弹幕下载后无法正确显示B站弹幕协议的细节很多人的需求不只是下载视频本身还想连弹幕一起保存尤其是在做视频切片、二次创作时。yt-dlp对B站弹幕的支持我实测并不是完美的。它在--write-subs参数下会尝试拉取弹幕文件通常输出为xml或json格式但B站现在很多视频的弹幕接口需要带oid参数每一个分P的弹幕接口地址都不同yt-dlp能处理大部分情况但在某些存在protobuf弹幕流的老视频上会失败。我这里提供一个更稳定的B站弹幕抓取办法基于B站公开的弹幕接口首先从视频页面的源代码中找到cid字段在页面源码里搜cid:或者直接用yt-dlp获取yt-dlp --print cid 视频地址拿到cid之后直接请求弹幕XML接口curl https://api.bilibili.com/x/v1/dm/list.so?oid你的cid -H Referer: https://www.bilibili.com/ -o danmaku.xml得到的XML文件是标准B站弹幕格式可以用多种弹幕转换工具比如DanmakuRender等转成ASS字幕格式挂到本地视频播放器里显示。这里要提醒一下B站弹幕分为高级弹幕和普通滚动弹幕XML接口里只包含普通弹幕。那些带定位、滚屏特效的弹幕需要走protobuf协议目前开源社区有对应的解析工具但需要提前做好技术储备自己写一个解析器哪怕用现成库也稍微有些复杂度一般个人尝试确实没必要。4.4 后台播放/多任务下载的隐形限制下载大量视频时还有一个容易忽视的坑B站接口对同一账号的并发请求数有限制。如果你用yt-dlp默认的并发参数单线程下载速度可能偏慢但不会触发风控但如果你加了-N 16并行16个片段来提速一些账号会被临时封禁播放接口表现为后续请求全部403持续几个小时。我的实测经验是并发数控制在4~6之间比较安全。如果你要下载100个视频与其一次性把并发拉满不如分成两批每批间隔二十分钟整体的成功率反而更高。加--sleep-requests 1.0参数可以在每个请求之间加1秒延迟进一步降低触发风控的概率。yt-dlp -f bv*ba/b --sleep-requests 1.0 --sleep-interval 5 -N 4 视频地址这个命令的意思是每个请求间隔1秒每个文件下载完成后暂停5秒最多并行下载4个片段。实测这个配置下一次性下载一个45P的番剧过程平稳没有触发过任何异常。5. 两个方案怎么选给不同需求场景的最终参考建议写到这里我知道肯定有人想问那到底哪个方法最好其实两个方法之间不是竞争关系而是互补关系。我的选择逻辑是这样的你可以直接参考如果你是偶尔想存一两个喜欢的视频或者只是想快速把某个教程视频下载到本地慢慢看用浏览器抓流方案就够了。不需要额外安装任何下载器不改变系统环境完整操作流程大概五分钟。虽然每集都要手动操作一次但胜在上手门槛低、代码零依赖。如果你满足下面任一条件直接上yt-dlp你打算把B站当资料库定期备份喜欢的UP主的更新视频你需要批量下载整个合集、系列课程、追番你对画质有极致要求想要4K HDR、高码率并愿意研究编码格式你需要自动化流程比如用脚本定期检查更新并下载你想保留弹幕、字幕做素材库配置好SESSDATA后yt-dlp最大的价值其实是一次配置长期复用。配合--download-archive实现增量更新以后UP主发新视频你只需要跑一遍之前的命令新内容就会被自动下载已下载的会被跳过完全不用人盯着。如果你的使用频率介于两者之间比如一周下一次我建议也提前把yt-dlp配好。因为用命令行工具下载出来的文件结构更整洁而且你不需要在每次下载时都打开开发者工具跟浏览器交互长期来看省下的不止是操作时间还有你不断翻坑的精力。最后分享一个自己踩过几次坑之后总结出的习惯下载完成后先用ffprobe查看一下文件信息确认音视频轨完整再去整理文件名。ffprobe output.mp4看到输出里有Stream #0:0: Video和Stream #0:1: Audio两行就说明文件结构是完整的。这个习惯看着有点强迫症但能帮你省掉「存了一堆文件后才发现之前的下载全是坏的」这种返工时间。B站视频下载这件事说穿了就是掌握规则、用对工具、留足耐心剩下的交给网络带宽就好。