Skill: benangel65/bilibili-downloader (version 1.0.0)

--- name: bilibili-downloader description: Download videos, audio, subtitles, and covers from Bilibili using bilibili-api. Use when working with Bilibili content for downloading videos in various qualities, extracting audio, getting subtitles and danmaku, downloading covers, and managing download preferences. --- # Bilibili Downloader ## Quick Start Download a video by URL: ```bash pip install bilibili-api-python python -c " from bilibili_api import video, sync v = video.Video(bvid='BV1xx411c7m2') sync(v.download(output='./video.mp4')) " ``` ## Download Options ### Video Quality - Specify quality with `qn` parameter (127=8K, 126=杜比, 125=1080P+, etc.) - Default selects best available quality ### Audio Download - Download original soundtrack: `v.download_audious(output='./audio.mp3')` - Supports various audio formats ### Subtitles - Get available subtitles: `v.get_subtitle()` - Download subtitle files: `sync(v.download_subtitle(output='./'))` ### Covers and Thumbnails - Get cover URL: `v.get_cover()` - Download cover: `sync(v.download_cover(output='./cover.jpg'))` ## Common Tasks ### Download Single Video ```python from bilibili_api import video, sync v = video.Video(bvid='BV1xx411c7m2') sync(v.download(output='./video.mp4')) ``` ### Download with Specific Quality ```python from bilibili_api import video, sync v = video.Video(bvid='BV1xx411c7m2') info = v.get_download_url(qn=127) # 8K quality ``` ### Download Entire Playlist ```python from bilibili_api import video, sync from bilibili_api import playlist pl = playlist.Playlist(playlist_id='123456') for v in sync(pl.get_videos()): sync(v.download(output=f'./playlist/{v["title"]}.mp4')) ``` ### Download Audio Only ```python from bilibili_api import video, sync v = video.Video(bvid='BV1xx411c7m2') sync(v.download_audio(output='./audio.mp3')) ``` ## Authentication For premium content, use browser cookies: 1. Login to Bilibili in browser 2. Export SESSDATA cookie value 3. Set environment variable: `export BILIBILI_SESSDATA='your_cookie_value'` ## Requirements - bilibili-api-python: `pip install bilibili-api-python` - ffmpeg: Required for video/audio processing - Python 3.8+ ## Resources ### scripts/ Utility scripts for common download operations. ### references/ - API documentation from bilibili-api repo - Quality codes reference (qn values) - Cookie setup guide ### assets/ Download templates and configuration examples.

path: assets/config_template.json
content: {
  "example_config": {
    "description": "Download configuration file for bilibili-downloader scripts",
    "settings": {
      "quality": 125,
      "output_dir": "./downloads",
      "audio_only": false,
      "include_subtitles": true,
      "include_cover": true
    }
  },
  "usage": "Edit the config.json file and run download_with_config.py"
}


path: references/quick_guide.md
content: # Bilibili API 参考指南

## 安装
```bash
pip install bilibili-api-python
```

## 质量代码 (qn参数)
| 代码 | 清晰度 |
|------|--------|
| 127 | 8K |
| 126 | 杜比视界 |
| 125 | 1080P+ |
| 120 | 1080P60 |
| 116 | 4K |
| 112 | 1080P |
| 80 | 1080P |
| 74 | 720P |
| 64 | 480P |
| 32 | 360P |

## 常用操作

### 获取视频信息
```python
from bilibili_api import video, sync
v = video.Video(bvid='BV1xx411c7m2')
info = sync(v.get_info())
```

### 下载视频
```python
sync(v.download(output='./video.mp4'))
```

### 获取下载链接
```python
url_info = v.get_download_url(qn=125)  # 1080P+
```

### 获取字幕列表
```python
subtitles = sync(v.get_subtitle())
```

### 下载字幕
```python
sub_info = sync(v.get_subtitle(subtitle_id))
```

### 获取封面
```python
cover_url = v.get_cover()
```

