mcpField
V
video-download

video-download

github.com/csfuwwcクリエイティブ・メディア4206 回インストール今日更新
リポジトリ

video-download について

SNSの共有リンクから動画を保存するスキルです。単体または一括で動画をローカルに取得するワークフロー向けに、共通スクリプトがサイト別の取得方法や代替手段を選び、ファイルを検証します。

主な機能

  1. 01複数サイトのリンク認識とダウンロード
  2. 02サイト別の主エンジンと代替手段の選択
  3. 03ログイン状態の確認と対話型ログイン
  4. 04動画ファイルの検証とメタデータ出力

活用シーン

  1. 01共有リンクからSNS動画を保存
  2. 02一括処理で共通のダウンロード入口を利用
  3. 03B站のログインを確認して高画質動画を取得

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/csfuwwc/md-skills --skill video-download

インストール後、Claude Code で/video-downloadを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

scripts/
download.py
tests/
test_douyin_cdp.py
test_douyin_warning_dom.py
test_platform_fallbacks.py
test_tiktok_cdp_endpoint.py
test_tiktok_list_media.py
test_wechat_channels.py

詳細

视频下载(视频号 / 抖音 / 小红书 / B站 + YouTube / Twitter 等)

统一入口原则(重要)

  • 本 skill 是社媒视频下载的唯一入口。
  • 当任务来自飞书多维表格(Base)/表格批处理时,下载动作也必须调用本 skill 的 scripts/download.py,不要在业务脚本里另写直连下载器。
  • 需要正文/点赞/收藏时,可以在业务脚本里各自抓取;但“视频文件获取”必须复用本 skill 的下载链路与校验能力。

从分享链接下载视频到本地。视频号使用用户配置的自托管解析器取得临时直链;B站优先使用 yt-dlp,失败后回退 Playwright;抖音/小红书优先使用 Playwright,抓流失败后回退 yt-dlp;TikTok 优先使用真实浏览器 CDP 抓流。

下载流程

重要:下载 B站视频前,必须先检查登录状态(未登录只能获取 480p)。

先进入 skill 根目录后再执行以下命令(命令均使用相对路径):

cd <your-skill-root>/video-download
步骤 1:检查登录状态(B站必须)
python3 ./scripts/download.py check-login bilibili
  • 退出码 0(输出 LOGIN_OK)→ 直接跳到步骤 3 下载
  • 退出码 2(输出 LOGIN_REQUIRED)→ 需要执行步骤 2 登录
步骤 2:交互式登录(需要时)

当 check-login 返回退出码 2 时,按以下流程操作:

  1. 后台启动登录浏览器(设置 block_until_ms: 0):
python3 ./scripts/download.py login bilibili --signal-file /tmp/video_dl_login_done
  1. 立即向用户展示确认按钮,使用 AskQuestion 工具:

    • 提示:「已打开 B站 登录页面,请在浏览器中完成登录,完成后点击下方确认按钮。」
    • 选项 A:「已完成登录」
    • 选项 B:「跳过登录(使用低画质)」
  2. 用户点击确认后:

    • 选择 A:创建信号文件 touch /tmp/video_dl_login_done,等待登录脚本退出,然后继续下载
    • 选择 B:终止登录脚本进程,直接下载(低画质)
  3. 兜底:如果用户直接关闭了浏览器窗口,登录脚本会自动检测到并保存 cookie,无需信号文件。

步骤 3:下载视频
python3 ./scripts/download.py "<分享文本或链接>" [输出文件名.mp4]

平台支持

脚本自动识别平台,并按平台使用不同的主引擎与兜底引擎:

平台支持的链接格式引擎需要登录备注
微信视频号weixin.qq.com/sph/xxx、channels.weixin.qq.com/finder-preview/pages/sph?id=xxx自托管解析器 + 直链下载解析器端需要优先 H.264,下载后用 ffprobe 校验
抖音v.douyin.com/xxx 短链、www.douyin.com/video/xxx、modal_id=xxxPlaywright→yt-dlp视风控优先抓网络请求;失败后使用已保存 Cookie 回退
小红书xiaohongshu.com/discovery/item/xxx、explore/xxx、xhslink.com/xxxPlaywright→yt-dlp视内容优先抓网络请求;失败后使用已保存 Cookie 回退
B站bilibili.com/video/BVxxx、b23.tv/xxx 短链yt-dlp→Playwright推荐yt-dlp 处理清晰度与音视频合并;需要 ffmpeg
TikToktiktok.com/@user/video/xxx、vm.tiktok.com/xxxCDP→tikwm→yt-dlp推荐优先真实浏览器 CDP;app-only/shop 场景自动尝试 tikwm 兜底
YouTubeyoutube.com/watch?v=xxx、youtu.be/xxxyt-dlp否
Twitter/Xx.com/xxx/status/xxx、twitter.com/...yt-dlp否
Instagraminstagram.com/reel/xxx、instagram.com/p/xxxyt-dlp否私密内容需登录
其他任意视频链接yt-dlp视站点支持 1700+ 站点
  • 回退条件包括「主引擎崩溃」,不只是「没抓到地址」:Playwright 抛的异常会被包成 RuntimeError,由调用方接住转兜底引擎;到顶层也只打一行错误,不会甩 traceback
  • 输出文件名可选,默认从视频标题生成
  • 文件保存到 ~/Downloads/
  • 依赖:playwright、yt-dlp、ffmpeg(B站及分离音视频格式合并)

