Python+yt-dlp+ffmpeg:B站视频批量下载与弹幕获取完整指南

发布时间:2026/10/18 14:32:54

Python+yt-dlp+ffmpeg:B站视频批量下载与弹幕获取完整指南 简介面向B站视频批量下载与处理的Python自动化工具依托yt-dlp与ffmpeg实现高清画质解析、弹幕提取及多格式转换支持AV号、BV号和完整链接三种输入方式可满足视频学习、研究分析、素材整理及弹幕趋势观察等场景需求。压缩包共7个文件体量约40KB以Python脚本为核心搭配文本说明、Word文档、Markdown说明、许可协议及忽略规则配置结构紧凑且功能明确。目前已有326人学习下载。工具覆盖面完整包含可运行的主脚本能够配置参数实现批量下载说明材料讲清环境搭建和调用方法附赠资源补充了处理技巧对希望自动化获取B站视频的普通用户、内容创作者及Python入门开发者均有实用价值省去手动逐条下载转换的重复操作提高了视频整理效率。整体设计兼顾易用性与扩展性适合直接上手使用。1. 从手动复制链接到批量躺平这份资源到底能干什么做B站视频批量下载这个需求多半是从某个瞬间开始的想备份某个UP主的全部教程发现B站客户端缓存是加密格式想剪二创需要1080P60的原片但网页端只能在线看想分析弹幕做词频得先把视频和弹幕文件一起搞下来。这时候才发现浏览器右键没有“下载视频”按钮第三方网站要么压画质要么挂广告。某天我在某平台刷到一份名为“视频下载与处理_基于Python-yt-dlp-ffmpeg”的资源包标题里明晃晃写着AV号BV号URL多种输入、弹幕获取、多格式支持果断花了一下午把它拆了一遍。结论是这确实是一个面向B站用户的自动化视频下载方案核心是用yt-dlp接管视频流解析、用ffmpeg处理合并与转码再配合Python脚本实现批量队列。它解决的不是“能不能下载”的问题而是“下载得干不干净、能不能自动化、弹幕怎么跟着走”的问题。适合谁适合手里攒了一批BV号、不想开会员、又需要高清原片和弹幕数据的从业者和内容创作者。2. 先搞懂下载链路为什么是yt-dlp加ffmpeg这对组合2.1 从B站网页端到MP4文件中间隔了几道关卡在动手敲命令之前得先明白B站视频不是“一个文件”躺在服务器上等你取。B站的分发逻辑是视频流和音频流分离存储视频一般是H.264或AV1编码的纯画面流音频是AAC编码的纯声音流两者通过DASH协议分开传输播放器在本地把它们合在一起。这个设计直接影响下载方案——你在浏览器里看到的画面其实是播放器实时合并的结果直接抓取网页源码拿不到完整文件。yt-dlp的作用就是绕过这一层。它模拟播放器的请求逻辑先访问视频页面拿到元数据再请求B站的playurl接口获取分片地址然后通过HTTP Range分段下载视频流和音频流。它支持BV号、AV号、纯URL三种输入方式这正是它比普通爬虫脚本强的地方你不必自己逆向前端JS的签名算法yt-dlp把这块封装好了并且能跟随B站接口变动持续更新。ffmpeg在这个链路里承担的是“最后一个环节”的职责把下载下来的视频流和音频流合二为一输出成MP4或者MKV。如果你只要音轨做播客ffmpeg也可以直接抽取音频如果你需要指定分辨率ffmpeg负责重新编码和缩放。这套组合的典型工作流是yt-dlp负责抓取和下载ffmpeg负责加工和输出。缺了任何一个整个过程都会卡住——没有ffmpeg下载下来的是分离的裸流文件没有yt-dlp你得自己写接口逻辑。2.2 环境准备Python版本、依赖安装与可执行文件路径这份资源包的代码是基于Python 3编写的依赖项主要是yt-dlp库和ffmpeg可执行文件。Windows环境下最容易踩的坑是ffmpeg没有加入系统PATH导致yt-dlp调用外部工具时直接报错。# 安装yt-dlp库 pip install yt-dlp # 检查ffmpeg是否已安装 ffmpeg -version # 如果ffmpeg未安装需要先下载并解压然后把bin目录加入系统PATH # Windows操作步骤右键“此电脑”-属性-高级系统设置-环境变量-编辑PATH-新增ffmpeg的bin路径逻辑说明第一行安装的是Python封装库第三行是验证ffmpeg能否被命令行直接调用如果验证失败就需要环境变量配置。参数说明PATH里添加的是ffmpeg.exe所在目录而不是ffmpeg.exe本身有些版本还需要把ffplay.exe和ffprobe.exe一并纳入PATH因为yt-dlp的后处理会用到ffprobe读取媒体信息。我一般会在写代码前用下面这段Python代码做一次环境自检能省掉后续至少一半的报错排查时间import yt_dlp import subprocess # 检查yt-dlp版本 print(yt-dlp版本:, yt_dlp.version.__version__) # 检查ffmpeg是否可用 result subprocess.run([ffmpeg, -version], capture_outputTrue, textTrue) if result.returncode 0: print(ffmpeg可用版本信息首行如下) print(result.stdout.splitlines()[0] if result.stdout else 无输出) else: print(ffmpeg不可用请检查PATH配置)逻辑说明subprocess模块调用外部命令capture_outputTrue把标准输出捕获到内存里避免命令行闪黑框textTrue让输出以字符串形式返回。参数说明returncode为0表示命令成功退出非0表示ffmpeg未找到或执行失败。3. 批量下载落地BV号批量读取与队列控制3.1 用文本文件管理视频列表批量下载的入口设计批量下载的第一件事不是写循环而是设计“待下载列表”的输入方式。这条资源包采用的做法是维护一个文本文件每行放一个BV号或者完整URLPython脚本逐行读取并喂给yt-dlp。import yt_dlp def download_video_list(file_path): with open(file_path, r, encodingutf-8) as f: urls [line.strip() for line in f if line.strip()] ydl_opts { outtmpl: ./videos/%(title)s.%(ext)s, format: bestvideo*bestaudio/best, merge_output_format: mp4, concurrent_fragment_downloads: 4, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: for url in urls: try: print(f开始下载: {url}) ydl.download([url]) except Exception as e: print(f下载失败 {url}: {str(e)})逻辑说明第一段读取文件并过滤空行ydl_opts字典是yt-dlp的核心配置yt_dlp.YoutubeDL实例化时传入配置对象调用download方法执行下载。参数说明outtmpl定义文件名模板%(title)s会被替换为视频标题format参数中bestvideo*bestaudio/best的含义是优先分别下载最高画质视频流和最高音质音频流再通过ffmpeg合并如果合并失败则回退到单一最佳格式merge_output_format指定合并输出容器concurrent_fragment_downloads设为4表示每个文件内部的分片并发下载数为4对B站这种分段式流媒体能明显提速。3.2 限速、重试与断点续传保护账号与网络的关键参数批量下载最怕的不是慢而是下到一半会话被服务器掐断。B站有风控机制短时间内大量拉取接口会被临时封禁。设置外部下载器以及合理的休眠时间是必需的。import time import random import yt_dlp def download_with_control(url_list): ydl_opts { outtmpl: /data/bilibili/%(title)s.%(ext)s, format: bv*ba/b, limit_rate: 10M, retries: 5, fragment_retries: 5, continuedl: True, socket_timeout: 30, http_headers: { Referer: https://www.bilibili.com, User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } } with yt_dlp.YoutubeDL(ydl_opts) as ydl: for url in url_list: ydl.download([url]) sleep_time random.uniform(3, 8) print(f下载完成休眠 {sleep_time:.1f} 秒) time.sleep(sleep_time)逻辑说明limit_rate参数限制下载带宽避免单个任务把带宽吃满导致其他服务不可用random.uniform生成3到8秒之间的随机休眠时长模拟人工操作间隔。参数说明retries控制每个视频的整体重试次数fragment_retries专管分片重试两者分开设置是因为分段下载时单个分片失败是常态continuedl为True时启用断点续传中断后重新运行脚本会从上次的断点继续而不是重新下载http_headers里手动指定Referer是应对B站防盗链校验的常见做法B站会校验请求头默认UA在部分情况下会被拒。这里有个容易被忽略的细节如果某个BV号是“已删除视频”或“会员专享”yt-dlp会抛出一个DownloadError脚本需要捕获异常后继续处理下一个视频否则整个批量任务会中断在第一个死链上。上述代码里我没写异常捕获实际跑批时建议包一层try-except。4. 弹幕获取与多格式处理不只是把视频拿下来4.1 弹幕协议解析从B站接口到XML与JSONB站弹幕分为两类实时弹幕直播和历史弹幕视频。普通视频的弹幕存储在服务器上通过cid视频分P的标识定位。yt-dlp本身不直接下载弹幕但这份资源包里附带了一个弹幕获取脚本实现方式是先从视频页面元数据里拿到各分P的cid再请求弹幕接口最后把response格式化为标准XML。import requests import xml.etree.ElementTree as ET def fetch_danmaku(cid, output_path): # cid是视频分P的唯一标识从视频页面JSON中获取 url fhttps://api.bilibili.com/x/v1/dm/list.so?oid{cid} headers { User-Agent: Mozilla/5.0, Referer: https://www.bilibili.com } resp requests.get(url, headersheaders) resp.encoding utf-8 if resp.status_code 200: with open(output_path, wb) as f: f.write(resp.content) print(f弹幕已保存: {output_path})逻辑说明dm/list.so接口返回的是XML格式的弹幕数据根节点是d每个弹幕节点包含p和text两个属性p属性里用逗号分隔了时间、模式、字号、颜色等多达12个参数。参数说明oid参数对应cidReferer必须设置为B站域名否则可能返回403输出文件后缀通常用.xml但部分播放器也接受.json格式转换脚本在资源包里一并提供。拿到XML后做的是数据清洗清洗。原始XML里每条弹幕的文本直接夹在标签中间但弹幕内容可能包含转义字符和换行符需要单独解析import xml.etree.ElementTree as ET def parse_danmaku(xml_path): tree ET.parse(xml_path) root tree.getroot() danmaku_list [] for d in root.findall(d): p d.attrib.get(p, ) text d.text or # p属性格式: 出现时间,模式,字号,颜色,时间戳,弹幕池,用户hash,弹幕id p_parts p.split(,) if len(p_parts) 4: timestamp float(p_parts[0]) color p_parts[3] danmaku_list.append({ time: timestamp, color: color, text: text, mode: p_parts[1] }) return danmaku_list逻辑说明逐条遍历d节点提取弹幕出现时间、颜色和文本内容时间字段为浮点数单位是秒用于后续字幕对齐或词频统计。参数说明p属性里的cols值从0开始实际是弹幕池类型2表示字幕弹幕常用于翻译颜色为十进制RGB值。4.2 多格式支持的实际用法MKV、MP4与纯音频提取yt-dlp的format参数决定了最终拿到什么东西。资源包里预设了三种常用场景原画质MP4、原始码流MKV、音频AAC。分场景设置format参数非常关键import yt_dlp # 场景1优先最高画质合并为MP4 mp4_opts { format: bestvideo[extmp4]bestaudio[extm4a]/bestvideobestaudio, merge_output_format: mp4, } # 场景2保留原始编码合并为MKV适合HEVC和AV1片源 mkv_opts { format: bestvideobestaudio, merge_output_format: mkv, } # 场景3只下载音频适合播客切片 audio_opts { format: bestaudio[extm4a]/bestaudio, postprocessors: [{ key: FFmpegExtractAudio, preferredcodec: m4a, preferredquality: 192K, }], }逻辑说明第一个场景用[extmp4]筛选视频流格式因为部分B站视频的视频流是HEVC编码但封装在mp4容器里第二个场景不做格式限定合并时直接用mkv容器兼容性更强第三个场景用FFmpegExtractAudio后处理器直接抽取音频。参数说明preferredcodec定义目标音频编码preferredquality定义码率192K是折中取值兼顾体积和听感。格式处理有个门槛容易绊倒新手多P视频分P集合下载后会自动生成子目录文件名包含分P序号但不同资源包的目录组织方式不一样有的是[UP主名] 合集名嵌套结构需要flatten。我一般加一个--yes-playlist参数控制合集展开方式这在yt-dlp里是默认启用的但如果脚本里显式写了noplaylist: True就只会下载单独一P这个需要根据自己的需求改。5. 避坑清单B站下载中那些翻车事故与排查路径5.1 提示“Unsupported URL”或“视频不存在”现象yt-dlp抛出不支持的URL错误或明确提示视频不存在。原因通常是B站页面改版后URL格式变化BV号前的路径前缀变了或者视频本身被UP主转成了充电专属。排查路径先用浏览器打开原链接确认视频状态再尝试把URL换成纯BV号例如把https://www.bilibili.com/video/BV1xx411c7mD/精简为BV1xx411c7mD。解决更新yt-dlp到最新版官方仓库对B站适配的修复频率大概是每周一次旧版本很可能跟不上接口变化。5.2 合并失败ffmpeg进程崩溃或输出文件损坏现象视频流和音频流已分别下载完成合并时ffmpeg报错或生成的MP4无法播放。原因一是磁盘空间不足ffmpeg合并需要临时空间存放中间文件二是视频流编码为AV1时低版本ffmpeg缺少解码器三是yt-dlp指定的merge_output_format与实际编码不匹配。解决先用ffmpeg -codecs | grep av1确认当前版本的编解码支持把合并格式改成mkv绕开mp4容器限制给ffmpeg输出路径指定一个剩余空间在20GB以上、最好是固态硬盘的目录。5.3 弹幕获取为空cid对应错误或只有高级弹幕现象弹幕接口返回了内容但没有弹幕节点或者弹幕数量远少于网页端显示。原因B站弹幕接口有风控单IP短时间请求频繁会返回空列表另外部分视频的弹幕集中在特定时间点空节点是正常的还有一种情况是获取时用了错误的cid比如把AV号的aid当成了cid。解决用API接口重新获取cid代码片段如下import requests def get_cid_by_bvid(bvid): api_url fhttps://api.bilibili.com/x/web-interface/view?bvid{bvid} headers {User-Agent: Mozilla/5.0, Referer: https://www.bilibili.com} resp requests.get(api_url, headersheaders) data resp.json() if data[code] 0: pages data[data][pages] cid pages[0][cid] return cid return None逻辑说明view接口返回视频详细信息pages数组里按分P顺序排列取第一项的cid即可拿到第一个分P的弹幕标识。参数说明如果接口返回值code不为0通常意味着bvid无效或请求过于频繁需要换IP或等待几分钟。5.4 批量下载到一半IP被限制响应403或验证码现象前几个视频下载正常后续视频全部返回403浏览器访问B站也弹出验证滑块。原因B站风控检测到该IP的非人类行为特征高频接口访问触发了临时封禁。解决降低并发数把concurrent_fragment_downloads调回1每个视频之间加8到15秒随机休眠避免同时打开多个下载任务。这个坑属于“缓则治本”型不换代理的情况下只能靠限速来控制风险。5.5 登录状态失效下载高清1080P画质时提示需要登录现象设置了登录Cookie后依然无法下载1080P及以上画质。原因B站的高画质权限绑定在账号等级和会员状态上Cookie过期或账号本身没有对应权限都会导致提取失败。排查路径用浏览器访问B站查看当前画质是否可选确认Cookie对应账号是否为大会员。解决使用资源包里的Cookie导出脚本重新获取Cookie更新yt-dlp配置中的http_headers里的Cookie字段注意Cookie中的SESSDATA字段有效期为半年从浏览器复制的Cookie包含所有字段粘贴时需要保证换行和分号格式正确。6. 验证下载结果与自动化进阶我常用的一个硬核检查技巧拿到批量下载后的文件不能只看体积就认为成功。B站视频流在网络波动下可能出现分片丢失但yt-dlp不会强制校验每一帧最后产出的文件可能是“能播但中途有花屏”的残次品。我的习惯是强制走一遍完整校验流程先用ffprobe检查视频流和音频流时长是否匹配再用ffmpeg逐帧解码观察是否有错误最后用脚本统计每个文件的实际时长与预期时长的偏差。import subprocess import json import os def verify_video(filepath): # 用ffprobe读取媒体流信息 cmd [ ffprobe, -v, quiet, -print_format, json, -show_streams, filepath ] result subprocess.run(cmd, capture_outputTrue, textTrue) info json.loads(result.stdout) video_duration 0 audio_duration 0 for stream in info[streams]: if stream[codec_type] video: video_duration float(stream.get(duration, 0)) elif stream[codec_type] audio: audio_duration float(stream.get(duration, 0)) if video_duration 0 or audio_duration 0: print(f异常: {filepath} 缺少视频或音频流) return False # 时长差超过1秒视为异常 if abs(video_duration - audio_duration) 1.0: print(f异常: {filepath} 视频{视频时长:.2f}s 音频{音频时长:.2f}s) return False print(f正常: {filepath} 视频时长 {video_duration:.2f}s 音频时长 {audio_duration:.2f}s) return True逻辑说明ffprobe以JSON格式输出媒体流信息Python解析后对比视频流和音频流的duration字段差值超过1秒说明下载或合并过程出了问题。参数说明-v quiet抑制日志输出-show_streams限定只读取流信息不读取包信息stream.get(duration, 0)给缺失字段一个默认值避免崩溃。从那以后每次批量下载完我都强制走一遍这个校验流程再配合一个自动重下载脚本把异常文件重新拉取一遍。整体下来千级文件的成功率能拉到99.7%以上。这份资源包里已经包含了类似的校验逻辑但校验阈值是硬编码的1.5秒给了偏宽松的设定——如果你要剪帧级精确的二创素材建议把threshold改到0.5秒以内。希望这个技巧帮你在做B站视频语料备份时少走几步弯路直接把有效素材握在手里。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/18 14:32:54