## Cookie 设置
需要登录的操作需要设置 SESSDATA:
```bash
export BILIBILI_SESSDATA='your_cookie_value'
```

或在代码中:
```python
import os
os.environ['BILIBILI_SESSDATA'] = 'your_cookie_value'
```

## 错误处理
- 403: Cookie无效或过期
- -404: 视频不存在
- -403: 需要登录


path: scripts/download_audio.py
content: #!/usr/bin/env python3
"""
Bilibili Audio Downloader Script
Usage: python download_audio.py <bvid_or_url> [output_path]
"""

import os
import sys
from bilibili_api import video, sync


def download_audio(bvid, output_path="./"):
    """Download audio from a Bilibili video."""
    v = video.Video(bvid=bvid)
    os.makedirs(output_path, exist_ok=True)

    info = v.get_info()
    filename = f"{info['title'][:50]}_audio.mp3".replace("/", "_")
    output_file = os.path.join(output_path, filename)

    sync(v.download_audio(output=output_file))
    print(f"Downloaded audio: {output_file}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python download_audio.py <bvid> [output_path]")
        sys.exit(1)

    bvid = sys.argv[1]
    output = sys.argv[2] if len(sys.argv) > 2 else "./"

    download_audio(bvid, output)


path: scripts/download_config.json
content: {
  "default_quality": 125,
  "output_directory": "./downloads",
  "audio_only": false,
  "download_subtitles": true,
  "download_cover": true,
  "cookies": {
    "SESSDATA": "your_sessdata_here"
  },
  "quality_codes": {
    "127": "8K",
    "126": "杜比视界",
    "125": "1080P+",
    "120": "1080P60",
    "116": "4K",
    "112": "1080P",
    "80": "1080P",
    "74": "720P",
    "64": "480P",
    "32": "360P"
  }
}


path: scripts/download_playlist.py
content: #!/usr/bin/env python3
"""
Bilibili Playlist/Series Downloader Script
Usage: python download_playlist.py <playlist_id> [output_path] [quality]
"""

import os
import sys
from bilibili_api import playlist, sync


def download_playlist(playlist_id, output_path="./", quality=None):
    """Download all videos from a playlist."""
    os.makedirs(output_path, exist_ok=True)

    pl = playlist.Playlist(playlist_id=int(playlist_id))
    videos = sync(pl.get_videos())

    print(f"Found {len(videos)} videos in playlist")

    for i, v in enumerate(videos, 1):
        try:
            video_obj = video.Video(bvid=v["bvid"])
            info = video_obj.get_info()
            title = info["title"][:50].replace("/", "_")

            filename = f"{i:03d}_{title}.mp4"
            output_file = os.path.join(output_path, filename)

            if quality:
                url_info = video_obj.get_download_url(qn=int(quality))
                sync(video_obj.download(output=output_file, url=url_info))
            else:
                sync(video_obj.download(output=output_file))

            print(f"[{i}/{len(videos)}] Downloaded: {title}")
        except Exception as e:
            print(f"[{i}/{len(videos)}] Failed: {v['bvid']} - {e}")

    print(f"\nCompleted: {output_path}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(
            "Usage: python download_playlist.py <playlist_id> [output_path] [quality]"
        )
        sys.exit(1)

    playlist_id = sys.argv[1]
    output = sys.argv[2] if len(sys.argv) > 2 else "./playlist"
    quality = sys.argv[3] if len(sys.argv) > 3 else None

    download_playlist(playlist_id, output, quality)


path: scripts/download_subtitles.py
content: #!/usr/bin/env python3
"""
Bilibili Subtitle Downloader Script
Usage: python download_subtitles.py <bvid_or_url> [output_path]
"""

import os
import sys
import json
from bilibili_api import video, sync


