Repository navigation
Expand file tree
/
Copy pathbili_download.py
More file actions
116 lines (83 loc) · 3.57 KB
/
Copy pathbili_download.py
File metadata and controls
116 lines (83 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""
Bilibili 视频下载模块
下载 Bilibili 视频并转换为音频,自动使用视频标题命名。
使用示例:
from bilibili_downloader import download_video
audio_path = download_video(
url="https://www.bilibili.com/video/BV1xx411c7mD",
output_dir="./downloads",
quality=32
)
"""
import re
import os
import subprocess
from pathlib import Path
import requests
def sanitize_filename(filename: str) -> str:
illegal_chars = r'[\\/:*?"<>|]'
return re.sub(illegal_chars, '_', filename).strip()
def video_to_audio(video_path: str, audio_output_path: str):
subprocess.run([
"ffmpeg", "-i", video_path, "-vn", "-acodec", "libmp3lame",
"-ac", "1", "-ar", "16000", "-b:a", "64k", "-y", "-loglevel", "warning",
audio_output_path
], check=True)
def extract_bvid(url: str) -> str:
return re.search(r'BV[a-zA-Z0-9]{10}', url).group(0)
def create_session() -> requests.Session:
session = requests.Session()
session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Referer': 'https://www.bilibili.com',
'Accept': 'application/json, text/plain, */*'
})
return session
def get_video_info(session: requests.Session, bvid: str) -> dict:
url = f"https://api.bilibili.com/x/web-interface/view?bvid={bvid}"
data = session.get(url).json()
video_data = data['data']
return {
'bvid': bvid,
'title': video_data['title'],
'cid': video_data['cid']
}
def get_play_url(session: requests.Session, bvid: str, cid: int, quality: int = 32) -> dict:
url = f"https://api.bilibili.com/x/player/playurl?bvid={bvid}&cid={cid}&qn={quality}&fnval=1"
data = session.get(url).json()
durl = data['data']['durl'][0]
return {'url': durl['url'], 'size': durl['size']}
def download_video(url: str, output_dir: str = "./wav_cache", quality: int = 32):
print("开始下载...")
bvid = extract_bvid(url)
session = create_session()
video_info = get_video_info(session, bvid)
play_info = get_play_url(session, bvid, video_info['cid'], quality)
safe_title = sanitize_filename(video_info['title'])
video_path = Path(output_dir) / f"{safe_title}.mp4"
audio_path = Path(output_dir) / f"{safe_title}.wav"
os.makedirs(output_dir, exist_ok=True)
print(f"下载视频: {video_info['title']}")
with session.get(play_info['url'], headers={'Referer': f'https://www.bilibili.com/video/{bvid}'}, stream=True) as r:
with open(video_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=81920):
f.write(chunk)
video_to_audio(str(video_path), str(audio_path))
os.remove(video_path)
print(f"{video_info['title']}转音频完成!")
# return str(audio_path) # 返回音频文件路径
audio_name = audio_path.stem # 返回音频文件名(不包含扩展名)
return audio_name
if __name__ == "__main__":
audio_name = download_video("https://www.bilibili.com/video/BV1uu4y1m7ak", "./wav_cache")
print(f"音频文件名: {audio_name}")
# import sys
# if len(sys.argv) < 2:
# print(f"用法: python {sys.argv[0]} <B站视频URL> [输出目录] [质量]")
# print("质量: 80=高清, 64=标清, 32=流畅 (默认: 32)")
# sys.exit(1)
# url = sys.argv[1]
# output_dir = sys.argv[2] if len(sys.argv) > 2 else "./"
# quality = int(sys.argv[3]) if len(sys.argv) > 3 else 32
# result = download_video(url, output_dir, quality)
# print(f"下载完成: {result}")