npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

video-pipeline

v1.3.3

Published

视频下载、转码、文本识别、AI 关键词分析一体化流程 CLI 工具

Readme

视频处理流水线 (Video Pipeline)

基于 process_videos.js (Node.js) 或 process_videos.py (Python),一键完成:yt-dlp 下载 → ffmpeg 转码 → whisper 识别 → AI 关键词归纳 → 写回 Excel。

五种使用方式,覆盖不同场景:

| 模式 | 输入 | 跳过步骤 | 适用场景 | |------|------|---------|----------| | Excel 批量 | Excel 行(多视频) | — | 批量处理全流程 | | --url 直链 | 单个视频 URL | — | 临时下载单个视频 | | --input 本地 | 本地视频/音频文件 | 下载 | 处理已有文件 | | --content 纯文本 | 文件路径或内联文本 | 下载+转码+识别 | 已有文本直接分析 | | --content-column | Excel 列的已有文本 | 下载+转码+识别 | 批量分析 Excel 中的文本 |


安装方式

Node.js 版本(推荐)

# 全局安装
npm install -g video-pipeline

# 使用后可直接调用
video-pipeline --help

Python 版本

# 克隆或下载脚本
git clone https://github.com/GuoSirius/yt-dlp_ffmpeg_whisper_memo-ai.git
cd yt-dlp_ffmpeg_whisper_memo-ai

# 安装 Python 依赖
pip install pandas openpyxl requests python-dotenv questionary

环境依赖

必装工具

| 工具 | 版本要求 | 安装方式 | 用途 | |------|-----------|----------|------| | Python | 3.9+ | python.org | 脚本运行 | | yt-dlp | 最新 | pip install yt-dlpGitHub Release | 视频下载 | | ffmpeg + ffprobe | 4.0+ | ffmpeg.orgwinget install ffmpeg | 音频转码 + 时长检测 |

验证安装:在终端执行 yt-dlp --versionffmpeg -versionffprobe -version,确保均在 PATH 中。

必装 Node.js(YouTube n-sig 挑战)

YouTube 要求 JS 运行时解开 n-sig 挑战,否则无法提取视频格式。

| 方式 | 安装命令 | |------|----------| | Node.js(推荐) | nodejs.org 下载 LTS 版,安装后 node --version 验证 | | Deno | winget install DenoLand.Denodeno.com |

脚本默认使用 --js-runtimes node,如果你装的是 deno,修改 .envYOUTUBE_JS_RUNTIMES=deno

Python 依赖

pip install pandas openpyxl requests python-dotenv questionary

questionary 为可选依赖(交互式确认时使用),建议一并安装。

环境变量配置(.env)

从 v2 开始,所有路径、字段映射、平台参数均通过 .env 文件配置。 这意味着同一套脚本可以直接用于其他 Excel 文件,只需修改 .env 中的值即可。

# 首次使用:复制模板
cp .env.example .env

# 编辑 .env 适配你的 Excel 结构
# 详见 .env.example 中的注释

核心配置项说明:

