Skill: feiskyer/feiskyer-download-video (version 1.0.1)

--- name: download-video description: Download videos from 1000+ websites (YouTube, Bilibili, Twitter/X, TikTok, Vimeo, Instagram, Twitch, etc.) using yt-dlp. Use this skill whenever a user shares a video URL, asks to save or download a video, wants to extract audio from an online video, needs a specific quality like 1080p or 4K, or mentions downloading a playlist. Also trigger on "下载视频", "保存视频", "提取音频", or any URL from a supported video platform. --- # Download Video Download videos from YouTube, Bilibili, Twitter/X, TikTok, and 1000+ other sites using yt-dlp. ## Step 1: Check prerequisites ```bash which yt-dlp && yt-dlp --version which ffmpeg ``` If yt-dlp is missing, install it: ```bash # macOS brew install yt-dlp ffmpeg # Cross-platform pip install yt-dlp ``` ## Step 2: Download Use the bundled script — it wraps yt-dlp with sensible defaults and clear error messages. ```bash python3 scripts/download.py "VIDEO_URL" ``` Default output: `~/Downloads/Videos/` ### Common options ```bash python3 scripts/download.py "URL" -f 1080 # Max 1080p python3 scripts/download.py "URL" -a # Audio only (MP3) python3 scripts/download.py "URL" -F # List formats python3 scripts/download.py "URL" --subs # With subtitles python3 scripts/download.py "URL" -o ~/Desktop # Custom output dir python3 scripts/download.py "URL" --cookies chrome # Use browser cookies ``` ### Direct yt-dlp commands For cases the script doesn't cover, use yt-dlp directly: ```bash # Download playlist yt-dlp -P ~/Downloads/Videos "PLAYLIST_URL" # Custom filename template yt-dlp -o "%(uploader)s - %(title)s.%(ext)s" "VIDEO_URL" # Download with subtitles in specific languages yt-dlp --write-subs --sub-lang zh,en -P ~/Downloads/Videos "VIDEO_URL" ``` ## Troubleshooting Most download failures fall into these categories: | Symptom | Fix | |---------|-----| | "Sign in required" or age-restricted | Add `--cookies chrome` to use browser session | | Only low quality available | Update yt-dlp (`brew upgrade yt-dlp`), then try with `--cookies chrome` | | Slow downloads | Try `--concurrent-fragments 3` or `--downloader aria2c` | | Network errors (behind firewall) | Use `--proxy socks5://127.0.0.1:1080` or set `ALL_PROXY` env var | For platform-specific details (YouTube PO tokens, Bilibili series, TikTok watermark removal, etc.), see [references/platform-tips.md](references/platform-tips.md).

path: references/platform-tips.md
content: # Platform-Specific Tips

## YouTube

### High-Quality Downloads (1080p+)

YouTube restricts high-quality formats for non-authenticated requests. Solutions:

#### Option 1: Browser Cookies (Recommended)

```bash
yt-dlp --cookies-from-browser chrome "VIDEO_URL"
```

Supported browsers: `chrome`, `firefox`, `safari`, `edge`, `opera`, `brave`

#### Option 2: PO Token Provider

For persistent high-quality access without browser dependency:

```bash
# Find yt-dlp's Python path
head -1 $(which yt-dlp)

# Install the plugin
/path/to/python -m pip install bgutil-ytdlp-pot-provider
```

### Age-Restricted Content

Requires authentication via cookies:

```bash
yt-dlp --cookies-from-browser chrome "VIDEO_URL"
```

## Bilibili

### Best Quality

```bash
# With authentication for high quality
yt-dlp --cookies-from-browser chrome "https://www.bilibili.com/video/BV..."

# Specify quality
yt-dlp -f "bestvideo+bestaudio" "https://www.bilibili.com/video/BV..."
```

### Download Entire Series

```bash
yt-dlp -P ~/Downloads/Videos "https://www.bilibili.com/video/BV..." --playlist-items 1-10
```

## Twitter/X

