初始发布: 21 个 skills (Claude Code / Codex / DSH)

This commit is contained in:
2026-08-14 01:51:44 +08:00
commit ea0857bedb
129 changed files with 35566 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
# youtube-download — 便携技能包
把 YouTube 视频下成本地最高画质 MP4(最高 4K,内含最佳音质 Opus 音轨)。默认规格:只下视频版,不单独下音频;除非用户明确要求音频版。已处理好现代 yt-dlp 下 YouTube 的两个坑:JS 运行时 + 机器人检测 cookie。
## 目录
```
youtube-download/
├─ SKILL.md # 技能说明(给 AI agent 读的:何时用、怎么用、坑)
├─ README.md # 本文件
└─ scripts/
├─ yt-download.ps1 # Windows 一键脚本(自动装 yt-dlp/deno
└─ yt-download.sh # Linux/macOS 一键脚本
```
## 快速开始
**Windows**
```powershell
powershell -ExecutionPolicy Bypass -File scripts\yt-download.ps1 "https://www.youtube.com/watch?v=VIDEO_ID"
```
首次运行会自动把 `yt-dlp.exe``deno.exe` 下到 `scripts\bin\`。还需要系统装了 `ffmpeg``winget install Gyan.FFmpeg`)。
**Linux/macOS**
```bash
bash scripts/yt-download.sh "https://www.youtube.com/watch?v=VIDEO_ID"
```
需先装 `yt-dlp``ffmpeg`、以及 JS 运行时 `bun` / `deno` / `node` 任一(命令见 SKILL.md 顶部;脚本默认优先用 bun)。
## 登录/受限视频要 cookie
公开视频不用管。如果报 `Sign in to confirm you're not a bot`
1. 浏览器(已登录 YouTube)装扩展 **Get cookies.txt LOCALLY**
2. 打开着 youtube.com 标签页,点扩展 → Export,得到 Netscape 格式 cookie 文件。
3. 改名为 `cookies.txt` 放进 `scripts/` 目录(脚本会自动带上)。
4. 报“cookies no longer valid”时重新导出覆盖即可。
⚠️ cookie 是你的登录凭证,别外发、别提交到 git。本包**不含** cookie。
## 在 Codex / 其他 agent 里用
CodexOpenAI CLI)没有 Claude 那种正式 skill 装载机制,但这个包是纯文档 + 脚本,任何 agent 都能用:
- 把整个 `youtube-download/` 文件夹放进项目,或放到 Codex 能读到的位置。
- 在项目根的 `AGENTS.md` 里加一句指路,例如:
> 需要下载 YouTube 视频时,读 `youtube-download/SKILL.md` 并运行其中的脚本。
- 或直接让 Codex “按 youtube-download/SKILL.md 的方法下这个链接”。
如果目标是 **Claude Code / Claude Agent**:把 `youtube-download/` 整个放进 `~/.claude/skills/`(或项目的 `.claude/skills/`)即可作为技能被自动发现(靠 SKILL.md 的 frontmatter)。
+87
View File
@@ -0,0 +1,87 @@
---
name: youtube-download
description: "Download YouTube videos at the highest available quality (up to 4K) as merged MP4 files with the best audio track (native Opus). Default spec: best video + best audio merged into one MP4 only — do not download a separate audio-only file unless the user explicitly asks for 音频/audio-only. Handles the modern yt-dlp requirements — a JS runtime (bun/deno/node) for YouTube's JS challenges, and browser cookies for videos blocked by bot detection / login / age gates. Use when asked to download, save, or grab a YouTube video, playlist item, or a high-quality/HD/4K copy of a YouTube URL."
---
# YouTube 高清下载 (youtube-download)
`yt-dlp` 把 YouTube 视频下成本地最高画质 MP4(最高 4K),也可以只下最高音质音频。已经踩平了 2025/2026 年 yt-dlp 下 YouTube 的两个主要坑:需要 JS 运行时、以及机器人检测要 cookie。
## 什么时候用
用户给一个或多个 YouTube 链接,要求“下载 / 保存 / 下高清 / 下 4K / 下最高画质”时。
## 默认规格(每次照此执行)
- 默认只下「视频版」:最高画质视频(最高 4K)+ 最佳音质音轨(原生 Opus),合并成单个 MP4,存到用户「下载」文件夹。
- 除非用户明确说「只要音频 / 音频版 / 单独下音频」,否则**不要**额外下载 audio-only 文件。
- 链接带 `&list=` / `start_radio=1` 时默认只下当前这一个视频(`--no-playlist`),除非用户要求整个播放列表/电台。
## 核心命令(能跑通的那条)
```
yt-dlp \
--cookies "cookies.txt" \ # 仅当视频需要登录/被机器人拦时必需,见下
--js-runtimes "bun:$(command -v bun)" \ # 必需:YouTube 现在要求解 JS 挑战(bun/deno/node 任选)
-f "bestvideo+bestaudio/best" \
--merge-output-format mp4 \
--ffmpeg-location "<ffmpeg bin 目录>" \ # 合并视频+音频需要 ffmpeg
-o "<输出目录>/%(title)s [%(height)sp].%(ext)s" \
--no-playlist \ # 链接带 &list= 时只下当前这一个
"https://www.youtube.com/watch?v=VIDEO_ID"
```
**推荐直接用打包好的脚本**(自动准备工具、找 ffmpeg、带 cookie):
- Windows`scripts/yt-download.ps1`
- Linux/macOS`scripts/yt-download.sh`
```powershell
# Windows 示例:下一个或多个视频到「下载」文件夹
powershell -ExecutionPolicy Bypass -File scripts\yt-download.ps1 "https://www.youtube.com/watch?v=xxxx"
powershell -ExecutionPolicy Bypass -File scripts\yt-download.ps1 URL1 URL2 URL3
```
```bash
# Linux/macOS 示例
bash scripts/yt-download.sh "https://www.youtube.com/watch?v=xxxx"
```
脚本行为:
- 默认就是最高画质视频 + 最佳音质音轨合并 MP4;不会单独下载音频。
- JS 运行时自动选 `bun`(已装);没有则用 `deno`,再退到 `node`。也可用环境变量 `JS_RUNTIME=bun|deno|node` 指定。
- 找不到 `yt-dlp`Windows 版还会找 `deno`)会自动下载到脚本旁的 `bin/` 目录。
- 自动探测 `ffmpeg`PATH 里没有会提示安装)。
- 如果脚本目录里存在 `cookies.txt`,会自动带上。
- 输出文件名格式:`标题 [1080p].mp4`,默认存到当前用户「下载」文件夹(可用 `-OutDir` / `$2` 改)。
## 三个关键坑(务必知道)
1. **必须有 JS 运行时。** 否则报 `No supported JavaScript runtime could be found` 或直接 `Sign in to confirm you're not a bot`。装 `bun` / `deno` / `node` 任一即可(macOS 上已装 bun,脚本默认用 bun),或给 yt-dlp 传 `--js-runtimes "bun:路径"`
- ⚠️ yt-dlp 已把 bun 标记为 deprecated,只支持 bun 1.2.111.3.14(本机 1.3.13 可用)。若以后升级 bun 或 yt-dlp 报 bun 不支持,用 `JS_RUNTIME=deno` / `JS_RUNTIME=node` 切换即可(deno 已随 brew 版 yt-dlp 装好)。
2. **机器人检测 → 需要 cookie。** 如果 API 返回 `LOGIN_REQUIRED` / “Sign in to confirm you're not a bot” 且 0 个格式,就必须提供你 YouTube 账号的 cookie
- 浏览器(登录着 YouTube)装扩展 **“Get cookies.txt LOCALLY”**(开源、纯本地不上传)。
- **切到 youtube.com 标签页**(当前激活),点扩展图标 → Export,导出 Netscape 格式的 `www.youtube.com_cookies.txt`
- 把它改名/放成脚本目录下的 `cookies.txt`(或用 `--cookies` 指定路径)。
- **公开视频不需要 cookie**,脚本没检测到 cookie 也能下公开视频。
3. **cookie 会过期/轮换。** 出现 `The provided YouTube account cookies are no longer valid` 时,按第 2 步重新导出覆盖 `cookies.txt` 即可。公开视频不受影响。
## 输出编码说明
YouTube 最高画质通常是 **AV1 视频 + Opus 音频**(封装成 mp4)。较新,VLC / PotPlayer / 新版系统播放器都能放;个别老设备放不了。需要更通用时:
- 想要 H.264(兼容性最好,但 YouTube 上 H.264 最高只到 1080p):把格式改成
`-f "bestvideo[vcodec^=avc1]+bestaudio[ext=m4a]/best[vcodec^=avc1]"`
- 或下完后用 ffmpeg 转码成 H.264/H.265。
## 小抄
- 仅当用户明确要求音频时才用:
- 只下音频(m4a):`-f "bestaudio[ext=m4a]/bestaudio" -x --audio-format m4a`
- 只下最高音质音频(保留 YouTube 原生 Opus,不转码、音质最好):`-f "bestaudio/best" -o "%(title)s.%(ext)s"`
- 限制最高 1080p`-f "bestvideo[height<=1080]+bestaudio/best[height<=1080]"`
- 整个播放列表:去掉 `--no-playlist`
- 看有哪些格式:`-F`
- 下字幕:`--write-subs --sub-langs "en,zh-Hans" --convert-subs srt`
+109
View File
@@ -0,0 +1,109 @@
<#
.SYNOPSIS
Download YouTube video(s) at highest quality as merged MP4.
.DESCRIPTION
Wraps yt-dlp with the settings needed for modern YouTube:
- JS runtime (bun preferred; deno auto-downloaded to .\bin if missing)
- yt-dlp (auto-downloaded to .\bin if missing)
- ffmpeg (must be on PATH, or set -FfmpegDir)
- cookies.txt next to this script is used automatically if present
.EXAMPLE
.\yt-download.ps1 "https://www.youtube.com/watch?v=xxxx"
.EXAMPLE
.\yt-download.ps1 URL1 URL2 URL3 -OutDir "D:\Videos"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true)]
[string[]] $Urls,
[string] $OutDir = (Join-Path $env:USERPROFILE 'Downloads'),
# Override format selection if you want (e.g. H.264 only, or <=1080p)
[string] $Format = 'bestvideo+bestaudio/best',
# Path to ffmpeg's bin dir. Auto-detected from PATH if omitted.
[string] $FfmpegDir = '',
# Path to a Netscape cookies.txt. Defaults to cookies.txt beside this script.
[string] $Cookies = ''
)
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$BinDir = Join-Path $ScriptDir 'bin'
New-Item -ItemType Directory -Force $BinDir | Out-Null
function Get-Tool($name, $url, $outFile) {
$local = Join-Path $BinDir $outFile
if (Test-Path $local) { return $local }
$onPath = (Get-Command $name -ErrorAction SilentlyContinue)
if ($onPath) { return $onPath.Source }
Write-Host "[setup] downloading $name ..." -ForegroundColor Cyan
Invoke-WebRequest -Uri $url -OutFile $local
return $local
}
# --- yt-dlp ---
$ytdlp = Get-Tool 'yt-dlp' 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe' 'yt-dlp.exe'
# --- JS runtime (bun preferred; deno fallback; required by YouTube) ---
$jsRuntime = ''
$bun = Get-Command 'bun' -ErrorAction SilentlyContinue
if ($bun) {
$jsRuntime = "bun:$($bun.Source)"
} else {
$deno = Join-Path $BinDir 'deno.exe'
if (-not (Test-Path $deno)) {
$onPath = Get-Command 'deno' -ErrorAction SilentlyContinue
if ($onPath) {
$deno = $onPath.Source
} else {
Write-Host "[setup] downloading deno ..." -ForegroundColor Cyan
$zip = Join-Path $BinDir 'deno.zip'
Invoke-WebRequest -Uri 'https://github.com/denoland/deno/releases/latest/download/deno-x86_64-pc-windows-msvc.zip' -OutFile $zip
Expand-Archive $zip -DestinationPath $BinDir -Force
Remove-Item $zip -Force
}
}
$jsRuntime = "deno:$deno"
}
# --- ffmpeg ---
if (-not $FfmpegDir) {
$ff = Get-Command 'ffmpeg' -ErrorAction SilentlyContinue
if ($ff) {
$FfmpegDir = Split-Path -Parent $ff.Source
} else {
Write-Warning "ffmpeg not found on PATH. Install it (winget install Gyan.FFmpeg) or pass -FfmpegDir. Merging video+audio will fail without it."
}
}
# --- cookies ---
if (-not $Cookies) {
$defaultCookies = Join-Path $ScriptDir 'cookies.txt'
if (Test-Path $defaultCookies) { $Cookies = $defaultCookies }
}
New-Item -ItemType Directory -Force $OutDir | Out-Null
$common = @(
'--no-js-runtimes',
'--js-runtimes', $jsRuntime,
'-f', $Format,
'--merge-output-format', 'mp4',
'-o', (Join-Path $OutDir '%(title)s [%(height)sp].%(ext)s'),
'--no-playlist'
)
if ($FfmpegDir) { $common += @('--ffmpeg-location', $FfmpegDir) }
if ($Cookies) { $common += @('--cookies', $Cookies); Write-Host "[info] using cookies: $Cookies" -ForegroundColor DarkGray }
else { Write-Host "[info] no cookies.txt -- public videos only. See SKILL.md if you hit 'Sign in to confirm you're not a bot'." -ForegroundColor DarkGray }
$fail = 0
foreach ($u in $Urls) {
Write-Host "`n==== downloading: $u ====" -ForegroundColor Green
& $ytdlp @common $u
if ($LASTEXITCODE -ne 0) { $fail++; Write-Warning "failed: $u" }
}
if ($fail) { Write-Warning "$fail download(s) failed."; exit 1 }
Write-Host "`nAll done. Saved to: $OutDir" -ForegroundColor Green
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
# Download YouTube video(s) at highest quality as merged MP4 (Linux/macOS).
#
# ./yt-download.sh "https://www.youtube.com/watch?v=xxxx"
# ./yt-download.sh URL1 URL2 URL3
#
# Env overrides:
# OUTDIR=/path/to/dir output directory (default: ~/Downloads)
# FORMAT="..." yt-dlp -f selector (default: bestvideo+bestaudio/best)
# COOKIES=/path/cookies.txt Netscape cookies file (default: cookies.txt beside this script)
#
# Requirements: yt-dlp, ffmpeg, and a JS runtime (bun/deno/node) must be installed.
# pipx install yt-dlp (or: brew install yt-dlp / apt install yt-dlp)
# brew install ffmpeg (or: apt install ffmpeg)
# bun / deno / node any one (needed for YouTube JS challenges)
set -euo pipefail
if [ "$#" -lt 1 ]; then
echo "usage: $0 <youtube-url> [more urls...]" >&2
exit 2
fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTDIR="${OUTDIR:-$HOME/Downloads}"
FORMAT="${FORMAT:-bestvideo+bestaudio/best}"
# yt-dlp
if ! command -v yt-dlp >/dev/null 2>&1; then
echo "error: yt-dlp not found. Install it: pipx install yt-dlp" >&2
exit 1
fi
# ffmpeg
if ! command -v ffmpeg >/dev/null 2>&1; then
echo "warning: ffmpeg not found; merging video+audio will fail. Install ffmpeg." >&2
fi
# JS runtime for YouTube JS challenges. Prefer bun, fall back to deno/node.
# Override with JS_RUNTIME=bun|deno|node (must be on PATH).
# --no-js-runtimes ensures ONLY the chosen runtime is used (bun won't be
# silently shadowed by yt-dlp's built-in deno preference).
JS_ARGS=()
JS_RUNTIME_NAME=
JS_RUNTIME_BIN=
if [ -n "${JS_RUNTIME:-}" ] && command -v "$JS_RUNTIME" >/dev/null 2>&1; then
JS_RUNTIME_NAME="$JS_RUNTIME"
JS_RUNTIME_BIN="$(command -v "$JS_RUNTIME")"
elif command -v bun >/dev/null 2>&1; then
JS_RUNTIME_NAME="bun"
JS_RUNTIME_BIN="$(command -v bun)"
elif command -v deno >/dev/null 2>&1; then
JS_RUNTIME_NAME="deno"
JS_RUNTIME_BIN="$(command -v deno)"
elif [ -x "$HOME/.deno/bin/deno" ]; then
JS_RUNTIME_NAME="deno"
JS_RUNTIME_BIN="$HOME/.deno/bin/deno"
elif command -v node >/dev/null 2>&1; then
JS_RUNTIME_NAME="node"
JS_RUNTIME_BIN="$(command -v node)"
fi
if [ -n "$JS_RUNTIME_NAME" ]; then
JS_ARGS=(--no-js-runtimes --js-runtimes "$JS_RUNTIME_NAME:$JS_RUNTIME_BIN")
else
echo "warning: no JS runtime (bun/deno/node) found. YouTube may reject the download ('confirm you're not a bot')." >&2
fi
# cookies
COOKIES="${COOKIES:-$SCRIPT_DIR/cookies.txt}"
COOKIE_ARGS=()
if [ -f "$COOKIES" ]; then
COOKIE_ARGS=(--cookies "$COOKIES")
echo "[info] using cookies: $COOKIES"
else
echo "[info] no cookies.txt -- public videos only. See SKILL.md for login-required videos."
fi
mkdir -p "$OUTDIR"
fail=0
for url in "$@"; do
echo ""
echo "==== downloading: $url ===="
if ! yt-dlp "${JS_ARGS[@]}" "${COOKIE_ARGS[@]}" \
-f "$FORMAT" \
--merge-output-format mp4 \
-o "$OUTDIR/%(title)s [%(height)sp].%(ext)s" \
--no-playlist \
"$url"; then
fail=$((fail+1))
echo "warning: failed: $url" >&2
fi
done
if [ "$fail" -gt 0 ]; then
echo "warning: $fail download(s) failed." >&2
exit 1
fi
echo ""
echo "All done. Saved to: $OUTDIR"