Skip to content

Commit

Permalink
provide audio quality option 添加下载音质的 CLI 选项 (#19)
Browse files Browse the repository at this point in the history
* add .idea to gitignore

* provide audio quality options

* formatted by black && isort

* add property to audio_quality_enums get quality_id directly

* update Audio's audio_quality assignment

* modify audio_quality default value to 192

* modify default value of option --quality

* fix: reformatted style

Signed-off-by: jingfelix <jingfelix@outlook.com>

---------

Signed-off-by: jingfelix <jingfelix@outlook.com>
Co-authored-by: jingfelix <jingfelix@outlook.com>
  • Loading branch information
un4gt and jingfelix authored May 27, 2024
1 parent 8877a6d commit 6e30546
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 15 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,6 @@ temp/
.vscode/
.DS_Store

.pdm-python
.pdm-python

.idea/
30 changes: 26 additions & 4 deletions src/bilifm/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import requests
import typer

from .util import get_signed_params
from .util import AudioQualityEnums, get_signed_params


class Audio:
Expand All @@ -16,7 +16,7 @@ class Audio:

headers = {}

def __init__(self, bvid: str) -> None:
def __init__(self, bvid: str, audio_quality: AudioQualityEnums) -> None:
if bvid is None:
raise ValueError("bvid is None")

Expand All @@ -40,6 +40,8 @@ def __init__(self, bvid: str) -> None:
"Referer": "https://www.bilibili.com/video/{bvid}".format(bvid=self.bvid),
}

self.audio_quality = audio_quality.quality_id

# 获取cid和title
if len(bvid) == 12:
# BV号
Expand Down Expand Up @@ -76,9 +78,29 @@ def download(self):
self.playUrl, params=params, headers=self.headers
).json()

baseUrl = json["data"]["dash"]["audio"][0]["baseUrl"]
if json["data"] is None:
typer.echo(
f" `data` field is not valid with url: {self.playUrl} and params : {params}"
)
return

audio = json["data"]["dash"]["audio"]
if not audio:
typer.echo(
f" `audio` field is empty with url: {self.playUrl} and params : {params}"
)
return

base_url = None
for au in audio:
if au["id"] == self.audio_quality:
base_url = au["baseUrl"]

# no audio url corresponding to current audio quality
if base_url is None:
base_url = audio[0]["baseUrl"]

response = requests.get(url=baseUrl, headers=self.headers, stream=True)
response = requests.get(url=base_url, headers=self.headers, stream=True)

total_size = int(response.headers.get("content-length", 0))
temp_size = 0
Expand Down
39 changes: 29 additions & 10 deletions src/bilifm/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,32 @@
from .season import Season
from .series import Series
from .user import User
from .util import Directory, Path
from .util import AudioQuality, AudioQualityEnums, Directory, Path

app = typer.Typer()


@app.command()
def bv(bv: str, directory: Directory = None):
audio = Audio(bv)
def bv(
bv: str,
directory: Directory = None,
audio_quality: AudioQuality = AudioQualityEnums.k192.value,
):
audio = Audio(bv, audio_quality)
audio.download()


@app.command()
def uid(uid: str, directory: Directory = None):
def uid(
uid: str,
directory: Directory = None,
audio_quality: AudioQuality = AudioQualityEnums.k192.value,
):
user = User(uid)

for video in user.videos:
bv = video["bvid"]
audio = Audio(bv)
audio = Audio(bv, audio_quality)
audio.download()

typer.echo("Download complete")
Expand All @@ -35,21 +43,27 @@ def fav(
media_id: str,
cookies_path: str = Path,
directory: Directory = None,
audio_quality: AudioQuality = AudioQualityEnums.k192.value,
):
with open(cookies_path, "r") as f:
cookies = f.read()

fav = Fav(media_id, cookies)

for bvid in fav.id_list:
audio = Audio(bvid)
audio = Audio(bvid, audio_quality)
audio.download()

typer.echo("Download complete")


@app.command()
def season(uid: str, sid: str, directory: Directory = None):
def season(
uid: str,
sid: str,
directory: Directory = None,
audio_quality: AudioQuality = AudioQualityEnums.k192.value,
):
sea = Season(uid, sid)
audio_generator = sea.get_videos()
if not audio_generator:
Expand All @@ -62,13 +76,18 @@ def season(uid: str, sid: str, directory: Directory = None):

for audios in audio_generator:
for id in audios:
audio = Audio(id)
audio = Audio(id, audio_quality)
audio.download()
typer.echo("Download complete")


@app.command()
def series(uid: str, sid: str, directory: Directory = None):
def series(
uid: str,
sid: str,
directory: Directory = None,
audio_quality: AudioQuality = AudioQualityEnums.k64,
):
"""Download bilibili video series
The api of series lacks the series name, executing
Expand All @@ -82,6 +101,6 @@ def series(uid: str, sid: str, directory: Directory = None):

for audios in audio_generator:
for id in audios:
audio = Audio(id)
audio = Audio(id, audio_quality)
audio.download()
typer.echo("Download complete")
25 changes: 25 additions & 0 deletions src/bilifm/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import random
import time
import urllib.parse
from enum import Enum
from functools import reduce
from hashlib import md5
from typing import Callable
Expand Down Expand Up @@ -97,6 +98,24 @@
]


# 音质映射到具体值
audio_quality_map = {
"64": 30216,
"132": 30232,
"192": 30280,
}


class AudioQualityEnums(str, Enum):
k64 = "64"
k132 = "132"
k192 = "192"

@property
def quality_id(self):
return audio_quality_map[self._value_]


def getMixinKey(orig: str):
"对 imgKey 和 subKey 进行字符顺序打乱编码"
return reduce(lambda s, i: s + orig[i], mixinKeyEncTab, "")[:32]
Expand Down Expand Up @@ -214,3 +233,9 @@ def wrapped_request(*args, **kwargs):
return None

return wrapped_request


AudioQuality = Annotated[
AudioQualityEnums,
typer.Option("--quality", "-q", help="audio quality", case_sensitive=False),
]

0 comments on commit 6e30546

Please sign in to comment.