Usually works without authentication:

```bash
yt-dlp "https://twitter.com/user/status/123456789"
yt-dlp "https://x.com/user/status/123456789"
```

For protected tweets, use cookies:

```bash
yt-dlp --cookies-from-browser chrome "https://twitter.com/user/status/123456789"
```

## TikTok

```bash
# Download single video
yt-dlp "https://www.tiktok.com/@user/video/123456789"

# Without watermark (if available)
yt-dlp -f "download_addr-0" "https://www.tiktok.com/@user/video/123456789"
```

## Instagram

Requires authentication for most content:

```bash
yt-dlp --cookies-from-browser chrome "https://www.instagram.com/p/ABC123/"
yt-dlp --cookies-from-browser chrome "https://www.instagram.com/reel/ABC123/"
```

## Twitch

### VODs

```bash
yt-dlp "https://www.twitch.tv/videos/123456789"
```

### Clips

```bash
yt-dlp "https://clips.twitch.tv/ClipName"
```

## Vimeo

```bash
# Public videos
yt-dlp "https://vimeo.com/123456789"

# Password-protected
yt-dlp --video-password "PASSWORD" "https://vimeo.com/123456789"
```

## Common Issues

### "Sign in to confirm your age"

```bash
yt-dlp --cookies-from-browser chrome "VIDEO_URL"
```

### "Video is unavailable"

1. Check if video exists in browser
2. Try with cookies
3. Check if region-restricted (use VPN/proxy)

### Slow Downloads

```bash
# Limit concurrent downloads
yt-dlp --concurrent-fragments 3 "VIDEO_URL"

# Use external downloader
yt-dlp --downloader aria2c "VIDEO_URL"
```

### Network Issues (China)

```bash
# Use proxy
yt-dlp --proxy socks5://127.0.0.1:1080 "VIDEO_URL"

# Or environment variable
export ALL_PROXY=socks5://127.0.0.1:1080
```

## Useful Options Reference

| Option | Description |
|--------|-------------|
| `-F` | List all formats |
| `-f FORMAT` | Select format |
| `-P DIR` | Output directory |
| `-o TEMPLATE` | Output filename template |
| `-x` | Extract audio |
| `--audio-format mp3` | Convert to MP3 |
| `--write-subs` | Download subtitles |
| `--sub-lang LANGS` | Subtitle languages |
| `--cookies-from-browser BROWSER` | Use browser cookies |
| `--proxy URL` | Use proxy |
| `--limit-rate RATE` | Limit download speed |


path: scripts/download.py
content: #!/usr/bin/env python3
"""
Universal video downloader using yt-dlp.

Supports 1000+ websites including YouTube, Bilibili, Twitter/X, TikTok, and more.
Default output directory: ~/Downloads/Videos/

Requirements:
    - yt-dlp: Install via `brew install yt-dlp` (macOS) or `pip install yt-dlp`

Usage:
    python3 download.py "VIDEO_URL"
    python3 download.py "VIDEO_URL" -o ~/Desktop
    python3 download.py "VIDEO_URL" -f 1080
    python3 download.py "VIDEO_URL" -a
    python3 download.py "VIDEO_URL" -F
"""

import argparse
import subprocess
import sys
from pathlib import Path


DEFAULT_OUTPUT_DIR = "~/Downloads/Videos"


def check_yt_dlp() -> bool:
    """Check if yt-dlp is installed."""
    result = subprocess.run(
        ["which", "yt-dlp"], capture_output=True, text=True
    )
    return result.returncode == 0


def get_yt_dlp_version() -> str:
    """Get yt-dlp version."""
    result = subprocess.run(
        ["yt-dlp", "--version"], capture_output=True, text=True
    )
    return result.stdout.strip() if result.returncode == 0 else "unknown"