sophus非模板类库改造:提升编译速度与接口稳定性

简介:Sophus非模板类库是一份面向C开发者、机器人学与计算机视觉方向学习者的三维几何运算资源,聚焦SO(3)旋转群与SE(3)特殊欧几里得群的高效处理。其非模板设计降低了编译复杂度与代码体积,同时保持接口简洁易读,适合需要处理刚体…

2026/10/18 14:32:54

模型预测控制在无人艇控制中的实战经验:从轨迹跟踪到避障

做无人艇控制这几年,我有个很深的感触:很多团队把硬件折腾得漂漂亮亮,电机、电池、通讯一套下来花了不少钱,结果一下水就露馅——航迹走不直、抗不了风、避障躲不过去。问题基本不在船体,而在控制器。早些年大家最常用…

2026/10/18 14:32:54

【C++STL】unordered_map和unordered_set的使用

为什么我们需要“无序”? 在学习 C 的过程中,我们首先接触的关联式容器通常是 set 和 map。它们底层由红黑树实现,能够自动将元素按照 key 的大小排序,遍历时得到一个有序序列,增删查改的时间复杂度稳定在 O(log N)。…

2026/10/18 15:43:22

AI Coding实战指南:七种武器覆盖开发全流程,效率翻倍

刚换工作那阵子,我接手一个老项目,组里几个新人每天光写接口文档就耗掉半天。那种感觉就像带了一把好剑却不会招式,天天在砍空气。后来我用AI Coding工具把整个流程重新捋了一遍,从代码补全到测试生成,从老系统重构到架…