def download_subtitles(bvid, output_path="./"):
    """Download subtitles from a Bilibili video."""
    v = video.Video(bvid=bvid)
    os.makedirs(output_path, exist_ok=True)

    subtitles = sync(v.get_subtitle())

    if not subtitles:
        print("No subtitles available for this video")
        return

    for sub in subtitles:
        lang = sub["lan"]
        sub_info = sync(v.get_subtitle(sub["id"]))

        filename = f"{v.get_info()['title'][:30]}_{lang}.json".replace("/", "_")
        output_file = os.path.join(output_path, filename)

        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(sub_info, f, ensure_ascii=False, indent=2)

        print(f"Downloaded subtitle: {output_file} ({lang})")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python download_subtitles.py <bvid> [output_path]")
        sys.exit(1)

    bvid = sys.argv[1]
    output = sys.argv[2] if len(sys.argv) > 2 else "./"

    download_subtitles(bvid, output)


path: scripts/download_video.py
content: #!/usr/bin/env python3
"""
Bilibili Video Downloader Script
Usage: python download_video.py <bvid_or_url> [output_path] [quality]
Quality: 127=8K, 126=杜比, 125=1080P+, 120=1080P, 116=4K, 112=1080P, 80=1080P, 74=720P, 64=480P, 32=360P
"""

import os
import sys
from bilibili_api import video, sync


def download_video(bvid, output_path="./", quality=None):
    """Download a single Bilibili video."""
    v = video.Video(bvid=bvid)
    os.makedirs(output_path, exist_ok=True)

    filename = f"{v.get_info()['title'][:50]}.mp4".replace("/", "_")
    output_file = os.path.join(output_path, filename)

    if quality:
        url_info = v.get_download_url(qn=int(quality))
        sync(v.download(output=output_file, url=url_info))
    else:
        sync(v.download(output=output_file))

    print(f"Downloaded: {output_file}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(__doc__)
        sys.exit(1)

    bvid = sys.argv[1]
    output = sys.argv[2] if len(sys.argv) > 2 else "./"
    quality = sys.argv[3] if len(sys.argv) > 3 else None

    download_video(bvid, output, quality)


path: scripts/download_with_config.py
content: #!/usr/bin/env python3
"""
Bilibili Downloader with Config
Usage: python download_with_config.py <bvid> [config_file]
"""

import os
import sys
import json
from bilibili_api import video, sync


def load_config(config_file="config.json"):
    """Load configuration from JSON file."""
    if os.path.exists(config_file):
        with open(config_file, "r") as f:
            return json.load(f)
    return {}


def download_with_config(bvid, config=None):
    """Download video with configuration."""
    config = config or {}
    v = video.Video(bvid=bvid)

    info = v.get_info()
    title = info["title"][:50].replace("/", "_")

    output_dir = config.get("output_directory", "./downloads")
    os.makedirs(output_dir, exist_ok=True)

    output_file = os.path.join(output_dir, f"{title}.mp4")

    quality = config.get("default_quality")
    if quality:
        url_info = v.get_download_url(qn=quality)
        sync(v.download(output=output_file, url=url_info))
    else:
        sync(v.download(output=output_file))

    print(f"Downloaded: {output_file}")

    if config.get("download_cover", True):
        cover_file = os.path.join(output_dir, f"{title}_cover.jpg")
        sync(v.download_cover(output=cover_file))
        print(f"Cover: {cover_file}")

    if config.get("download_subtitles", True):
        subtitles_dir = os.path.join(output_dir, "subtitles")
        os.makedirs(subtitles_dir, exist_ok=True)
        subtitles = sync(v.get_subtitle())
        for sub in subtitles:
            sub_info = sync(v.get_subtitle(sub["id"]))
            sub_file = os.path.join(subtitles_dir, f"{title}_{sub['lan']}.json")
            with open(sub_file, "w", encoding="utf-8") as f:
                json.dump(sub_info, f, ensure_ascii=False, indent=2)
            print(f"Subtitle: {sub_file}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python download_with_config.py <bvid> [config.json]")
        sys.exit(1)

    bvid = sys.argv[1]
    config_file = sys.argv[2] if len(sys.argv) > 2 else "config.json"
    config = load_config(config_file)

    download_with_config(bvid, config)


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