def download(
    url: str,
    output_dir: str = DEFAULT_OUTPUT_DIR,
    max_height: int = None,
    audio_only: bool = False,
    list_formats: bool = False,
    with_subs: bool = False,
    use_cookies: str = None,
) -> int:
    """
    Download video from URL using yt-dlp.

    Args:
        url: Video URL
        output_dir: Output directory
        max_height: Maximum video height (e.g., 1080, 720)
        audio_only: Extract audio only (as MP3)
        list_formats: List available formats instead of downloading
        with_subs: Download subtitles
        use_cookies: Browser to extract cookies from (chrome, firefox, etc.)

    Returns:
        Exit code (0 for success)
    """
    if not check_yt_dlp():
        print("Error: yt-dlp is not installed")
        print("Install via: brew install yt-dlp  # or: pip install yt-dlp")
        return 1

    print(f"yt-dlp version: {get_yt_dlp_version()}")

    cmd = ["yt-dlp"]

    # List formats only
    if list_formats:
        cmd.extend(["-F", url])
        return subprocess.run(cmd).returncode

    # Output directory
    output_path = Path(output_dir).expanduser().resolve()
    output_path.mkdir(parents=True, exist_ok=True)
    cmd.extend(["-P", str(output_path)])

    # Browser cookies for authentication
    if use_cookies:
        cmd.extend(["--cookies-from-browser", use_cookies])

    # Audio only
    if audio_only:
        cmd.extend(["-x", "--audio-format", "mp3"])
    elif max_height:
        cmd.extend(["-f", f"bestvideo[height<={max_height}]+bestaudio/best"])
    else:
        cmd.extend(["-f", "bestvideo+bestaudio/best"])

    # Subtitles
    if with_subs:
        cmd.extend(["--write-subs", "--sub-lang", "zh,en,ja"])

    # Progress display
    cmd.append("--progress")

    # Add URL
    cmd.append(url)

    print(f"\nCommand: {' '.join(cmd)}\n")
    result = subprocess.run(cmd)

    if result.returncode == 0:
        print(f"\nDownload completed!")
        print(f"Location: {output_path}")
    else:
        print(f"\nDownload failed (exit code: {result.returncode})")
        print("\nTroubleshooting tips:")
        print("  1. Update yt-dlp: brew upgrade yt-dlp")
        print("  2. Try with cookies: python3 download.py URL --cookies chrome")
        print("  3. Check formats: python3 download.py URL -F")

    return result.returncode


def main():
    parser = argparse.ArgumentParser(
        description="Download videos from 1000+ websites using yt-dlp",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s "https://youtu.be/VIDEO_ID"
  %(prog)s "https://www.bilibili.com/video/BV..." --cookies chrome
  %(prog)s "https://twitter.com/user/status/123" -f 720
  %(prog)s "VIDEO_URL" -a                        # Audio only
  %(prog)s "VIDEO_URL" -F                        # List formats
        """,
    )
    parser.add_argument("url", help="Video URL to download")
    parser.add_argument(
        "-o", "--output",
        default=DEFAULT_OUTPUT_DIR,
        help=f"Output directory (default: {DEFAULT_OUTPUT_DIR})",
    )
    parser.add_argument(
        "-f", "--format",
        type=int,
        metavar="HEIGHT",
        help="Max video height (e.g., 1080, 720, 480)",
    )
    parser.add_argument(
        "-a", "--audio",
        action="store_true",
        help="Download audio only (as MP3)",
    )
    parser.add_argument(
        "-F", "--list-formats",
        action="store_true",
        help="List available formats",
    )
    parser.add_argument(
        "--subs",
        action="store_true",
        help="Download subtitles (zh, en, ja)",
    )
    parser.add_argument(
        "--cookies",
        metavar="BROWSER",
        help="Browser to extract cookies from (chrome, firefox, safari, edge)",
    )

    args = parser.parse_args()

    exit_code = download(
        url=args.url,
        output_dir=args.output,
        max_height=args.format,
        audio_only=args.audio,
        list_formats=args.list_formats,
        with_subs=args.subs,
        use_cookies=args.cookies,
    )

    sys.exit(exit_code)


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)