piano_transcription / convert.py
admin
sync
07c7745
raw
history blame
4.02 kB
import os
import sys
import fitz
import requests
import subprocess
from PIL import Image
from music21 import converter
def download(url: str, directory: str, filename: str):
if directory != "" and not os.path.exists(directory):
os.makedirs(directory)
# Create the full path for the file to be saved
file_path = os.path.join(directory, filename)
# Send a GET request to the URL
response = requests.get(url, stream=True)
# Check if the request was successful
if response.status_code == 200:
# Open the file in write-binary mode
with open(file_path, "wb") as file:
# Write the contents of the response to the file
for chunk in response.iter_content(chunk_size=1024):
if chunk: # Filter out keep-alive new chunks
file.write(chunk)
print(f"The file has been downloaded and saved to {file_path}")
else:
print(f"Failed to download the file. Status code: {response.status_code}")
return os.path.join(directory, filename)
if sys.platform.startswith("linux"):
apkname = "MuseScore.AppImage"
extra_dir = "squashfs-root"
if not os.path.exists(apkname):
download(
url="https://master.dl.sourceforge.net/project/musescore.mirror/v4.2.0/MuseScore-4.2.0.233521125-x86_64.AppImage?viasf=1",
directory="./",
filename=apkname,
)
if not os.path.exists(extra_dir):
subprocess.run(["chmod", "+x", f"./{apkname}"])
subprocess.run([f"./{apkname}", "--appimage-extract"])
MSCORE = f"./{extra_dir}/AppRun"
os.environ["QT_QPA_PLATFORM"] = "offscreen"
else:
MSCORE = "D:/Program Files/MuseScore 3/bin/MuseScore3.exe"
def add_title_to_xml(xml_path: str, title: str):
midi_data = converter.parse(xml_path)
# 将标题添加到 MIDI 文件中
midi_data.metadata.movementName = title
midi_data.metadata.composer = "Transcripted by AI"
# 保存修改后的 MIDI 文件
midi_data.write("musicxml", fp=xml_path)
def xml2abc(xml_path: str):
result = subprocess.run(
["python", "xml2abc.py", xml_path], stdout=subprocess.PIPE, text=True
)
if result.returncode == 0:
return result.stdout
return ""
def xml2mxl(xml_path: str):
mxl_file = xml_path.replace(".musicxml", ".mxl")
command = [MSCORE, "-o", mxl_file, xml_path]
result = subprocess.run(command)
print(result)
return mxl_file
def midi2xml(mid_file: str, title: str):
xml_file = mid_file.replace(".mid", ".musicxml")
command = [MSCORE, "-o", xml_file, mid_file]
result = subprocess.run(command)
add_title_to_xml(xml_file, title)
print(result)
return xml_file
def xml2midi(xml_file: str):
midi_file = xml_file.replace(".musicxml", ".mid")
command = [MSCORE, "-o", midi_file, xml_file]
result = subprocess.run(command)
print(result)
return midi_file
def pdf2img(pdf_path: str):
output_path = pdf_path.replace(".pdf", ".jpg")
doc = fitz.open(pdf_path)
# 创建一个图像列表
images = []
for page_number in range(doc.page_count):
page = doc[page_number]
# 将页面渲染为图像
image = page.get_pixmap()
# 将图像添加到列表
images.append(
Image.frombytes("RGB", [image.width, image.height], image.samples)
)
# 竖向合并图像
merged_image = Image.new(
"RGB", (images[0].width, sum(image.height for image in images))
)
y_offset = 0
for image in images:
merged_image.paste(image, (0, y_offset))
y_offset += image.height
# 保存合并后的图像为JPG
merged_image.save(output_path, "JPEG")
# 关闭PDF文档
doc.close()
return output_path
def xml2jpg(xml_file: str):
pdf_score = xml_file.replace(".musicxml", ".pdf")
command = [MSCORE, "-o", pdf_score, xml_file]
result = subprocess.run(command)
print(result)
return pdf_score, pdf2img(pdf_score)