| 分类 | 变量 | 说明 | |------|------|------| | 输入 | EXCEL_FILE | Excel 文件路径 | | 列映射 | COL_ID / COL_TITLE / COL_CONTENT / COL_KEYWORDS | 唯一标识列 / 标题列 / 识别文本输出列 / AI 关键词输出列 | | 列映射 | COL_TENCENT / COL_BILIBILI / COL_YOUTUBE / COL_YOUKU | 各平台视频 ID 所在列 | | Sheet | VIDEO_SHEETS | 逗号分隔需要处理的 sheet(留空则全部) | | 平台 | PLATFORM_PRIORITY | 平台重试优先级 | | 平台 | {平台}_URL_TPL | URL 模板(如 YOUTUBE_URL_TPL=https://youtu.be/{youtube}) | | 平台 | {平台}_COOKIES_FROM_BROWSER | 从浏览器直读 cookie(推荐 Firefox,替代手动导出文件) | | 平台 | {平台}_COOKIE_FILE | cookie 文件路径(备用方案,需定期更新) | | 平台 | {平台}_PROXY | 代理地址(如 http://127.0.0.1:7897,Clash Verge) | | 平台 | {平台}_FORMAT / {平台}_USER_AGENT | 下载格式 / UA | | 平台 | {平台}_JS_RUNTIMES / {平台}_REMOTE_COMPONENTS | JS 运行时 / 远程组件(YouTube n-sig 求解) | | 识别 | WHISPER_BACKEND | local(本地 openai-whisper)或 service(whisper.cpp server) | | 识别 | WHISPER_* 系列 | 详见下方「Whisper 语音识别」章节——分共享(4) / 服务(2) / 本地(12) 三组,共 18 个变量 | | 工具 | YTDLP / FFMPEG / FFPROBE | 外部工具路径 | | AI 分析 | AI_ENABLED | true 启用 / false 跳过(默认 true) | | AI 分析 | AI_API_KEY / AI_BASE_URL / AI_MODEL | OpenAI 兼容 API 配置 | | AI 分析 | AI_PROMPT_TPL | 提示词模板,必须包含 {content} 占位符。支持文件路径(try-file-first),CLI 覆盖:--ai-prompt <text|path>(CLI > .env > 内置默认) | | AI 分析 | AI_TEMPERATURE | AI 推理温度 (0.0~2.0) |

.env 配置项变更权限

.env.example 中每个配置项都带有变更权限标记,含义如下:

| 标记 | 含义 | 涵盖的配置项 | 示例 | |------|------|-------------|------| | 【自由】 | 值可随意改为任意合法内容 | 路径、开关、数字、字符串、URL、UA、格式参数等 | EXCEL_FILE, YOUTUBE_PROXY, WHISPER_MODEL | | 【调序】 | 只能从固定集合中增减/排序,不能用集合外的值 | PLATFORM_PRIORITY | 只能包含 bilibili / youtube / tencent / youku | | 【关联】 | 值需与脚本内约定的 Key 名一致 | URL 模板中的 {占位符} | {youtube} 必须跟 COL_YOUTUBE 的后缀一致 | | 【固定】 | 除非 Excel 列名或脚本内部逻辑改变,否则不应修改 | 列名映射 | COL_ID=extra.idCOL_TITLE=title 等 |

最容易混淆的是【调序】PLATFORM_PRIORITY 可以调整顺序、增减条目,但只能用脚本已定义的 4 个 key,新增 tiktokdouyin 等无效 key 会导致脚本无法识别。

Whisper 语音识别

支持两种后端,通过 WHISPER_BACKEND 切换。所有 Whisper 相关环境变量分三组管理:

🔷 共享变量(两种后端均生效)

| 变量 | 默认值 | 说明 | |------|--------|------| | WHISPER_BACKEND | local | 后端选择:localservice | | WHISPER_TEMPERATURE | 0.0 | 采样温度(0.0=贪婪解码,推荐中文识别) | | WHISPER_TEMPERATURE_INC | 0.2 | 温度递减步长(fallback 时温度递增步长) | | WHISPER_OUTPUT_FORMAT | json | 输出格式:json / txt / srt / vtt / tsv |

🔶 服务模式独有WHISPER_BACKEND=service

需要本地或远程运行 whisper.cpp server,监听 http://127.0.0.1:9588

| 变量 | 默认值 | 说明 | |------|--------|------| | WHISPER_SERVICE | http://127.0.0.1:9588 | whisper.cpp server 地址 | | WHISPER_SERVICE_MODEL | (模型文件路径) | 模型文件路径,如 models/ggml-base.bin;留空=使用当前已加载模型 |

API 端点:

  • POST /inference ← 上传 wav 文件,返回识别文本(参数: file / temperature / temperature_inc / response_format)
  • POST /load ← 切换模型(参数: model=模型文件路径),脚本首次识别时自动调用,同一模型只加载一次(缓存)

注意:本地模式和服务模式不能混用。WHISPER_MODEL / WHISPER_LANGUAGE 等本地变量在服务模式下不生效,反之亦然。

🔸 本地模式独有WHISPER_BACKEND=local

需安装 openai-whisperpip install openai-whisper,脚本直接调用 whisper CLI。

| 变量 | 默认值 | 说明 | |------|--------|------| | WHISPER_TASK | transcribe | 任务类型: transcribe / translate | | WHISPER_MODEL | medium | 模型大小:tiny / base / small / medium / large-v3 / turbo | | WHISPER_LANGUAGE | zh | 语言代码(zh/en/ja 等),空=多语言自动检测 | | WHISPER_DEVICE | cpu | 推理设备:cpu / cuda | | WHISPER_MODEL_DIR | 空 | 模型缓存目录,空=~/.cache/whisper(或 $XDG_CACHE_HOME/whisper) | | WHISPER_BEAM_SIZE | 5 | Beam search 宽度(越大越准但越慢,建议 5) | | WHISPER_BEST_OF | 5 | 候选采样数(非零时启用温度采样) | | WHISPER_INITIAL_PROMPT | 生物医学 90+ 术语 | 首段音频提示词,已预填细胞/免疫/分子/蛋白/实验技术等高频术语,空格分隔。支持文件路径(try-file-first):值指向存在的文件则读取内容。CLI 覆盖:--whisper-initial-prompt <text|path>(CLI > .env > 内置默认) | | WHISPER_CONDITION_ON_PREV | False | 推荐 False:每段独立解码,避免长视频错误累积;True=前段文本传入当前段(仅适合短音频<30分钟) | | WHISPER_FP16 | False | FP16 推理(需 CUDA/GPU,CPU 上无效) | | WHISPER_THREADS | 0 | CPU 线程数(0=自动检测) | | WHISPER_EXTRA_ARGS | 空 | 额外 whisper CLI 参数(shell 字符串,如 --beam_size 5 --verbose),追加到命令末尾。同名参数自动去重(extra 覆盖已有)。CLI 覆盖:--whisper-extra-args(CLI > .env) |

选择建议:默认 False(每段独立,避免长视频错误累积);短音频(<30min)单人连贯语音可设 True 提升连贯性。专有名词多的场景可配合 INITIAL_PROMPT 提升准确率,详细示例见 .env.example。需要微调 whisper 行为时可通过 WHISPER_EXTRA_ARGS 传入额外 CLI 参数(如 --beam_size 10 --verbose),同名参数自动去重。

目录结构

├── process_videos.js              # Node.js 主流程脚本(推荐)
├── process_videos.py              # Python 主流程脚本(备选)
├── package.json                   # Node.js 项目配置(npm 包)
├── .env.example                  # 环境变量模板(可提交 Git)
├── .env                          # 实际环境变量(已 gitignore,按需修改)
├── data/                         # 数据源目录
│   └── export_2026-06-10_split.xlsx   # Excel 数据源
├── cookies/                     # 站点 cookie 文件
│   ├── bilibili.txt            # B站 cookie(Netscape 格式)
│   └── youtube.txt             # YouTube cookie 备用(Firefox 直读方案不需要)
├── output/                       # 输出根目录(可通过环境变量覆盖)
│   ├── downloads/                # yt-dlp 下载输出(mp4)
│   │   ├── youtube/              # 按平台分目录
│   │   └── bilibili/
│   ├── transcoded/               # ffmpeg 转码输出(wav 16kHz mono)
│   │   ├── youtube/
│   │   └── bilibili/
│   └── reports/                 # 执行报告(按 sheet/平台分目录)
│       ├── YouTube视频/
│       │   ├── report_YYYYMMDD_HHMMSS.json   # JSON 报告(机器可读,用于重跑)
│       │   └── tasks/                        # 人类可读文本摘要
│       │       ├── 2143.txt
│       │       └── ...
│       ├── 普诺赛中文站/
│       │   ├── report_YYYYMMDD_HHMMSS.json
│       │   └── tasks/
│       │       └── ...
│       ├── youtube/                  # --url 模式按平台名分目录
│       │   ├── report_YYYYMMDD_HHMMSS.json
│       │   └── tasks/
│       ├── local/                    # --input 模式默认目录
│       │   ├── report_YYYYMMDD_HHMMSS.json
│       │   └── tasks/
│       └── content/                  # --content 模式固定目录
│           ├── report_YYYYMMDD_HHMMSS.json
│           └── tasks/
├── scripts/                      # 辅助脚本
│   ├── release.js                 # 版本发布脚本
│   └── regenerate-changelog.js  # CHANGELOG 重建脚本
├── .github/                      # GitHub Actions 工作流
├── .husky/                      # Git hooks(commit 消息检查)
├── node_modules/                 # Node.js 依赖(已 gitignore)
├── CHANGELOG.md                  # 版本变更记录
├── README.md                     # 使用文档
└── LICENSE                       # MIT 许可证

Cookie 设置(首次使用必须)

YouTube(推荐:Firefox 浏览器直读)

yt-dlp 可直接从 Firefox 浏览器读取 cookie,无需手动导出:

  1. 用 Firefox 浏览器登录 youtube.com
  2. .env 中设置 YOUTUBE_COOKIES_FROM_BROWSER=firefox
  3. 脚本自动通过 --cookies-from-browser firefox 读取

Firefox 在 Windows 上的 cookie 加密格式 yt-dlp 可稳定解密,只要浏览器保持登录态即可。 Chrome/Edge 在 Windows 上 DPAPI 解密已知失败,不推荐使用。

YouTube(备用:手动导出文件)

如果无法使用 Firefox,可手动导出 cookie 文件:

  1. Chrome 安装扩展 Get cookies.txt LOCALLY
  2. 访问 youtube.com 并登录
  3. 点击扩展图标 → Export → 保存为 cookies/youtube.txt
  4. .env 中注释掉 YOUTUBE_COOKIES_FROM_BROWSER,启用 YOUTUBE_COOKIE_FILE=cookies/youtube.txt

⚠️ YouTube cookie 有效期约 48 小时,过期后需重新导出。下载时如果报 cookies does no longer seem to be valid,说明 cookie 已失效。优先用 Firefox 方案,免维护。

B站(bilibili)

方案 A(推荐):直接从 Firefox 浏览器读 cookie

  1. 用 Firefox 浏览器登录 bilibili.com
  2. .env 中设置 BILIBILI_COOKIES_FROM_BROWSER=firefox
  3. 脚本自动通过 --cookies-from-browser firefox 读取

Firefox cookie 直读方案同样适用于 B站,无需手动导出。

方案 B(备用):从文件读取 cookie

  1. Chrome 安装扩展 Get cookies.txt LOCALLY
  2. 访问 bilibili.com 并登录
  3. 点击扩展图标 → Export → 保存为 cookies/bilibili.txt
  4. .env 中注释掉 BILIBILI_COOKIES_FROM_BROWSER,启用 BILIBILI_COOKIE_FILE=cookies/bilibili.txt

使用方法

单条测试

# 下载 + 转码 + 识别 + AI分析,指定 sheet + extra.id
node process_videos.js --sheet "YouTube视频" --id 2143
# 或 Python 版本
python process_videos.py --sheet "YouTube视频" --id 2143

# 只跑下载
node process_videos.js --sheet "普诺赛中文站" --id 16 --step download
# 或 Python 版本
python process_videos.py --sheet "普诺赛中文站" --id 16 --step download

# 只跑转码(需要已有下载文件)
node process_videos.js --sheet "普诺赛中文站" --id 16 --step transcode

# 只跑识别(需要已有转码文件)
node process_videos.js --sheet "普诺赛中文站" --id 16 --step transcribe

# 只跑 AI 分析(需要已有识别文本)
node process_videos.js --sheet "普诺赛中文站" --id 16 --step analyze

# 强制重新下载(忽略已有文件)
node process_videos.js --sheet "YouTube视频" --id 2143 --force

批量全量

# 全量执行(2 个并发,失败重试 3 次)
node process_videos.js --concurrency 2 --retry 3

# 只跑某一 sheet
node process_videos.js --sheet "YouTube视频" --concurrency 2 --retry 3

# 先干跑预览
node process_videos.js --dry-run

# Excel 数据量大时,偏移+限量调试
node process_videos.js --offset 10 --limit 5 --dry-run  # 跳过前10条,预览5条
node process_videos.js --limit 3 --concurrency 1        # 只处理前3条

重跑失败

# 第一次跑完后生成 reports/{sheet名称}/report_xxx.json
# 查看失败项:
node process_videos.js --retry-failed reports/YouTube视频/report_20260610_143000.json --dry-run

# 重跑:
node process_videos.js --retry-failed reports/YouTube视频/report_20260610_143000.json --concurrency 2 --retry 3

超时控制(防止任务卡死)

每个步骤都有独立超时,超时后自动 kill 子进程、标记失败并继续执行后续任务:

# 自定义超时(单位秒,设为 0 表示不限制)
node process_videos.js \
    --download-timeout 1800 \   # 下载 30 分钟
    --transcode-timeout 1200 \  # 转码 20 分钟
    --transcribe-timeout 0 \    # 识别 不限制
    --analyze-timeout 300       # AI 分析 5 分钟

# 默认值:下载 1800s / 转码 1200s / 识别 0(不限制) / AI 分析 300s
  • 超时属于可重试错误,会触发指数退避重试(--retry 控制次数)
  • 无论超时多少次,不会阻塞其他并发任务,失败项会记录到报告
  • 超时失败的任务可用 --retry-failed 单独重跑

直接指定 URL 下载

# 直接指定视频链接,自动识别平台(支持标准链接、短链接、内嵌链接)
node process_videos.js --url "https://www.youtube.com/watch?v=zzJmKPX8a3c"
python process_videos.py --url "https://www.bilibili.com/video/BV1xx411c7mD"

# 指定输出文件名(不含扩展名)
node process_videos.js --url "https://youtu.be/zzJmKPX8a3c" --name "产品介绍"

# 只执行部分步骤
node process_videos.js --url "https://www.youtube.com/watch?v=zzJmKPX8a3c" --step transcode

支持的 URL 格式:

  • YouTube: 标准页、短链接、Shorts、内嵌页、直播
  • B站: 标准页(BV/av号)、短链接、内嵌页、移动端
  • 腾讯视频: 标准页、内嵌页、移动端
  • 优酷: 标准页

文件命名规则:

  • 默认:{平台}_{视频ID}(如 youtube_zzJmKPX8a3c
  • 自定义:通过 --name 指定(如 --name "产品介绍"
  • 冲突处理:自动提示选择(覆盖 / 跳过 / 自定义名称)

处理本地文件

# 指定本地视频文件,跳过下载,直接转码→识别→分析
node process_videos.js --input "downloads/产品介绍.mp4"
python process_videos.py --input "downloads/产品介绍.mp4"

# 指定输出文件名
node process_videos.js --input "downloads/产品介绍.mp4" --name "产品介绍_分析"

# 只执行部分步骤
node process_videos.js --input "downloads/产品介绍.mp4" --step analyze

文件校验:

  • 检查文件是否存在
  • 检查文件格式是否支持(视频/音频)
  • 检查是否可以正常读取
  • 校验失败会提示错误并退出

处理纯文本内容(跳过视频步骤)

如果你已经有了一段文本内容(比如爬虫爬取的、之前识别好的、或者从其他途径获取的),可以直接做 AI 分析,跳过下载、转码、识别三个步骤:

# ═══════════ --content 模式:纯文本 AI 分析 ═══════════

# 从文件读取内容,自动用文件名作为输出名
node process_videos.js --content "data/article.txt"
python process_videos.py --content "data/article.txt"

# 直接提供内联文本,自动取前 32 字符作为输出名
node process_videos.js --content "这是一段需要分析的内容..."
python process_videos.py --content "这是一段需要分析的内容..."

# 指定输出文件名(--name)
node process_videos.js --content "data/article.txt" --name "文章分析"
python process_videos.py --content "data/article.txt" --name "文章分析"

# 配合 --dry-run 预览
node process_videos.js --content "data/article.txt" --dry-run

输出文件命名规则:

  • 指定了 --name → 使用 --name 的值
  • 内容是文件路径 → 使用文件名(不含扩展名)
  • 内容是内联文本 → 使用前 32 个字符

输出位置: output/reports/content/tasks/{name}.txt + output/reports/content/report_xxx.json

Excel 列文本批量 AI 分析

当 Excel 某列已经存好了文本内容(比如之前爬虫爬取的),可以批量对这些文本做 AI 关键词分析:

# ═══════════ --content-column 模式:批量 AI 分析 ═══════════

# 对 Excel 中 "content" 列的文本逐行做 AI 关键词分析,结果写回 "keywords" 列
node process_videos.js --content-column "content"

# 指定其他列名
node process_videos.js --content-column "爬取文本"

# 指定特定 sheet
node process_videos.js --sheet "普诺赛中文站" --content-column "content"

# 配合 --dry-run 预览
node process_videos.js --content-column "content" --dry-run

# 配合 --offset / --limit 调试
node process_videos.js --content-column "content" --offset 0 --limit 3
node process_videos.js --content-column "content" --concurrency 2 --retry 2

注意--content-column 模式自动设置 --step analyze(仅 AI 分析),不会触发下载/转码/识别。 文本为空的行会自动跳过。 分析结果写入 Excel 的 keywords 列(由 COL_KEYWORDS 环境变量指定)。

工具预检(执行前自动检测)

每次执行任务前,脚本会自动检测本次涉及步骤所需的工具/服务是否可用:

| 步骤 | 检测项 | 不可用时行为 | |------|--------|-------------| | download | yt-dlp 可调用 | 提示用户,输入 yes 继续 / 其他取消 | | transcode | ffmpeg + ffprobe 可调用 | 同上 | | transcribe | whisper 服务/本地 CLI 可连通 | 同上 | | analyze | AI_ENABLED=true 且 API 配置完整 | 同上 |

  • dry-run 模式下同样展示检测结果(但不中断执行)
  • 所有模式(正常执行、重跑失败、单步运行)均执行预检
  • 即使工具不可用,用户仍可选择强制继续(但相应步骤大概率失败)

参数说明

| 参数 | 类型 | 默认值 | 说明 | |------|------|---------|------| | --sheet <name> | str | 全部 | 指定 sheet 名称 | | --id <id> | str | — | 指定 extra.id 或 title(单条测试) | | --offset <n> | int | 0 | 跳过前 N 条任务(从 0 开始),适合调试大量数据 | | --limit <n> | int | 0 | 最多处理 N 条任务,0 表示无限制 | | --step <step> | str | 全跑 | 只执行某步:download / transcode / transcribe / analyze | | --force | flag | off | 强制重做下载+转码,忽略已有文件 | | --concurrency <n> | int | 1 | 并发数,建议 2~3 | | --retry <n> | int | 0 | 每步失败最大重试次数 | | --retry-delay <n> | float | 5 | 重试间隔基数(秒),指数退避 5→10→20 | | --download-timeout <n> | int | 1800 | 单个下载任务最长执行时间(秒),0=不限制 | | --transcode-timeout <n> | int | 1200 | 单个转码任务最长执行时间(秒),0=不限制 | | --transcribe-timeout <n> | int | 0 | 单个识别任务最长执行时间(秒),0=不限制 | | --analyze-timeout <n> | int | 300 | 单个 AI 分析任务最长执行时间(秒),0=不限制 | | --dry-run | flag | off | 干跑模式,只列任务不执行 | | --retry-failed <path> | path | — | 从报告 JSON 重跑失败项(如 reports/YouTube视频/report_xxx.json) | | --init | flag | off | 复制 .env.example 到当前目录并重命名为 .env | | --file <path> | path | — | 指定 Excel 文件路径(优先级高于 EXCEL_FILE 环境变量) | | --input <path> | path | — | 指定本地视频文件路径(跳过下载,直接转码→识别→分析) | | --url <url> | str | — | 直接指定视频下载链接(跳过 Excel),支持标准链接和内嵌链接 | | --content <text 或 path> | str | — | 直接提供文本内容(文件路径或内联文本),跳过下载/转码/识别,仅做 AI 分析 | | --content-column <col> | str | — | Excel 模式:指定包含已有文本的列名,批量做 AI 分析(自动设 --step analyze) | | --name <name> | str | — | 指定输出文件名,不含扩展名(与 --url / --input / --content 配合使用) | | --env-file <path> | path | .env | 指定要加载的 .env 文件路径 | | --whisper-initial-prompt <text\|path> | str | .env | Whisper 初始提示词(文本或文件路径,CLI 优先级最高) | | --ai-prompt <text\|path> | str | .env | AI 分析提示词模板(文本或文件路径,CLI 优先级最高) | | --whisper-extra-args <args> | str | .env | Whisper 额外参数(shell 字符串,如 "--beam_size 5",最高优先级且自动去重) |


重试规则

| 可重试 | 不重试 | |----------|----------| | 网络超时、连接拒绝 | HTTP 404 / 403 / 401 | | yt-dlp 下载中断 | 视频已删除 / 私有 | | whisper 服务超时 | 无效 URL、文件不存在 | | 步骤级超时(任务卡死) | 参数错误(ValueError/TypeError) |


智能跳过与自动重转码

脚本默认不会重复处理已有文件,但会在以下情况自动触发重做:

| 步骤 | 跳过条件 | 自动重做条件 | |------|-----------|----------------| | 下载 | 同名文件已存在(非 --force) | --force 或文件不存在 | | 转码 | WAV 已存在 MP4 时间戳 ≤ WAV 时间戳 | --forceMP4 比 WAV 新(重新下载过) | | 识别 | —(每次必跑,覆盖写入 Excel) | — |

关键设计:即使不加 --force,只要视频重新下载过(MP4 的修改时间晚于 WAV),转码也会自动重新执行,确保下载和转码内容始终保持一致


临时文件自动清理

yt-dlp 下载过程中会生成 .part(未完成分片)和 .ytdl(元数据)临时文件。脚本在以下时机自动清理这些残留:

| 时机 | 说明 | |------|------| | 下载开始前 | 清除上次中断留下的 .part / .ytdl,确保干净环境 | | 跳过已有文件时 | 检查并清除该视频的历史残留 | | 下载失败后 | 立即清理,避免无效文件占磁盘 |

例如:2152.mp4.part + 2152.mp4.ytdl 会在下次下载该视频时自动删除,无需手动清理。


AI 关键词归纳

在识别完成后,脚本可自动调用 OpenAI 兼容 API 对识别文本做关键词归纳,结果写入 keywords 列。

配置

.env 中配置以下变量(见 .env.example):

# 启用/禁用 AI 分析环节
AI_ENABLED=true

# OpenAI 兼容 API(支持任何兼容接口)
AI_API_KEY=sk-xxx
AI_BASE_URL=https://apihub.agnes-ai.com/v1
AI_MODEL=agnes-2.0-flash

# 提示词模板({content} 会被识别文本替换)
# 采用两步法:先语义修正 Whisper 同音/形近/术语错误,再提取关键词
# 支持文件路径:值指向存在的文件则读取内容(try-file-first 策略)
# CLI 覆盖:--ai-prompt <text|path> 优先级最高(CLI > .env > 内置默认)
AI_PROMPT_TPL=你是多语言内容分析专家...这是内容:{content}

# 请求超时(秒,通过 --analyze-timeout 参数设置)

工作原理

  1. whisper 识别完成 → 得到文本(存入 content 列)
  2. AI 先对识别文本做语义修正(修正 Whisper 常见的同音错字、专业术语误判、形近字混淆)
  3. 再对修正后的文本提取搜索关键词 → 写入 keywords

提示词模板可自由定制:只需保留 {content} 占位符,提示词内容可改为翻译、摘要、分类等任意任务。完整模板见 .env.example。值支持文件路径(指向存在的文件则自动读取内容),也可通过 --ai-prompt CLI 参数临时覆盖(优先级:CLI > .env > 内置默认)。

单独运行

# 已有识别文本,只跑 AI 分析
node process_videos.js --sheet "普诺赛中文站" --id 427 --step analyze
# 或 Python 版本
python process_videos.py --sheet "普诺赛中文站" --id 427 --step analyze

# 单独跑 analyze 超过 16 条不会写入 Excel
# 要想写入 Excel 跑完整流程 --step analyze
node process_videos.js --sheet "YouTube视频" --step analyze --concurrency 2

禁用 AI 分析

设置 AI_ENABLED=false,识别完成后跳过 AI 分析步骤。

提示词优先级

WHISPER_INITIAL_PROMPTAI_PROMPT_TPL 均支持三种输入方式:

| 方式 | 示例 | 说明 | |------|------|------| | 内联文本 | WHISPER_INITIAL_PROMPT=细胞 冻存 | 直接写入值 | | 文件路径 | AI_PROMPT_TPL=./prompts/my-prompt.txt | 值指向存在的文件时自动读取内容 | | CLI 覆盖 | --ai-prompt ./prompts/custom.txt | 优先级最高,临试覆盖不修改 .env |

优先级:CLI 参数 > .env 环境变量 > 内置默认值

# 用自定义 prompt 文件跑全量
video-pipeline --ai-prompt ./prompts/keyword-extract.txt --sheet "普诺赛中文站"

# 临时覆盖 whisper 初始提示词 + 额外参数
video-pipeline --whisper-initial-prompt "细胞冻存,复苏" --whisper-extra-args "--beam_size 10 --verbose" --id 427

文件名去重

脚本默认使用 COL_ID(即 extra.id)作为文件名 stem。当同一个 sheet 内出现重复 id 时,自动应用以下去重策略:

| 优先级 | 格式 | 示例 | |--------|------|------| | 1 | {id} | 2143 | | 2 | {id}_{title} | 2143_产品介绍 | | 3 | {id}_{title}_{platform} | 2143_产品介绍_bilibili |

去重仅在同 sheet 内生效,不同 sheet 之间允许同名文件(存放在不同子目录)。


进度显示

执行时会同时展示总体进度单视频进度

[1/91] [2143] 开始处理 (sheet=YouTube视频, platform=youtube, title=xxx)
  [2143] 开始下载 (平台=youtube)
  [2143] https://youtu.be/zzJmKPX8a3c
  [2143] 解析页面...
  [2143] 15.2% 2.50MiB/s ETA 00:17          ← 下载实时进度
  [2143] 45.8% 3.12MiB/s ETA 00:08
  [2143] 下载完成 -> 2143.mp4
  [2143] 开始转码 -> 2143.wav
  [2143] 25.3% (38s/150s)                    ← 转码进度 + 时长比
  [2143] 50.1% (75s/150s)
  [2143] 转码完成
  [2143] 开始识别 (文件 45.2MB)...
  [2143] 识别中... 5s                        ← 识别每 5s 报时
  [2143] 识别完成 (22s, 1234 字符)
  [2143] AI 分析中... 5s                     ← AI 每 5s 报时
  [2143] AI 分析中... 10s
  [2143] AI 分析完成 (567 字符)

[总进度 1/91 (1.1%)] ✅1 ❌0 ⚠️0 ⏭️0         ← 每完成一个刷新

| 层级 | 显示内容 | |------|----------| | 总体进度 | 完成/总任务数、百分比、✅成功 ❌失败 ⚠️部分 ⏭️无视频 四维计数 | | 下载 | yt-dlp 实时百分比 + 速度 + ETA | | 转码 | 先 ffprobe 取时长,再实时解析 time= 算百分比(如 25.3% (38s/150s)) | | 识别 | 每 5s 打印已用时间,完成时显示总耗时和文本长度 | | AI 分析 | 每 5s 打印已用时间,完成时显示结果长度或失败原因 |

多线程并发时使用打印锁保证输出不交错。


输出结构速查表

五种输入来源在不同处理环节的输出路径汇总如下。所有路径均以 output/ 为根(可通过 DOWNLOADS_DIR / TRANSCODED_DIR / REPORTS_DIR 环境变量覆盖)。

{sheet} = Excel 工作表名(如 YouTube视频普诺赛中文站{platform} = 视频平台标识(如 youtubebilibilitencentyouku{stem} = 去重后的安全文件名(不含扩展名)

① Excel 批量模式(默认)

| 环节 | 输出路径 | 产物格式 | 说明 | |------|---------|---------|------| | 下载 | output/downloads/{sheet}/{stem}.mp4 | 视频 | yt-dlp 下载原始视频 | | 转码 | output/transcoded/{sheet}/{stem}.wav | 音频 | ffmpeg 转 16kHz mono WAV | | JSON 报告 | output/reports/{sheet}/report_YYYYMMDD_HHMMSS.json | JSON | 机器可读,含 summary + failed_items,可供 --retry-failed 重跑 | | 文本报告 | output/reports/{sheet}/tasks/{stem}.txt | 文本 | 人类可读,含语音识别原文 + AI 关键词分析 |

多 sheet 同时执行时,每个 sheet 独立一个子目录,互不干扰。

② --url 直链模式

| 环节 | 输出路径 | 产物格式 | 说明 | |------|---------|---------|------| | 下载 | output/downloads/{platform}/{name}.mp4 | 视频 | yt-dlp 下载单个视频 | | 转码 | output/transcoded/{platform}/{name}.wav | 音频 | ffmpeg 转 16kHz mono WAV | | JSON 报告 | output/reports/{platform}/report_YYYYMMDD_HHMMSS.json | JSON | 格式与 Excel 模式一致 | | 文本报告 | output/reports/{platform}/tasks/{name}.txt | 文本 | 含识别原文 + AI 分析 |

{platform} 由脚本自动从 URL 解析,如 https://www.youtube.com/watch?v=xxxyoutube

③ --input 本地文件模式

| 环节 | 输出路径 | 产物格式 | 说明 | |------|---------|---------|------| | 下载 | —(跳过) | — | 本地文件无需下载 | | 转码 | output/transcoded/local/{stem}.wav | 音频 | ffmpeg 转 16kHz mono WAV | | JSON 报告 | output/reports/local/report_YYYYMMDD_HHMMSS.json | JSON | 格式与 Excel 模式一致 | | 文本报告 | output/reports/local/tasks/{stem}.txt | 文本 | 含识别原文 + AI 分析 |

local--input 模式的固定目录名(与 Excel 模式的 sheet 名无关),所有本地文件处理结果统一归入此目录。

④ --content 纯文本模式

| 环节 | 输出路径 | 产物格式 | 说明 | |------|---------|---------|------| | 下载 | —(跳过) | — | 无需下载 | | 转码 | —(跳过) | — | 无需转码 | | 识别 | —(跳过) | — | 无需语音识别 | | JSON 报告 | output/reports/content/report_YYYYMMDD_HHMMSS.json | JSON | 格式与 Excel 模式一致 | | 文本报告 | output/reports/content/tasks/{stem}.txt | 文本 | 含源内容 + AI 关键词分析 |

content 是固定目录名。{stem} = --name 值 > 文件名 stem > 内联文本前 32 字符。

⑤ --content-column Excel列文本批量模式

| 环节 | 输出路径 | 产物格式 | 说明 | |------|---------|---------|------| | 下载 | —(跳过) | — | 无需下载 | | 转码 | —(跳过) | — | 无需转码 | | 识别 | —(跳过) | — | 无需语音识别 | | JSON 报告 | output/reports/{sheet}/report_YYYYMMDD_HHMMSS.json | JSON | 按 Excel sheet 分目录,格式与 Excel 模式一致 | | 文本报告 | output/reports/{sheet}/tasks/{stem}.txt | 文本 | 含列文本 + AI 关键词分析 | | Excel 写回 | {EXCEL_FILE}keywords 列 | Excel | AI 关键词写入 Excel |

此模式自动设置 --step analyze,下载/转码/识别全跳过。AI 结果同时写入 Excel 和报告文件。


五种来源对比一览

| 维度 | Excel 批量 | --url 直链 | --input 本地文件 | --content 纯文本 | --content-column 列文本 | |------|-----------|-----------|-----------------|-----------------|------------------------| | 输入 | Excel 行(多视频批量) | 单个视频 URL | 本地视频/音频文件 | 文件路径或内联文本 | Excel 列的已有文本 | | 下载 | ✅ yt-dlp | ✅ yt-dlp | ❌ 跳过 | ❌ 跳过 | ❌ 跳过 | | 转码 | ✅ ffmpeg | ✅ ffmpeg | ✅ ffmpeg | ❌ 跳过 | ❌ 跳过 | | 识别 | ✅ whisper | ✅ whisper | ✅ whisper | ❌ 跳过 | ❌ 跳过 | | AI 分析 | ✅ | ✅ | ✅ | ✅ | ✅ | | 下载目录 | downloads/{sheet}/ | downloads/{platform}/ | 无 | 无 | 无 | | 转码目录 | transcoded/{sheet}/ | transcoded/{platform}/ | transcoded/local/ | 无 | 无 | | 报告目录 | reports/{sheet}/ | reports/{platform}/ | reports/local/ | reports/content/ | reports/{sheet}/ | | 分组依据 | Excel sheet 名 | URL 解析的平台名 | 固定 local | 固定 content | Excel sheet 名 | | 并发支持 | ✅ 多线程 | ❌ 单任务 | ❌ 单任务 | ❌ 单任务 | ✅ 多线程 | | 写入 Excel | ✅ | ❌ | ❌ | ❌ | ✅ | | 支持 --retry-failed | ✅ | ❌ | ❌ | ❌ | ❌ | | 适用场景 | 批量处理全流程 | 临时下载单个视频 | 处理已有视频文件 | 已有文本直接分析 | 批量分析Excel中的文本 |


JSON 报告结构

{
  "timestamp": "2026-06-10T14:30:00",
  "config": { "concurrency": 3, "retry": 3 },
  "summary": {
    "total": 91,
    "success": 85,
    "partial": 3,
    "failed": 2,
    "no_video": 1
  },
  "failed_items": [
    {
      "sheet": "普诺赛中文站",
      "id": "427",
      "title": "xxx视频",
      "download_error": "HTTP Error 403",
      "transcode_error": null,
      "transcribe_error": null
    }
  ]
}

状态含义

  • success:下载 + 转码 + 识别全部成功(AI 分析失败不影响此状态)
  • partial:下载 + 转码成功,识别或 AI 分析失败
  • failed:下载或转码失败
  • no_video:该行无可用视频 ID

典型工作流

场景一:Excel 批量处理视频

# 1. 干跑预览
node process_videos.js --dry-run
# 或 Python 版本
python process_videos.py --dry-run

# 2. 单条验证
node process_videos.js --sheet "YouTube视频" --id 2143 --retry 2

# 3. 全量执行
node process_videos.js --concurrency 3 --retry 3

# 4. 查看报告,重跑失败项
node process_videos.js --retry-failed reports/YouTube视频/report_xxx.json --concurrency 2 --retry 3

场景二:临时下载单个视频

# 从 URL 下载 → 转码 → 识别 → AI 分析,一条龙
node process_videos.js --url "https://www.youtube.com/watch?v=zzJmKPX8a3c"

# 指定输出文件名
node process_videos.js --url "https://www.bilibili.com/video/BV1xx411c7mD" --name "产品介绍视频"

场景三:处理本地视频文件

# 已有视频文件,直接转码分析
node process_videos.js --input "downloads/产品介绍.mp4"

# 只做 AI 分析(已有转码+识别结果)
node process_videos.js --input "downloads/产品介绍.mp4" --step analyze

场景四:纯文本 AI 分析

# 已有文本内容,跳过所有视频步骤,直接做关键词提取
node process_videos.js --content "data/article.txt"

# 内联文本直接分析
node process_videos.js --content "今天我们要讨论的是普诺赛产品..." --name "产品讨论"

场景五:批量分析 Excel 中的已有文本

# Excel 某列已有文本(如爬虫爬取的),批量做 AI 关键词分析
node process_videos.js --content-column "content" --dry-run      # 先预览
node process_videos.js --content-column "content" --concurrency 2  # 执行

平台适配说明

脚本支持四个视频平台的下载,各有不同的反爬配置:

| 平台 | 字段 | 反爬措施 | |------|-------|----------| | B站 (bilibili) | extra.bilibili | Chrome UA + Referer 头 + 有效 cookie + 并发分片 | | YouTube | extra.youtube | Chrome UA + Firefox cookie 直读 + 代理 + Node.js 解 n-sig | | 腾讯视频 | extra.tencent | 无需特殊配置 | | 优酷 | extra.youku | 无需特殊配置(部分视频需会员) |

YouTube 反爬最强:需要 代理 + 登录态 cookie + JS runtime 解 n-sig 三者配合。 脚本会自动给 yt-dlp 及其 node/ejs 子进程注入 HTTPS_PROXY 环境变量,确保所有流量走代理。

各平台 URL 格式与视频 ID 提取

脚本通过 {平台}_URL_TPL 生成下载链接,支持 yt-dlp 能识别的所有 URL 格式。 下表列出各平台「标准页面 / 内嵌链接 / 短链接」格式及视频 ID 提取正则,方便从完整 URL 中解析视频 ID。

YouTube

| 格式类型 | URL 示例 | 视频 ID 提取正则 | |----------|-----------|-------------------| | 标准观看页 | https://www.youtube.com/watch?v=VIDEO_ID | youtube\.com/watch\?v=([a-zA-Z0-9_-]{11}) | | 短链接 | https://youtu.be/VIDEO_ID | youtu\.be/([a-zA-Z0-9_-]{11}) | | Shorts | https://www.youtube.com/shorts/VIDEO_ID | youtube\.com/shorts/([a-zA-Z0-9_-]{11}) | | 内嵌页 | https://www.youtube.com/embed/VIDEO_ID | youtube\.com/embed/([a-zA-Z0-9_-]{11}) | | 直播 | https://www.youtube.com/live/VIDEO_ID | youtube\.com/live/([a-zA-Z0-9_-]{11}) |

  • 视频 ID 格式:11 位字符(大小写字母 + 数字 + - + _
  • 统一提取正则(覆盖所有格式):
    (?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/|live\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})
  • 格式互转
    • 标准 → 短链接:提取 VIDEO_IDhttps://youtu.be/VIDEO_ID
    • 标准 → 内嵌:提取 VIDEO_IDhttps://www.youtube.com/embed/VIDEO_ID
    • Shorts → 标准:提取 VIDEO_IDhttps://www.youtube.com/watch?v=VIDEO_ID

B站(bilibili)

| 格式类型 | URL 示例 | 视频 ID 提取正则 | |----------|-----------|-------------------| | 标准页(BV 号) | https://www.bilibili.com/video/BV1xx411c7mD | bilibili\.com\/video\/(BV[a-zA-Z0-9]{10}) | | 标准页(av 号) | https://www.bilibili.com/video/av170001 | bilibili\.com\/video\/av(\d+) | | 短链接 | https://b23.tv/BV1xx411c7mD | b23\.tv\/(BV[a-zA-Z0-9]{10}) | | 内嵌页 | https://player.bilibili.com/player.html?bvid=BV1xx411c7mD&cid=CID | bvid=(BV[a-zA-Z0-9]{10}) | | 移动端 | https://m.bilibili.com/video/BV1xx411c7mD | m\.bilibili\.com\/video\/(BV[a-zA-Z0-9]{10}) |

  • BV 号格式BV + 10 位字符(大小写敏感)
  • 统一提取正则
    bilibili\.com\/video\/(BV[a-zA-Z0-9]{10})|bvid=(BV[a-zA-Z0-9]{10})
  • 格式互转
    • 标准 → 内嵌:提取 BV_ID 后需通过 B站 API 获取 cidhttps://api.bilibili.com/x/player/pagelist?bvid=BV_ID 获取 cid → 内嵌 URL:https://player.bilibili.com/player.html?bvid=BV_ID&cid=CID&page=1
    • BV 号 → av 号:需调用 API(https://api.bilibili.com/x/web-interface/view?bvid=BV_ID 返回 aid

腾讯视频

| 格式类型 | URL 示例 | 视频 ID 提取正则 | |----------|-----------|-------------------| | 标准页(x/page) | https://v.qq.com/x/page/VIDEO_ID.html | v\.qq\.com\/x\/page\/([a-zA-Z0-9]+)\.html | | 标准页(x/cover) | https://v.qq.com/x/cover/COVER/VIDEO_ID.html | v\.qq\.com\/x\/cover\/[^\/]+\/([a-zA-Z0-9]+)\.html | | 内嵌页 | https://v.qq.com/txp/iframe/player.html?vid=VIDEO_ID | [?&]vid=([a-zA-Z0-9]+) | | 移动端 | https://m.v.qq.com/x/mv.xhtml?vid=VIDEO_ID | [?&]vid=([a-zA-Z0-9]+) |

  • 视频 ID 格式:字母 + 数字组合(如 o0325y3hqh,长度不固定)
  • 统一提取正则
    v\.qq\.com\/(?:x\/page\/|x\/cover\/[^\/]+\/)([a-zA-Z0-9]+)\.html|[?&]vid=([a-zA-Z0-9]+)
  • 格式互转
    • 标准 → 内嵌:提取 VIDEO_IDhttps://v.qq.com/txp/iframe/player.html?vid=VIDEO_ID

优酷(Youku)

| 格式类型 | URL 示例 | 视频 ID 提取正则 | |----------|-----------|-------------------| | 标准页(v_show) | https://v.youku.com/v_show/id_VIDEO_ID.html | v\.youku\.com\/v_show\/id_([a-zA-Z0-9=]+)\.html | | 标准页(video) | https://v.youku.com/video/VIDEO_ID | v\.youku\.com\/video\/([a-zA-Z0-9=]+) | | 标准页(www) | https://www.youku.com/v_show/id_VIDEO_ID.html | www\.youku\.com\/v_show\/id_([a-zA-Z0-9=]+)\.html |

  • 视频 ID 格式:旧格式 X + Base64 字符串(可能含 = 填充);新格式长度不固定
  • 统一提取正则
    v\.youku\.com\/v_show\/id_([a-zA-Z0-9=]+)\.html|v\.youku\.com\/video\/([a-zA-Z0-9=]+)
  • 格式互转
    • 优酷内嵌格式较复杂,建议直接使用标准页链接({YOUKU_URL_TPL}

脚本使用提示:Excel 中只需填入视频 ID(如 zzJmKPX8a3cBV1pg411b7Ugo0325y3hqhXMzgxNzExNTY4MA==),脚本自动替换 URL 模板中的 {youtube}{bilibili} 等占位符生成下载链接。

常见下载错误

| 错误 | 平台 | 原因 | 解决方案 | |------|------|------|----------| | Sign in to confirm you're not a bot | YouTube | cookie 过期或无效 | 检查 Firefox 登录态,或重新导出 cookie 文件 | | cookies does no longer seem to be valid | YouTube | cookie 文件超过 48h | 用 Firefox cookies-from-browser 方案(免维护) | | Unable to download webpage: HTTP Error 403 | YouTube | IP 被识别为非 YouTube 地区 | 确保代理运行(端口 7897),检查 YOUTUBE_PROXY | | n challenge solving failed | YouTube | 无 JS 运行时 | 安装 Node.js,确保 YOUTUBE_JS_RUNTIMES=node | | Requested format is not available | YouTube | n-sig 未解开,格式不可用 | 同上,安装 JS 运行时 | | HTTP Error 412 | B站 | 缺少 Chrome UA 或 cookie 过期 | 重新导出 cookies/bilibili.txt 或使用 Firefox 直读 | | HTTP Error 403 | B站 | 地区限制或视频已删除 | 检查视频是否可访问 | | dpapi decryption failed | YouTube | Windows Chrome cookie 加密 | 改用 Firefox.env 中设 YOUTUBE_COOKIES_FROM_BROWSER=firefox) |


换电脑使用

Node.js 版本

  1. 安装 Node.js (18+):nodejs.org
  2. 安装视频处理工具:
    npm install -g video-pipeline
  3. 克隆或下载项目文件(.env.example.envcookies/ 等)
  4. 安装必装工具:yt-dlpffmpegffprobe,确保均在 PATH
  5. 用 Firefox 登录 YouTube,设置 YOUTUBE_COOKIES_FROM_BROWSER=firefox
  6. B站 cookie 仍需手动导出 cookies/bilibili.txt(或设置 BILIBILI_COOKIES_FROM_BROWSER=firefox
  7. 启动代理(Clash Verge 等),确认端口匹配 YOUTUBE_PROXY
  8. video-pipeline --dry-run 验证

Python 版本

  1. 安装 Python 3.9+:python.org
  2. 安装必装工具:yt-dlpffmpegffprobe,确保均在 PATH
  3. 安装 Python 依赖:pip install pandas openpyxl requests python-dotenv questionary
  4. cp .env.example .env,根据实际情况修改 .env 中的路径、代理端口和字段映射
  5. 用 Firefox 登录 YouTube,设置 YOUTUBE_COOKIES_FROM_BROWSER=firefox
  6. B站 cookie 仍需手动导出 cookies/bilibili.txt(或设置 BILIBILI_COOKIES_FROM_BROWSER=firefox
  7. 启动代理(Clash Verge 等),确认端口匹配 YOUTUBE_PROXY
  8. python process_videos.py --dry-run 验证

适配其他 Excel

如果需要用这套脚本处理其他项目的 Excel(列名不同、平台不同):

方法一:修改 .env 文件

  1. 复制 .env.example 为新 .env(或修改现有 .env
  2. 修改 EXCEL_FILE 指向新 Excel
  3. 修改列映射(COL_IDCOL_TITLECOL_CONTENT 及各平台列名)
  4. 修改 VIDEO_SHEETS 为新的 sheet 名称
  5. 如需新平台,在 PLATFORM_PRIORITY 中添加 key,并配置对应的 {KEY}_URL_TPL
  6. node process_videos.js --dry-run 验证配置
  7. 跑全量

方法二:使用 --file 选项(推荐)

# 直接指定 Excel 文件,无需修改 .env
node process_videos.js --file "data/其他项目.xlsx" --dry-run

# 配合 --env-file 使用自定义环境变量
node process_videos.js --file "data/其他项目.xlsx" --env-file ".env.其他项目" --dry-run

优点:

  • 无需修改 .env 文件
  • 可以为不同项目创建不同的 .env 配置文件
  • 命令行优先级高于环境变量