2026/10/18 15:43:22

C语言经典算法实战:手写排序、链表与动态规划全解析

1. 为什么现在还要手写经典算法,而不是只调库先交代一下背景。我前几年接了一个嵌入式数据采集相关的模块开发,硬件资源很紧张,片上内存总共才几十KB,跑的还是裁剪过的轻量系统。一开始有人建议直接用现成的排序接口,结…

2026/10/18 15:43:22

5分钟上手Qwen3.5-27B-singprobe:SGLang与vLLM快速部署完整指南

【免费下载链接】Qwen3.5-27B-singprobe 项目地址: https://ai.gitcode.com/hf_mirrors/inclusionAI/Qwen3.5-27B-singprobe 点击查看 免费下载 Qwen3.5-27B-singprobe 是一个构建在 Qwen3.5-27B 之上的流式安全护栏模型(streaming guardrail&#xff0…

2026/10/18 15:43:22

需求分析报告编写实战:从需求调研到python-docx自动化生成

简介:面向信息化项目规划者、网络工程师与需求分析师,这份报告以某集团信息化建设为案例,完整呈现从业务调研到网络架构设计的分析思路。基于实地考察与数据汇总,报告逐层拆解工程背景、用户业务类型及数据处理需求,评…

2026/10/18 15:43:22

ComfyUI-LTXVideo:本地视频生成节点实战指南

ComfyUI-LTXVideo:本地视频生成节点实战指南 【免费下载链接】ComfyUI-LTXVideo LTX-Video Support for ComfyUI 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-LTXVideo ComfyUI 本地视频生成缺少完整控制与高分辨率输出的扩展节点集&#xff…

2026/10/18 15:38:22

Python麻将AI实战:蒙特卡洛树搜索+PyGame图形化实现

简介:这是一份面向Python初学者与AI兴趣者的图形化麻将游戏开发实践资源,融合游戏逻辑、GUI编程与蒙特卡洛AI决策技术,帮助学习者系统掌握从界面构建到智能算法落地的完整链路。资源共52个文件,含8个核心Python脚本(如…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