B站、抖音与小红书回退策略

按以下顺序下载:

  1. B站:yt-dlp → Playwright。
  2. 抖音、小红书:Playwright → yt-dlp。
  3. yt-dlp 需要 Cookie 时,只使用 ~/.config/video-download/<平台>_cookies.json 中对应平台的 Cookie。
  4. 脚本把该平台 Cookie 临时转换为 Netscape 格式,权限设为 0600,yt-dlp 结束后立即删除;不要默认读取整个浏览器 Cookie 数据库。
  5. Cookie 缺失或失效时,先执行 python3 ./scripts/download.py login <平台>,再重试下载。

微信视频号专项说明

视频号分享页通常只公开封面和基础元数据,不直接暴露可下载的视频地址。本 Skill 借鉴 ltaoo/wx_channels_download 的分享链接解析接口形状,但不会安装根证书、修改系统代理,也不会直接保存或发送元宝 Cookie。

优先配置 Video-Picture-OSS-Auth 自托管解析器;脚本也兼容 wx_channels_download 的嵌套响应结构:

export WECHAT_CHANNELS_RESOLVER_URL="http://api-ai.modianinc.com:8080/wechat/channels/resolve"
export WECHAT_CHANNELS_RESOLVER_API_KEY="<WECHAT_API_KEY>"
  • WECHAT_CHANNELS_RESOLVER_API_KEY 可选;配置后通过 X-API-Key 请求头发送。
  • 元宝登录 Cookie 只应保存在解析器服务端的 WECHAT_CHANNELS_YUANBAO_COOKIE 环境变量或 GitHub Secret 中,不能放进 Skill、命令参数、Git 或元数据文件。
  • 公网 HTTP 会明文传输 API Key 和解析结果;当前无 HTTPS 时仅建议在可信网络临时使用,并尽快迁移到 HTTPS 或内网。
  • 解析器应返回可直接下载的 URL;若返回解密密钥,Skill 会拒绝下载并要求解析器提供已解密代理地址。

仅解析并查看元数据、临时直链:

python3 ./scripts/download.py resolve "https://weixin.qq.com/sph/ARebDCbPGy"

解析并下载:

python3 ./scripts/download.py "https://weixin.qq.com/sph/ARebDCbPGy" "video.mp4"

成功后生成:

  • 视频文件(默认 ~/Downloads/,可用 VIDEO_DOWNLOAD_OUTPUT_DIR 修改)
  • <视频文件>.meta.json,包含作者、描述、封面、时间和互动数据,不包含临时视频 URL、API Key 或 Cookie

TikTok 専用の説明(CDP 優先)

スクリプトは、以下の CDP ポートへの接続を優先して試み、video/mp4 のレスポンス本文を取得します。

  1. VIDEO_DOWNLOAD_TIKTOK_CDP_ENDPOINT(設定されている場合)
  2. http://127.0.0.1:9225

ポートのルール(チーム規則):

  • TikTok のバッチタスクで VIDEO_DOWNLOAD_TIKTOK_CDP_ENDPOINT が明示的に設定されている場合は、これを唯一の接続先ポート(例:9225)として扱い、タスク層で別のポートに切り替えて再試行しないでください。
  • チームで現在標準としている TikTok のポートは http://127.0.0.1:9225 です。
  • TikTok タスクでは 9222 にフォールバックしません。他のプラットフォームのブラウザーに接続してしまうことを防ぐためです。
  • アカウントのホームページを一括処理する場合は、VIDEO_DOWNLOAD_TIKTOK_LIST_RECORD と VIDEO_DOWNLOAD_TIKTOK_AUTHOR_HANDLE を設定できます。9225 のブラウザーコンテキストを通じて Cookie を使い、検証済みリストレコード内の playAddr にリクエストしますが、作品の詳細ページには移動しません。VIDEO_DOWNLOAD_TIKTOK_LIST_ONLY=1 を設定すると、直接リンクに失敗した場合は再試行に回し、作品の詳細ページには移動しません。

CDP による取得に失敗すると、自動的に tikwm による解析を試みます。それでも失敗した場合は、環境変数の設定に応じて yt-dlp にフォールバックします。

失敗時の再試行戦略(組み込み済み):

  • 1 回目:CDP -> tikwm
  • 2 回目(別の方法で 1 回再試行):tikwm -> CDP
  • それでも失敗した場合:VIDEO_DOWNLOAD_TIKTOK_ALLOW_YTDLP_FALLBACK=1 の設定に応じて yt-dlp にフォールバック

環境変数でポートを指定できます。

VIDEO_DOWNLOAD_TIKTOK_CDP_ENDPOINT=http://127.0.0.1:9225 \
python3 ./scripts/download.py "<tiktok链接>" "output.mp4"

