Skip to content

Commit 553e201

Browse files
committed
v2.1.1
1 parent 0cbe7b0 commit 553e201

File tree

6 files changed

+241
-84
lines changed

6 files changed

+241
-84
lines changed

Diff for: NotaGenNode.py

+141-37
Original file line numberDiff line numberDiff line change
@@ -292,15 +292,20 @@ def inference_patch(self, model, period, composer, instrumentation,
292292

293293
for image_path in png_paths:
294294
i = Image.open(image_path)
295-
i = ImageOps.exif_transpose(i)
295+
# 创建一个白色背景的图像
296+
image = Image.new("RGB", i.size, (255, 255, 255))
297+
298+
# 将透明背景的图片粘贴到白色背景上
299+
image.paste(i, mask=i.split()[3]) # 使用 Alpha 通道作为掩码
300+
# i = ImageOps.exif_transpose(i) # 翻转图片
296301

297302
# 调整宽度为1024,保持宽高比
298-
width, height = i.size
299-
new_width = 1024
300-
new_height = int(height * (new_width / width))
301-
i = i.resize((new_width, new_height), Image.Resampling.LANCZOS)
303+
# width, height = i.size
304+
# new_width = 1024
305+
# new_height = int(height * (new_width / width))
306+
# i = i.resize((new_width, new_height), Image.Resampling.LANCZOS)
302307

303-
image = i.convert("RGB")
308+
image = image.convert("RGB")
304309
image = np.array(image).astype(np.float32) / 255.0
305310
image = torch.from_numpy(image)[None,]
306311
images.append(image)
@@ -467,45 +472,144 @@ def wait_for_png_sequence(self, base_path, timeout=15, check_interval=0.3):
467472

468473
def xml2mp3(self, xml_path, musescore4_path):
469474
import subprocess
475+
import sys
476+
import tempfile
477+
470478
mp3_path = xml_path.rsplit(".", 1)[0] + ".mp3"
471-
try:
472-
subprocess.run(
473-
[musescore4_path, '-o', mp3_path, xml_path],
474-
check=True,
475-
capture_output=True,
476-
)
477-
# 等待MP3文件生成完成
478-
if self.wait_for_file(mp3_path):
479-
print(f"Conversion to {mp3_path} completed")
480-
return mp3_path
481-
else:
482-
print("MP3 conversion timeout")
479+
# 检测操作系统是否为 Linux
480+
if sys.platform == "linux":
481+
try:
482+
# 使用不同的显示端口
483+
display_number = 100
484+
os.environ["DISPLAY"] = f":{display_number}"
485+
486+
# 检查并清理旧的 Xvfb 锁文件
487+
tmp_dir = tempfile.mkdtemp()
488+
xvfb_lock_file = os.path.join(tmp_dir, f".X{display_number}-lock")
489+
if os.path.exists(xvfb_lock_file):
490+
print(f"清理旧的 Xvfb 锁文件: {xvfb_lock_file}")
491+
os.remove(xvfb_lock_file)
492+
493+
# 杀死所有残留的 Xvfb 进程
494+
subprocess.run(["pkill", "Xvfb"], stderr=subprocess.DEVNULL) # 忽略错误
495+
time.sleep(1) # 等待进程终止
496+
497+
# 启动 Xvfb
498+
xvfb_process = subprocess.Popen(["Xvfb", f":{display_number}", "-screen", "0", "1024x768x24"])
499+
time.sleep(2) # 等待 Xvfb 启动
500+
501+
# 设置 Qt 插件环境变量
502+
os.environ["QT_QPA_PLATFORM"] = "offscreen"
503+
504+
# 运行 mscore 命令
505+
subprocess.run(
506+
[musescore4_path, '-o', mp3_path, xml_path],
507+
check=True,
508+
capture_output=True,
509+
)
510+
511+
# 等待MP3文件生成完成
512+
if self.wait_for_file(mp3_path):
513+
print(f"Conversion to {mp3_path} completed")
514+
return mp3_path
515+
else:
516+
print("MP3 conversion timeout")
517+
return None
518+
except subprocess.CalledProcessError as e:
519+
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
520+
return None
521+
finally:
522+
# 关闭 Xvfb
523+
xvfb_process.terminate()
524+
xvfb_process.wait()
525+
else:
526+
try:
527+
subprocess.run(
528+
[musescore4_path, '-o', mp3_path, xml_path],
529+
check=True,
530+
capture_output=True,
531+
)
532+
# 等待MP3文件生成完成
533+
if self.wait_for_file(mp3_path):
534+
print(f"Conversion to {mp3_path} completed")
535+
return mp3_path
536+
else:
537+
print("MP3 conversion timeout")
538+
return None
539+
except subprocess.CalledProcessError as e:
540+
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
483541
return None
484-
except subprocess.CalledProcessError as e:
485-
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
486-
return None
487542

488543
def xml2png(self, xml_path, musescore4_path):
489544
import subprocess
545+
import sys
546+
import tempfile
490547

491548
base_png_path = xml_path.rsplit(".", 1)[0]
492-
try:
493-
subprocess.run(
494-
[musescore4_path, '-o', f"{base_png_path}.png", xml_path],
495-
check=True,
496-
capture_output=True,
497-
)
498-
# 等待PNG序列生成完成
499-
png_files = self.wait_for_png_sequence(base_png_path)
500-
if png_files:
501-
print(f"Converted to {len(png_files)} PNG files")
502-
return png_files
503-
else:
504-
print("PNG conversion timeout")
549+
# 检测操作系统是否为 Linux
550+
if sys.platform == "linux":
551+
try:
552+
# 使用不同的显示端口
553+
display_number = 100
554+
os.environ["DISPLAY"] = f":{display_number}"
555+
556+
# 检查并清理旧的 Xvfb 锁文件
557+
tmp_dir = tempfile.mkdtemp()
558+
xvfb_lock_file = os.path.join(tmp_dir, f".X{display_number}-lock")
559+
if os.path.exists(xvfb_lock_file):
560+
print(f"清理旧的 Xvfb 锁文件: {xvfb_lock_file}")
561+
os.remove(xvfb_lock_file)
562+
563+
# 杀死所有残留的 Xvfb 进程
564+
subprocess.run(["pkill", "Xvfb"], stderr=subprocess.DEVNULL) # 忽略错误
565+
time.sleep(1) # 等待进程终止
566+
567+
# 启动 Xvfb
568+
xvfb_process = subprocess.Popen(["Xvfb", f":{display_number}", "-screen", "0", "1024x768x24"])
569+
time.sleep(2) # 等待 Xvfb 启动
570+
571+
# 设置 Qt 插件环境变量
572+
os.environ["QT_QPA_PLATFORM"] = "offscreen"
573+
574+
# 运行 mscore 命令
575+
subprocess.run(
576+
[musescore4_path, '-o', f"{base_png_path}.png", xml_path],
577+
check=True,
578+
capture_output=True,
579+
)
580+
# 等待PNG序列生成完成
581+
png_files = self.wait_for_png_sequence(base_png_path)
582+
if png_files:
583+
print(f"Converted to {len(png_files)} PNG files")
584+
return png_files
585+
else:
586+
print("PNG conversion timeout")
587+
return None
588+
except subprocess.CalledProcessError as e:
589+
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
590+
return None
591+
finally:
592+
# 关闭 Xvfb
593+
xvfb_process.terminate()
594+
xvfb_process.wait()
595+
else:
596+
try:
597+
subprocess.run(
598+
[musescore4_path, '-o', f"{base_png_path}.png", xml_path],
599+
check=True,
600+
capture_output=True,
601+
)
602+
# 等待PNG序列生成完成
603+
png_files = self.wait_for_png_sequence(base_png_path)
604+
if png_files:
605+
print(f"Converted to {len(png_files)} PNG files")
606+
return png_files
607+
else:
608+
print("PNG conversion timeout")
609+
return None
610+
except subprocess.CalledProcessError as e:
611+
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
505612
return None
506-
except subprocess.CalledProcessError as e:
507-
print(f"Conversion failed: {e.stderr}" if e.stderr else "Unknown error")
508-
return None
509613

510614
def abc2xml(self, abc_path, output_dir, python_path):
511615
import subprocess

Diff for: README-CN.md

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
[中文](README-CN.md) | [English](README.md)
2+
3+
# 符号音乐生成. NotaGen 的 ComfyUI 节点.
4+
5+
![image](https://github.com/billwuhao/ComfyUI_NotaGen/blob/master/images/2025-03-10_06-24-03.png)
6+
7+
8+
## 📣 更新
9+
10+
[2025-03-15]⚒️: 支持 Linux Ubuntu/Debian 系列, 以及服务器, 其他未测试.
11+
12+
本地 Linux 电脑, 安装 `musescore` 等:
13+
```
14+
sudo apt update
15+
sudo apt install musescore
16+
sudo apt install libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0
17+
```
18+
然后将 `mscore` 路径输入节点即可, 如 `/bin/mscore`. 以及 comfyui 中 `python` 的绝对路径, 如 `/root/comfy/ComfyUI/bin/python`.
19+
20+
服务器, 安装虚拟显示器 Xvfb, 其他操作同上:
21+
```
22+
sudo apt update
23+
sudo apt install xvfb
24+
```
25+
26+
[2025-03-13]⚒️:
27+
28+
- 生成 `.abc` 自动转 `.xml`, `.mp3`, `.png` 格式, 可以听生成的音乐, 同时可以看曲谱啦🎵🎵🎵
29+
30+
- 支持自定义 prompt, 格式必须保持 `<period>|<composer>|<instrumentation>` 的格式, `period`, `composer`, `instrumentation` 的顺序不能乱, 而且以 `|` 分割.
31+
32+
- 为了避免配置环境变量的麻烦, 请安装 [MuseScore4](https://musescore.org/en/download), 并将 `MuseScore4.exe` 的绝对路径输入节点中, 如 `D:\APP\MuseScorePortable\App\MuseScore\bin\MuseScore4.exe`, 以及 comfyui 中 `python.exe` 的绝对路径, 如 `D:\AIGC\APP\ComfyUI_v1\python_embeded\python.exe`.
33+
34+
## 安装
35+
36+
```
37+
cd ComfyUI/custom_nodes
38+
git clone https://github.com/billwuhao/ComfyUI_NotaGen.git
39+
cd ComfyUI_NotaGen
40+
pip install -r requirements.txt
41+
42+
# python_embeded
43+
./python_embeded/python.exe -m pip install -r requirements.txt
44+
```
45+
46+
## 模型下载
47+
48+
将模型下载放到 `ComfyUI\models\TTS\NotaGen` 下, 并按要求重命名:
49+
50+
[NotaGen-X](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagenx_p_size_16_p_length_1024_p_layers_20_h_size_1280.pth)`notagenx.pth`
51+
[NotaGen-small](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagen_pretrain_p_size_16_p_length_2048_p_layers_12_c_layers_3_h_size_768_lr_0.0002_batch_8.pth)`notagen_small.pth`
52+
[NotaGen-medium](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagen_pretrain_p_size_16_p_length_2048_p_layers_16_c_layers_3_h_size_1024_lr_0.0001_batch_4.pth)`notagen_medium.pth`
53+
[NotaGen-large](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagen_pretrain_p_size_16_p_length_1024_p_layers_20_c_layers_6_h_size_1280_lr_0.0001_batch_4.pth)`notagen_large.pth`
54+
55+
56+
https://github.com/user-attachments/assets/229139bd-1065-4539-bcfa-b0c245259f6d
57+
58+
## 鸣谢
59+
60+
[NotaGen](https://github.com/ElectricAlexis/NotaGen)

Diff for: README-en.md

-33
This file was deleted.

Diff for: README.md

+39-10
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,51 @@
1-
[中文](README.md) | [English](README-en.md)
1+
[中文](README-CN.md) | [English](README.md)
22

3-
# 符号音乐生成. NotaGen 的 ComfyUI 节点.
3+
# Symbolic Music Generation, NotaGen node for ComfyUI.
44

55
![image](https://github.com/billwuhao/ComfyUI_NotaGen/blob/master/images/2025-03-10_06-24-03.png)
66

77

8-
## 📣 更新
8+
## 📣 Updates
99

10-
[2025-03-13]⚒️:
10+
[2025-03-15]⚒️: Supports Linux Ubuntu/Debian series, as well as servers, others untested, as well as servers.
1111

12-
- 生成 `.abc` 自动转 `.xml`, `.mp3`, `.png` 格式, 可以听生成的音乐, 同时可以看曲谱啦🎵🎵🎵
12+
For local Linux computers, install `musescore` etc.:
13+
```
14+
sudo apt update
15+
sudo apt install musescore
16+
sudo apt install libxcb-xinerama0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0
17+
```
18+
Then input the `mscore` path into the node, such as `/bin/mscore`. And the absolute path of `python` in ComfyUI, such as `/root/comfy/ComfyUI/bin/python`.
1319

14-
- 支持自定义 prompt, 格式必须保持 `<period>|<composer>|<instrumentation>` 的格式, `period`, `composer`, `instrumentation` 的顺序不能乱, 而且以 `|` 分割.
20+
For servers, install the virtual display Xvfb, other operations are the same as above:
21+
```
22+
sudo apt update
23+
sudo apt install xvfb
24+
```
1525

16-
- 为了避免配置环境变量的麻烦, 请安装 [MuseScore4](https://musescore.org/en/download), 并将 `MuseScore4.exe` 的绝对路径输入节点中, 如 `D:\APP\MuseScorePortable\App\MuseScore\bin\MuseScore4.exe`, 以及 comfyui 中 `python.exe` 的绝对路径, 如 `D:\AIGC\APP\ComfyUI_v1\python_embeded\python.exe`.
26+
[2025-03-13]⚒️:
1727

18-
## 模型下载
28+
- Automatically convert generated `.abc` to `.xml`, `.mp3`, and `.png` formats. Now you can listen to the generated music and see the sheet music too! 🎵🎵🎵
1929

20-
将模型下载放到 `ComfyUI\models\TTS\NotaGen` 下, 并按要求重命名:
30+
- Supports custom prompts. The format must be maintained as `<period>|<composer>|<instrumentation>`, with the order of `period`, `composer`, and `instrumentation` strictly enforced and separated by `|`.
31+
32+
- To avoid the hassle of configuring environment variables, please install [MuseScore4](https://musescore.org/en/download) and enter the absolute path of `MuseScore4.exe` into the node, such as `D:\APP\MuseScorePortable\App\MuseScore\bin\MuseScore4.exe`, as well as the absolute path of `python.exe` in ComfyUI, such as `D:\AIGC\APP\ComfyUI_v1\python_embeded\python.exe`.
33+
34+
## Installation
35+
36+
```
37+
cd ComfyUI/custom_nodes
38+
git clone https://github.com/billwuhao/ComfyUI_NotaGen.git
39+
cd ComfyUI_NotaGen
40+
pip install -r requirements.txt
41+
42+
# python_embeded
43+
./python_embeded/python.exe -m pip install -r requirements.txt
44+
```
45+
46+
## Model Download
47+
48+
Download the model to `ComfyUI\models\TTS\NotaGen` and rename it as required:
2149

2250
[NotaGen-X](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagenx_p_size_16_p_length_1024_p_layers_20_h_size_1280.pth)`notagenx.pth`
2351
[NotaGen-small](https://huggingface.co/ElectricAlexis/NotaGen/blob/main/weights_notagen_pretrain_p_size_16_p_length_2048_p_layers_12_c_layers_3_h_size_768_lr_0.0002_batch_8.pth)`notagen_small.pth`
@@ -27,6 +55,7 @@
2755

2856
https://github.com/user-attachments/assets/229139bd-1065-4539-bcfa-b0c245259f6d
2957

30-
## 鸣谢
58+
59+
## Acknowledgments
3160

3261
[NotaGen](https://github.com/ElectricAlexis/NotaGen)

Diff for: pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "notagen-mw"
33
description = "Symbolic Music Generation, NotaGen node for ComfyUI."
4-
version = "2.0.1"
4+
version = "2.1.1"
55
license = {file = "LICENSE"}
66

77
[project.urls]

Diff for: requirements.txt

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# transformers==4.40.0
2-
# numpy==1.26.4
3-
# gradio==5.17.1
41
wandb>=0.17.2
52
abctoolkit>=0.0.6
63
samplings>=0.1.7

0 commit comments

Comments
 (0)