-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7c6335f
commit 0f9e5ca
Showing
14 changed files
with
608 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
|
||
# | ||
temp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,55 @@ | ||
# ncmdump | ||
将.ncm格式音频文件转换为flac格式,提供windows客户端和WEB两种使用方式。(Convert .ncm format audio files to flac format, providing two usage options: a Windows client and a web interface.) | ||
# ncm -> flac converter | ||
|
||
将.ncm格式音频文件转换为flac格式,提供windows客户端和WEB两种使用方式。 | ||
|
||
## 1 环境 | ||
|
||
基本环境: | ||
```bash | ||
pip install mutagen | ||
pip install pycryptodome | ||
``` | ||
|
||
GUI额外环境: | ||
```bash | ||
pip install PyQt6 | ||
pip install pyinstaller | ||
``` | ||
|
||
WEB额外环境: | ||
```bash | ||
pip install streamlit | ||
``` | ||
|
||
全安装: | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
|
||
## 2 使用 | ||
|
||
### 2.1 GUI | ||
|
||
运行: | ||
```bash | ||
python gui.py | ||
``` | ||
|
||
编译: | ||
```bash | ||
pyinstaller --onefile --add-data="file:file" -wF -i file/favicon-32x32.png -n "NCM转换器" .\gui.py | ||
``` | ||
|
||
效果: | ||
![s1](./file/s1.gif) | ||
|
||
|
||
### 2.2 WEB | ||
|
||
运行: | ||
```bash | ||
streamlit run web.py --server.port 1111 | ||
``` | ||
|
||
效果: | ||
![s2](./file/s2.gif) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import ctypes | ||
import os | ||
|
||
class NcmdumpDll: | ||
def __init__(self, file_name): | ||
dll_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "libncmdump.dll")) | ||
self.dll = ctypes.CDLL(dll_path) | ||
|
||
# Define function prototypes | ||
self.dll.CreateNeteaseCrypt.argtypes = [ctypes.c_char_p] | ||
self.dll.CreateNeteaseCrypt.restype = ctypes.c_void_p | ||
|
||
self.dll.Dump.argtypes = [ctypes.c_void_p] | ||
self.dll.Dump.restype = ctypes.c_int | ||
|
||
self.dll.FixMetadata.argtypes = [ctypes.c_void_p] | ||
self.dll.FixMetadata.restype = None | ||
|
||
self.dll.DestroyNeteaseCrypt.argtypes = [ctypes.c_void_p] | ||
self.dll.DestroyNeteaseCrypt.restype = None | ||
|
||
# Convert file name to bytes | ||
file_bytes = file_name.encode('utf-8') | ||
|
||
# Allocate memory and copy file name bytes | ||
input_ptr = ctypes.create_string_buffer(file_bytes) | ||
|
||
# Create NeteaseCrypt instance | ||
self.netease_crypt = self.dll.CreateNeteaseCrypt(input_ptr) | ||
|
||
def dump(self): | ||
return self.dll.Dump(self.netease_crypt) | ||
|
||
def fix_metadata(self): | ||
self.dll.FixMetadata(self.netease_crypt) | ||
|
||
def destroy(self): | ||
self.dll.DestroyNeteaseCrypt(self.netease_crypt) | ||
|
||
def process_file(self): | ||
self.dump() | ||
self.fix_metadata() | ||
self.destroy() | ||
|
||
if __name__ == "__main__": | ||
# 文件名 | ||
file_path = "YOASOBI.ncm" | ||
# 创建 NeteaseCrypt 类的实例 | ||
netease_crypt = NcmdumpDll(file_path) | ||
# 启动转换过程 | ||
netease_crypt.process_file() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import sys | ||
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel | ||
from PyQt6.QtCore import Qt | ||
from PyQt6.QtGui import QDropEvent,QPixmap, QPainter, QFont, QColor,QFontMetrics,QIcon,QDragEnterEvent | ||
import os | ||
from ncmdump import dump | ||
|
||
class DragDropWidget(QWidget): | ||
def __init__(self, parent=None): | ||
super().__init__(parent) | ||
self.setAcceptDrops(True) | ||
self.init_ui() | ||
|
||
def init_ui(self): | ||
self.setWindowTitle("NCM转换器") | ||
self.setGeometry(100, 100, 573, 573) | ||
|
||
self.setWindowIcon(QIcon(self.get_resource_path("file/favicon-32x32.png"))) | ||
# 加载图片 | ||
self.original_pixmap = QPixmap(self.get_resource_path("file/bk.png")) | ||
|
||
self.label = QLabel(self) | ||
self.label.setPixmap(self.original_pixmap) | ||
self.label.setGeometry(0, 0, 573, 573) | ||
self.update_text('将ncm文件拖拽到此处') # 初始文本内容 | ||
def update_text(self, text): | ||
pixmap = self.original_pixmap.copy() # 复制原始的 QPixmap 对象 | ||
painter = QPainter(pixmap) | ||
painter.setPen(QColor('black')) # 设置文本颜色 | ||
font = QFont('SimHei', 20) # 设置字体和大小 | ||
painter.setFont(font) | ||
|
||
font_metrics = QFontMetrics(font) | ||
text_width = font_metrics.horizontalAdvance(text) | ||
text_height = font_metrics.height() | ||
|
||
x = (pixmap.width() - text_width) // 2 | ||
y = (pixmap.height() - text_height) // 2 + font_metrics.ascent() | ||
|
||
painter.drawText(x, y, text) # 在图片中居中绘制文本 | ||
painter.end() | ||
self.label.setPixmap(pixmap) # 更新 QLabel 中的图片 | ||
|
||
def get_resource_path(self,relative_path): | ||
if hasattr(sys, '_MEIPASS'): | ||
return os.path.join(sys._MEIPASS, relative_path) | ||
return os.path.join(os.path.abspath("."), relative_path) | ||
|
||
|
||
def dragEnterEvent(self, event: QDragEnterEvent): | ||
if event.mimeData().hasUrls(): | ||
event.acceptProposedAction() | ||
|
||
def dropEvent(self, event: QDropEvent): | ||
for url in event.mimeData().urls(): | ||
file_path = url.toLocalFile() | ||
if file_path.endswith(".ncm"): | ||
try: | ||
dump(file_path) | ||
self.update_text(f"处理完成:{file_path}") | ||
except Exception as e: | ||
self.update_text(f"处理文件时出错:{str(e)}") | ||
|
||
|
||
if __name__ == "__main__": | ||
app = QApplication(sys.argv) | ||
widget = DragDropWidget() | ||
widget.show() | ||
sys.exit(app.exec()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .core import dump |
Oops, something went wrong.