任意の環境変数:

  • VIDEO_DOWNLOAD_TIKTOK_DISABLE_TIKWM=1:tikwm によるフォールバックを無効にします
  • VIDEO_DOWNLOAD_TIKTOK_ALLOW_YTDLP_FALLBACK=1:最終的に yt-dlp へフォールバックすることを許可します

TikTok 取得メタデータの出力

TikTok のダウンロードが成功するたびに、動画と同じ場所にメタデータファイルが生成されます。

  • <動画ファイルパス>.meta.json

主なフィールド:

  • source:cdp / tikwm / ytdlp
  • target_video_id
  • resolved_video_id
  • expected_duration
  • actual_duration
  • validation.id_ok
  • validation.duration_ok
  • validation.video_track_ok

バッチ処理での表への記録に便利なよう、端末にも概要が 1 行出力されます。

[TikTok/META] source=... id_ok=... duration_ok=... video_track_ok=...

ログイン管理

# 登录(打开可见浏览器)
python3 ./scripts/download.py login bilibili

# 带信号文件的登录(Agent 交互模式用)
python3 ./scripts/download.py login bilibili --signal-file /tmp/video_dl_login_done

# 检查登录状态
python3 ./scripts/download.py check-login bilibili

Cookie は ~/.config/video-download/<平台>_cookies.json に保存され、有効期限は自動的に検出されます。

対応プラットフォーム:bilibili / douyin / xiaohongshu

Douyin の既存 CDP 環境

既存の Douyin ブラウザー環境がある場合は、VIDEO_DOWNLOAD_DOUYIN_CDP_ENDPOINT=http://127.0.0.1:9222 を明示的に設定し、引き続き scripts/download.py をダウンロードのエントリーポイントとして使用します。作者が分かっている場合は、アカウントの sec_uid を VIDEO_DOWNLOAD_DOUYIN_AUTHOR_ID に設定します。エンドポイントは MD-Browser の既存設定に準拠してください。

このモードでは既存の環境にのみ接続し、今回のタスク用ページを開いて閉じます。Cookie はインポートせず、ヘッドレスブラウザーも起動しません。接続または作品の検証に失敗した場合は、他のダウンロード方法にフォールバックせず、直接エラーを返します。対象の aweme_id に対応する詳細ページからメディアアドレスを取得し、作者、動画トラック、長さを検証します。成功すると .mp4.meta.json を生成し、動画の一時 CDN アドレスや Cookie は保存しません。詳細ページのカバー画像アドレスは、呼び出し元がすぐにアーカイブできるように提供されます。

依存関係のインストール

pip3 install playwright && python3 -m playwright install chromium
brew install ffmpeg   # B站视频合并需要
brew install yt-dlp   # B站、抖音/小红书兜底及通用站点需要

トラブルシューティング

問題解決策
SSL 証明書エラースクリプトには ssl._create_unverified_context が組み込まれています
動画アドレスを取得できない待機時間を延ばすか、コンテンツにログインが必要、または画像とテキストのみで動画が含まれていない可能性があります
Douyin/小紅書で yt-dlp にフォールバックした後、fresh cookies と表示される対応するプラットフォームの login コマンドを実行して新しい Cookie を保存し、再試行してください
curl/ダウンロードで 403 が返されるReferer ヘッダーがプラットフォームのドメインと一致しているか確認してください
Bilibili で ffmpeg が見つからないbrew install ffmpeg
Bilibili で画質が低いlogin bilibili を実行してログインしてから、再ダウンロードしてください
CDN アドレスの期限切れ再実行してください。URL の有効期間は数時間です
Cookie の期限切れlogin コマンドを再実行してください
yt-dlp がインストールされていないbrew install yt-dlp または pip3 install yt-dlp
WeChat Channels でパーサーが設定されていないと表示されるWECHAT_CHANNELS_RESOLVER_URL を設定してください
WeChat Channels の解析に失敗する/ログインの期限が切れているパーサーのサーバー側で Yuanbao のログイン Cookie を更新してください。Cookie を Skill に渡さないでください
WeChat Channels から暗号化されたストリームが返されるパーサーから復号済みのプロキシ URL を返すようにしてください。Skill は制限対象プロジェクトの復号コードを複製しません

Douyin 素材ファクトリーのリスト優先ダウンロード

呼び出し元は VIDEO_DOWNLOAD_DOUYIN_LIST_RECORD に検証済みのホームページレコード JSON を設定し、マネージャーから返された既存の CDP エンドポイントと想定作者 ID を組み合わせて使用できます。リスト内の 720p 候補を優先してダウンロードし、失敗した場合は詳細ページにアクセスします。実際に選択された候補とすべての候補の概要は meta に記録されます。詳細ページから返された新しいフィールドは detail_updates を通じて呼び出し元に渡され、現在の値を上書きします。パラメーターがない場合は、作品リンクからのエントリーポイントが維持されます。画質の選択とアーカイブのルールについては、douyin-scraper の素材ファクトリーの全手順を参照してください。

コメント