mirror of
https://github.com/xhongc/music-tag-web.git
synced 2026-02-02 17:59:07 +08:00
feature:展示时长,比特率,大小
This commit is contained in:
@@ -54,6 +54,7 @@ services:
|
||||
restart: always
|
||||
```
|
||||
ps. `/path/to/your/music` 改成你的音乐文件夹路径!
|
||||
|
||||
3 访问在127.0.0.1:8001
|
||||
|
||||
# 📷 User Interface
|
||||
|
||||
2
applications/task/constants.py
Normal file
2
applications/task/constants.py
Normal file
@@ -0,0 +1,2 @@
|
||||
ALLOW_TYPE = ["flac", "mp3", "ape", "wav", "aiff", "wv", "tta", "m4a", "ogg", "mpc",
|
||||
"opus", "wma", "dsf", "dff"]
|
||||
143
applications/task/services/music_ids.py
Normal file
143
applications/task/services/music_ids.py
Normal 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,
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
1
static/dist/js/app.b068a6c3125601076d2c.js
vendored
Normal file
1
static/dist/js/app.b068a6c3125601076d2c.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user