ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

video-use:命令行视频批量下载与格式整理实战指南

video-use:命令行视频批量下载与格式整理实战指南 在整理本地视频素材这件事上我前后折腾过不少方案。最早是手动去页面右键另存后来用在线解析站再后来换过几个图形界面的下载工具但总有各种别扭的地方要么平台接口失效快要么批量任务要一个个点要么下载完还要单独转格式。直到我花时间把日常用的这套命令行工具整理成了video-use项目才真正把看到链接就想保存到本地这件事变得顺滑。这篇文章就围绕video-use这个项目把我做选型时的思考、实际用的配置、踩过的坑以及最终沉淀下来的操作流程完整写一遍。适合正在做视频资源整理、需要批量保存教学视频或演示片段、又不想被各种图形工具绑架的朋友参考。1. 项目定位与核心设计思路1.1 这个工具解决的三个真实痛点我在日常工作中接触最多的不是单条视频下载而是一堆链接要批量整理。比如我每隔两周要整理一批产品演示录像来源是公司的内部分享平台每段视频大概 30 到 90 分钟另外我自己学一些公开课的时候也会把课程章节拆成几十个短视频片段按目录归档。这时候如果还用浏览器手动操作一次两次能忍十次八次就非常煎熬。video-use最开始就是奔着三个痛点去的。第一是重复劳动我希望能用一个统一的命令把不同来源的链接全部收进来不想为每个站点记一套操作步骤。第二是格式和画质不统一有的页面默认给的是低码率流有的混流封装方式很奇怪播放器兼容性差所以我需要一个统一的输出标准默认走mp4 h264 aac画质能选就选清晰度最高的那个档位。第三是批量化我要能把几十个链接丢进一个文本文件一次跑完并且下载失败的任务可以单独重试不影响其他任务。这个工具的设计目标说白了就是把视频保存动作标准化。专业一点讲就是封装了链接解析、流地址抽取、并发下载、格式归一化这几层能力。我刻意没有给它加图形界面因为命令行本身就是最好的批处理载体配合定时任务或简单脚本能干的事比点鼠标多得多。1.2 为什么采用解析引擎 下载器 处理层三层架构video-use在架构上分得非常清楚。第一层叫解析引擎负责把用户输入的页面链接转换成真实的媒体流地址第二层是下载器负责把媒体流以可靠的方式落到磁盘第三层是处理层负责封装格式、写入元数据、合并字幕有时候还承担画质筛选。这个分层的逻辑其实是从实际故障中逼出来的。早期我写过一个一把梭的版本解析和下载混在一个函数里结果某个平台改了一次页面结构整个流程全崩排查了一晚上才定位到是解析函数里的正则匹配失效。拆开之后解析层只要保证输出标准的{video_url, audio_url, subtitles, title}结构下载层只管拿 URL 干活互不干扰。下次再遇到站点更新我只需要修解析层的规则下载器一行都不用动。下载层我选择了优先多线程分片、回退单线程的方案。分片下载对不稳定的网络更友好一个分片失败了只需要重试这个分片而不是整个文件推倒重来。同时我留了一个开关刻意照顾一些对并发敏感的服务端——它们会对快速建立的多连接做限速此时反而单线程更稳。这个开关我在日常用到的频次不高但一旦遇到就是救命级别的存在。处理层的核心依赖是 FFmpeg。音频流和视频流分离存储、单独下载最后再混流封装这是很多流媒体站点的通病形式。用家庭影院类比的话视频流相当于画面音频流相当于声音FFmpeg 就是那个把画面和声音同步合成一体的剪辑台。没有它我本地只会有两个干巴巴的中间文件根本没法直接观看。1.3 技术选型背后的理由编程语言我选了 Python。原因很简单生态里跟网页结构解析、URL 处理相关的库非常成熟而且写这类胶水代码效率高。解析引擎部分我组合使用了正则表达式和 DOM 选择器两种方式。正则适用于提取页面内嵌的 JSON 数据DOM 选择器适用于定位视频标签节点。平时总觉得正则万能实际项目做多了就会发现结构化的页面用选择器才是正道正则只用来抽取零散字段。下载器底层没有另起炉灶直接复用了requests库做标准下载同时在分片场景下调用aria2作为外部下载器。成熟工具能解决的问题不需要自己重复发明aria2对分片、重试、断点续传的支持都非常稳我只需要把参数传对。这里也有一个经验凡是遇到视频流地址有效期短的情况比如 URL 里带签名和时间戳就必须让 aria2 紧跟在高并发请求之后并且延迟要调低等签名过期了再重试就没有意义了。格式归一化都是交给 FFmpeg 的。-c copy是首选意味着不重新编码只做封装容器变化速度快、画质零损失只有源文件编码格式和目标容器不兼容时才迫不得已走 re-encode。这个决策带来的直接好处就是99% 的视频下载耗时都花在网络传输上本地处理几乎不占 CPU。2. 环境准备与快速部署2.1 依赖环境清单在开始video-use之前先把基础环境准备好。我的建议是你至少准备一台能跑 Python 3.9 以上的电脑Windows / macOS / Linux 都行FFmpeg 已加入系统 PATH磁盘空间考虑到你下载的可能是高清长视频建议保留双倍于视频体积的剩余空间临时文件用完再清理稳定的网络连接这直接决定分片下载的成功率FFmpeg 是非常重要的一个依赖。我在 Windows 上的安装方法是到 FFmpeg 官网下载编译好的压缩包解压后把bin目录加入系统Path。Linux 用户一般是sudo apt install ffmpeg或sudo dnf install ffmpegmacOS 用户用brew install ffmpeg最省心。装完在终端里跑ffmpeg -version能看到版本号就说明妥了。2.2 安装与初始化直接用 pip 安装发布包或者从源码运行两种方式二选一。# 方式一安装发布包 pip install video-use # 方式二从源码运行 git clone https://example.com/video-use.git cd video-use pip install -r requirements.txt python -m video_use --help我第一次跑--help的时候看到满屏参数其实有点懵但用几次就发现核心命令就那么几个。日常最常敲的就是video-use get 视频页面链接 video-use batch list.txt video-use info 视频页面链接info命令是我建议先用起来的。它的作用是只解析、不下载把能拿到的标题、时长、清晰度档位、格式类型先列出来。这相当于点菜之前先看菜单避免下载完才发现不是自己想要的那个版本。初始化配置也很简单。首次执行任意命令时程序会在用户目录下创建video-use/config.yaml你只需要按需改这个文件。我不会让它第一次运行就问一堆交互式问题那对脚本化使用场景太不友好了。2.3 核心配置文件逐项说明配置文件长这样我逐段解释每个字段背后我踩过的坑storage: root_dir: ./downloads temp_dir: ./tmp preferred_format: mp4 preferred_quality: highest download: max_concurrent_tasks: 3 max_retries: 5 aria2_enabled: true aria2_split: 8 request_timeout: 30 max_speed_limit: 0 cookies_file: root_dir和temp_dir的分离是一个很实用的习惯。temp_dir放下载中的.part文件和没合并的半成品root_dir只放最终可播放的文件。这样就算下载中断清理临时文件也不会误删成品。preferred_format我默认设为mp4。不是因为它画质最好而是它兼容性广——电视、手机、平板、网页播放器基本通吃。mkv在封装字幕方面更强但部分老设备可能放不了。画质字段preferred_quality默认highest意思是尽量选清晰度最高的视频流没有明确档位时就看码率。下载参数里max_concurrent_tasks我控制在 3。这个数字是经验值超过 5 之后部分平台的服务端会触发风控反而整体变慢。max_retries我的习惯是 5 次第一次失败可能是网络抖动连续 5 次还失败那大概率是链接失效或者被封了不值得继续耗。request_timeout设为 30 秒是针对慢网络的妥协值后来证明比默认的 10 秒稳妥得多。cookies_file这个字段要重点说。很多视频平台未登录状态下只给到 480p 或者更低画质把浏览器的 cookies 导出来喂给工具就能拿到会员画质。这里有个合规边界我后面专门讲但技术上就是让解析请求带上身份信息。3. 核心功能实操手册3.1 单视频解析下载从链接到成片基本的单条下载命令video-use get https://视频平台分享页链接执行过程会分为几个阶段。首先进入解析阶段终端会打印出识别到的视频标题、站点类型、可用清晰度列表。这时候如果发现解析出来的视频流是dash格式不要惊讶它意味着音频和视频分成两路下载器会自动把它们都拉下来再交给 FFmpeg 合并。接着进入下载阶段。如果你启用了 aria2会看到分片进度按块推进没启用的话就是常规的进度条。下载完成后进入处理阶段FFmpeg 开始执行封装操作。默认流程下我会先看源文件是不是已经符合目标格式要求如果符合就直接改名收工不符合才走转封装。我想强调一个心态看到Processing阶段耗时较长别慌。有些长视频虽然下载只用了两分钟但 FFmpeg 在做-c copy时因为容器基数变化需要重写索引表这个过程对 90 分钟的视频可能要额外花十几秒甚至更长。这属于正常现象不是卡死。画质筛选我做了自动逻辑最高清的视频流编号音频流选码率更高的那条。遇到过有的站点把多语言音轨拆成多条音频流默认策略是选第一条需要在命令里加参数指定语言比如video-use get 链接地址 --audio-language zh-CN3.2 批量任务处理列表文件与并发控制批量处理这个场景list.txt文件就是你全部要下载的视频页面链接一行一个https://平台A/分享页/101 https://平台B/watch?id202 https://平台C/play/303然后用video-use batch list.txt这里有个细节批量任务建议每行的末尾都不要带多余空格空行会被自动忽略。我曾经在一个文件里塞了 Windows 换行符和 Linux 换行符混排的内容结果解析阶段偶发把\r当成链接的一部分折腾了半天才定位到问题。现在我会在批量执行前先统一转换行尾。并发数默认 3这是全局并发意味着同时最多 3 个视频任务在跑。每个任务内部还有基于 aria2 的分片并发所以实际对服务器的连接数可能是 3 乘 8。有的服务器对单个 IP 的连接数有硬性限制如果你发现批量跑的时候大量 403 或者超时可以先调低max_concurrent_tasks到 1、aria2_split到 4 试验稳定之后再慢慢往上加。批量任务结束后我还会做一次状态汇总检查。正常结束的任务会标记为completed失败的任务会给出失败阶段解析失败、下载失败、合并失败。我的经验是不要着急一把梭重跑全部失败任务先看看是不是同一个原因引起的。比如全是403那大概是频率被限制全是解析失败可能是平台改版。前者等一会儿再重跑就好后者需要等规则更新。3.3 格式转换与画质选择关于格式我先给一张对照表这是我在实际整理素材时总结的容器格式视频编码适用场景备注mp4h264 aac通用兼容适合移动设备与网页我的默认选择mp4h265 aac同体积画质更高适合本地收藏老设备可能不支持mkv任意编码多字幕、多音轨收藏向不适合直接网页播放flvh264Flash 时代遗留基本不推荐preferred_format: mp4但遇到源视频是mkv的情况默认会做一次容器转换。注意这里的转换大多数时候是-c copy速度极快。如果遇到opus音频要给老播放器用的情况我会把音频转成aacvideo-use get 链接 --format mp4 --audio-encode aac这个操作比全视频重编码轻得多因为只动音频轨视频轨仍然是 copy。画质选择方面--quality参数可以覆盖配置文件的默认值。比如你要快速预览可以采用video-use get 链接 --quality 720p我的建议是仅仅为了看内容720p 其实已经够了要收藏或者剪辑直接上最高画质。1080p 和 4K 的体积差距不是线性增长是几何级数增长一块 500G 的移动硬盘也架不住高质量视频长期囤积。3.4 封面、字幕、元数据写入下载完视频只算完成了一半video-use还会尝试抓取封面图、字幕并写入元数据。封面方面解析引擎会从页面 OG 标签或者播放器配置里找previewImage找到就保存为封面图.jpg并且通过 FFmpeg 的-metadata:s:v参数嵌到文件里。嵌封面的好处是在文件夹里用缩略图模式浏览时一眼就能认出视频内容比一堆同名字的灰色媒体图标舒服多了。字幕的优先级是硬字幕烧进画面 外挂字幕独立文件 软字幕封装进容器。对平台来说最常见的是外挂字幕文件。遇到没有字幕的我一般直接关闭字幕抓取不浪费时间video-use get 链接 --skip-subtitles元数据写入这块我特别强调 标题清洗。很多平台自动生成的标题带一堆推广后缀比如 【官方】某某课程完整版_高清_1080P_免费看这种文件名保存到本地之后在文件管理器里异常违和。video-use内置了一套清洗规则把渠道号、推广词、清晰度后缀去掉只保留核心标题。4. 常见问题与排查技巧实录4.1 下载中途失败与断点续传下载到 60% 断掉这是最常见的场景之一。video-use的临时文件会以.part结尾保存重跑时如果检测到同名.part文件会询问你是否续传。依赖 aria2 时这个续传是自动完成的不需要额外参数。我遇到断线的原因大多是网络波动少部分是服务器主动断开长连接。还有一种情况容易被忽略如果下载的是分片流且部分分片早于其他分片很多就下载完成临时合并排序需要额外的磁盘 I/O磁盘性能差的机器在这一步可能卡顿看起来像断了其实还在跑。排查快慢的经验是看日志关键字。出现Retrying说明是网络层在自动重试正常出现Failed to establish connection说明目标服务器拒绝连接需要考虑降速或换时段。真正可怕的不是报错而是无限重试却没有任何进展这时候要在配置里调低max_retries早点止损。4.2 合并报错与编码问题FFmpeg 合并时报错最典型的是 Invalid data found when processing input直接原因通常是下载的音频或视频分片不完整或者临时文件被其他程序占用。我自己的习惯是报这个错先把临时目录下的相关文件删掉重新跑一次完整流程不要自作聪明去手动拼接反而容易把问题复杂化。另一种情况是源视频流编码是h265但目标格式强制要求 mp4 且参数里没有明确允许h265。这时候 FFmpeg 会直接报编码不支持。解决方式很简单要么接受mkv封装不让它转要么指定视频编码转一次video-use get 链接 --format mp4 --video-encode h265如果连 h265 都不支持就降到 h264代价是文件体积会变大。我日常本地收藏的素材几乎全走 h265因为体积少大约一半而画质感官差距极小。但交给朋友或者传到线上的我只用 h264不为别的省得别人播放器打不开。4.3 链接解析失败与 403解析失败是最让人挫败的一种错误因为不是网络问题是规则失效。我的排查顺序是这样的先确认链接本身在浏览器里能正常打开排除链接输入错误或权限问题再看日志里的parser字段确认工具命中了解析引擎的哪个分支检查输出内容里是否有 parser returned empty stream 之类的提示若有基本可以确定页面结构有变动403 则多半是身份验证问题。未登录状态抓不到高清流或者在批量模式下并发过高触发了风控。我的做法是批量任务统一把max_concurrent_tasks调到 2aria2_split调到 4如果仍触发 403则在配置文件的download段设置下载间隔。更底层的一个排查方向是 User-Agent。有些站点会拦截非浏览器发起的请求。我会在配置里让工具默认模拟浏览器的 UA而不是 Python 默认 UA。这不算欺骗只是让自己看起来像一个正常访客降低服务端误杀的几率。4.4 磁盘空间与命名冲突视频下载经常把磁盘塞爆。我经历过一次最狼狈的情况是批量下载一个系列课程30 个视频平均每个 3GB中途 D 盘满了结果一半文件半成品一半文件没开始。之后我吸取教训每次批量任务开始前先检查磁盘剩余空间判断标准是预估总体积的 1.5 倍剩余空间留出临时文件转储、合并操作的缓冲。命名冲突则是另一种烦同一系列视频有多个分P标题可能完全一样。video-use默认会追加序号区分比如课程名称_01.mp4、课程名称_02.mp4。如果遇到重名会在文件名尾部加时间戳而不是直接覆盖这个保护逻辑我是后来才加的之前被覆盖过一份未备份的视频想起来都心疼。5. 使用边界与合规建议5.1 只下载自己有权使用的内容写工具是方便自己但使用边界不能丢。video-use从设计上就不内置任何针对付费墙的破解逻辑也不会去绕过平台的版权验证。我个人的使用边界是公开的免费内容、自己购买过的课程、公司内部授权分发的素材、以及无版权风险的创作共用CC内容。下载之后如何处置同样重要。个人学习、离线备份、多设备迁移这些场景只要不重新公开传播、不用于商业牟利基本都在合理范畴内。我整理素材时有一个原则所有下载的视频都放在本地私人目录不二次上传到公开网络。这个原则帮我避免了很多麻烦。5.2 版权判断的三条标准我不能帮你做法律判断但在日常操作中自己会参考三个标准授权状态。页面上是否有明确的可下载、可转载标识或者是否属于公开授权的内容用途性质。是个人学习、内部参考还是对外发布、商业使用。前者灵活度更高后者需要格外谨慎影响评估。下载行为是否会对内容创作者、平台造成明显损害。比如大规模批量抓取、二次扩散会损害生态的不做这三个标准我每一条没过就会停下哪怕工具技术上完全支持。工具是用来提升效率的不是用来试探边界。5.3 对频率与流量的控制工具内置的限速、限并发机制不只是为规避风控也是对内容服务器负责。配置里max_concurrent_tasks默认 3、aria2_split默认 8单任务并发连接数其实已经不小。个人使用时我还会给自己设一条自律线每小时内启动的批量任务不超过 2 次单次解析的链接数不超过 50 个。这个数字没有科学依据但足够我处理日常需求也不会给服务器造成压力。如果要批量获取大量内容更稳妥的做法是去找平台提供的官方 API 或开放下载渠道好比走正门而不是绕窗户。video-use只是个人场景的调优工具不是大规模采集系统。6. 我日常的使用流程与优化沉淀经过几轮迭代我现在的日常使用流程基本固定为收集链接手动粘贴到一个queue.txt里先跑video-use info $(cat queue.txt)批量侦察一遍确认所有链接可解析、画质符合预期删除信息异常的链接跑video-use batch queue.txt结束后检查日志把失败任务单独再试一次定期清理tmp目录保证磁盘水位这个流程最大的价值在第二步。先侦察再下载看起来多了一步实际上省掉了很多无效下载。根据我的统计批量信息侦察能过滤掉大约 8% 的坏链接这些链接如果直接进下载流程每个都要等超时才报错浪费的时间按分钟算。另外我会用系统自带的任务计划程序把每周的视频归档做成一个半自动任务先下载再转存到 NAS最后生成一份下载清单。这样整理素材的精力成本几乎降到零我只需要每周花十分钟看一眼清单确认没有异常。最后再分享一个小技巧如果你也经常需要处理从分享页复制来的链接可以给video-use配一个命令别名把最常用的参数组合固化下来。比如我会在 shell 里写alias vuvideo-use get --format mp4 --quality highest --skip-subtitles每天敲vu 链接就完事。习惯之后这套流程用起来就跟呼吸一样自然。
返回列表