feature:展示时长,比特率,大小

This commit is contained in:
charlesxie
2023-08-04 18:00:07 +08:00
parent 5dd227a447
commit 223cb8efb0
6 changed files with 179 additions and 31 deletions

View File

@@ -54,6 +54,7 @@ services:
restart: always
```
ps. `/path/to/your/music` 改成你的音乐文件夹路径!
3 访问在127.0.0.1:8001
# 📷 User Interface

View File

@@ -0,0 +1,2 @@
ALLOW_TYPE = ["flac", "mp3", "ape", "wav", "aiff", "wv", "tta", "m4a", "ogg", "mpc",
"opus", "wma", "dsf", "dff"]

View File

@@ -0,0 +1,143 @@
import base64
import os
import music_tag
class MusicIDS:
def __init__(self, folder):
self.file = music_tag.load_file(folder)
self.path = folder
@property
def album_name(self):
album_name = self.file["album"].value
album_name = album_name.replace(" ", "")
if not album_name:
album_name = "未知专辑"
return self.file["album"].value
@property
def album(self):
album_name = self.file["album"].value
album_name = album_name.replace(" ", "")
if not album_name:
album_name = "未知专辑"
return album_name
return self.file["album"].value
@property
def album_artist(self):
return self.file["albumartist"].value
@property
def artist_name(self):
return self.file["artist"].value
@property
def artist(self):
return self.file["artist"].value
@property
def year(self):
try:
year = self.file["year"].value
except Exception:
return 0
try:
year = int(year)
except Exception:
year_list = year.split("-")
if year_list and year_list[0]:
try:
return int(year_list[0].replace(" ", ""))
except Exception:
return 0
return year
@property
def genre(self):
genre = self.file["genre"].value
if genre:
genre = genre.upper()
else:
genre = "未知"
return genre
@property
def comment(self):
return self.file["comment"].value
@property
def lyrics(self):
return self.file["lyrics"].value
@property
def duration(self):
return round(self.file['#length'].value, 2)
@property
def size(self):
return round(os.path.getsize(self.path) / 1024 / 1024, 2)
@property
def suffix(self):
return self.file['#codec'].value
@property
def bit_rate(self):
return self.file['#bitrate'].value
@property
def track_number(self):
try:
return self.file['tracknumber'].value
except Exception:
return 1
@property
def disc_number(self):
try:
return self.file['discnumber'].value
except Exception:
return 1
@property
def title(self):
return self.file['title'].value
@property
def artwork(self):
try:
bs64_img = ""
artwork = self.file['artwork'].values
if artwork:
zip_img = artwork[0].raw_thumbnail([128, 128])
bs64_img = base64.b64encode(zip_img).decode()
return "data:image/jpeg;base64," + bs64_img
except Exception:
return ""
@property
def file_name(self):
return os.path.basename(self.path)
def to_dict(self):
return {
"year": self.year,
"comment": self.comment,
"lyrics": self.lyrics,
"duration": self.duration,
"size": self.size,
"suffix": self.suffix,
"bit_rate": self.bit_rate,
"tracknumber": self.track_number,
"discnumber": self.disc_number,
"artwork": self.artwork,
"title": self.title or self.file_name.split(".")[0],
"artist": self.artist,
"album": self.album,
"genre": self.genre,
"filename": self.file_name,
"albumartist": self.album_artist,
}

View File

@@ -8,10 +8,12 @@ from django.utils.decorators import method_decorator
from django.views.decorators.gzip import gzip_page
from rest_framework.decorators import action
from applications.task.constants import ALLOW_TYPE
from applications.task.models import TaskRecord, Task
from applications.task.serialziers import FileListSerializer, Id3Serializer, UpdateId3Serializer, \
FetchId3ByTitleSerializer, FetchLlyricSerializer, BatchUpdateId3Serializer, TranslationLycSerializer, \
TidyFolderSerializer
from applications.task.services.music_ids import MusicIDS
from applications.task.services.music_resource import MusicResource
from applications.task.services.update_ids import update_music_info
from applications.task.tasks import full_scan_folder, scan, clear_music, batch_auto_tag_task, tidy_folder_task
@@ -52,8 +54,6 @@ class TaskViewSets(GenericViewSet):
except FileNotFoundError:
return self.failure_response(msg="文件夹不存在")
children_data = []
allow_type = ["flac", "mp3", "ape", "wav", "aiff", "wv", "tta", "m4a", "ogg", "mpc",
"opus", "wma", "dsf", "dff"]
frc_map = {}
file_data = []
full_path_list = []
@@ -80,7 +80,7 @@ class TaskViewSets(GenericViewSet):
"children": []
})
continue
if file_type not in allow_type:
if file_type not in ALLOW_TYPE:
continue
if file_name in frc_map:
icon = "icon-script-files"
@@ -118,28 +118,7 @@ class TaskViewSets(GenericViewSet):
sub_path = file_path.split('/')[-1]
if sub_path == file_name:
return self.success_response()
file_title = file_name.split('.')[0]
f = music_tag.load_file(f"{file_path}/{file_name}")
artwork = f["artwork"].values
bs64_img = ""
if artwork:
zip_img = artwork[0].raw_thumbnail([128, 128])
bs64_img = base64.b64encode(zip_img).decode()
res_data = {
"title": f["title"].value or file_title,
"artist": f["artist"].value,
"album": f["album"].value,
"albumartist": f["albumartist"].value,
"genre": f["genre"].value,
"year": f["year"].value,
"lyrics": f["lyrics"].value,
"comment": f["comment"].value,
"tracknumber": f["tracknumber"].value,
"discnumber": f["discnumber"].value,
"artwork": "data:image/jpeg;base64," + bs64_img,
"filename": file_name
}
res_data = MusicIDS(f"{file_path}/{file_name}").to_dict()
return self.success_response(data=res_data)
@action(methods=['POST'], detail=False)

File diff suppressed because one or more lines are too long

View File

@@ -161,6 +161,24 @@
<bk-input :clearable="true" v-model="musicInfo.tracknumber"></bk-input>
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">时长</div>
<div style="width: 70%;">
{{musicInfo.duration}}
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">比特率</div>
<div style="width: 70%;">
{{musicInfo.bit_rate}}
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">文件大小</div>
<div style="width: 70%;">
{{musicInfo.size}}
</div>
</div>
</div>
</transition>
<transition name="bk-slide-fade-left">
@@ -186,7 +204,8 @@
<div style="display: flex;margin-bottom: 10px;align-items: center;margin-top: 10px;">
<div class="label1" v-bk-tooltips="'变量名:${title}'">标题</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.title"></bk-input>
<bk-input :clearable="true" v-model="musicInfoManual.title"
:placeholder="'支持变量批量修改'"></bk-input>
</div>
<div>
<bk-icon type="arrows-right-circle" @click="toggleLock('title')"
@@ -196,13 +215,15 @@
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1" v-bk-tooltips="'变量名:${filename}'">文件名</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.filename"></bk-input>
<bk-input :clearable="true" v-model="musicInfoManual.filename"
:placeholder="'例如:${title}-${album}'"></bk-input>
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1" v-bk-tooltips="'变量名:${artist}'">艺术家</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.artist"></bk-input>
<bk-input :clearable="true" v-model="musicInfoManual.artist"
:placeholder="'具体哪些变量,鼠标悬浮在标题上查看'"></bk-input>
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
@@ -212,7 +233,7 @@
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">专辑艺术家</div>
<div class="label1" v-bk-tooltips="'变量名:${albumartist}'">专辑艺术家</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.albumartist"></bk-input>
</div>
@@ -276,13 +297,13 @@
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">光盘编号</div>
<div class="label1" v-bk-tooltips="'变量名:${discnumber}'">光盘编号</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.discnumber"></bk-input>
</div>
</div>
<div style="display: flex;margin-bottom: 10px;align-items: center;">
<div class="label1">音轨号</div>
<div class="label1" v-bk-tooltips="'变量名:${tracknumber}'">音轨号</div>
<div style="width: 70%;">
<bk-input :clearable="true" v-model="musicInfoManual.tracknumber"></bk-input>
</div>
@@ -776,6 +797,7 @@
console.log(res)
if (res.result) {
this.$cwMessage('创建成功', 'success')
this.handleSearchFile()
} else {
this.$cwMessage('创建失败', 'error')
}