Yongkang ZOU commited on
Commit
bec0341
·
1 Parent(s): 77ae978

update musicxml viz

Browse files
Files changed (1) hide show
  1. app.py +28 -30
app.py CHANGED
@@ -7,16 +7,17 @@ from pathlib import Path
7
  from basic_pitch.inference import predict_and_save
8
  from basic_pitch import ICASSP_2022_MODEL_PATH
9
  from music21 import converter
10
- import base64
11
 
12
  # 加载环境变量
13
  load_dotenv()
14
  MUSICGEN_API_URL = os.getenv("MUSICGEN_API_URL")
 
15
 
16
  # 确保输出目录存在
17
  Path("output").mkdir(exist_ok=True)
18
 
19
- def wav_to_musicxml(wav_path: str, timestamp: str) -> str:
 
20
  output_dir = Path("output")
21
 
22
  # 清理旧 MIDI 文件
@@ -44,33 +45,30 @@ def wav_to_musicxml(wav_path: str, timestamp: str) -> str:
44
  musicxml_path = output_dir / f"generated_{timestamp}.musicxml"
45
  score.write("musicxml", fp=musicxml_path)
46
 
47
- with open(musicxml_path, "r", encoding="utf-8") as f:
48
- musicxml_content = f.read()
49
-
50
- return musicxml_content
51
 
52
 
53
- def render_musicxml_html(musicxml_content: str) -> str:
54
- musicxml_b64 = base64.b64encode(musicxml_content.encode("utf-8")).decode("utf-8")
 
55
 
56
- html = f"""
57
- <div id="verovio-container"></div>
58
- <script type="module">
59
- import 'https://www.verovio.org/javascript/app/verovio-app.js';
 
 
60
 
61
- const container = document.getElementById('verovio-container');
62
- const app = new Verovio.App(container, {{
63
- defaultView: 'responsive',
64
- defaultZoom: 3,
65
- enableResponsive: true,
66
- enableDocument: false
67
- }});
68
 
69
- const musicxml = atob("{musicxml_b64}");
70
- app.loadData(musicxml);
71
- </script>
72
- """
73
- return html
 
 
74
 
75
 
76
  def generate_music_and_score(melody_file, prompt):
@@ -97,13 +95,13 @@ def generate_music_and_score(melody_file, prompt):
97
 
98
  # Step 2: 转 MusicXML
99
  try:
100
- musicxml_content = wav_to_musicxml(wav_out_path, timestamp)
101
  except Exception as e:
102
  return wav_out_path, f"⚠️ 音乐生成成功,但乐谱转换失败:{e}"
103
 
104
- # Step 3: 生成 HTML
105
- verovio_html = render_musicxml_html(musicxml_content)
106
- return wav_out_path, verovio_html
107
 
108
 
109
  demo = gr.Interface(
@@ -114,10 +112,10 @@ demo = gr.Interface(
114
  ],
115
  outputs=[
116
  gr.Audio(type="filepath", label="🎵 生成的音乐"),
117
- gr.HTML(label="🎼 乐谱预览 (Verovio)")
118
  ],
119
  title="🎵 MusicGen + 乐谱生成器",
120
- description="上传哼唱音频和描述,生成音乐并以 Verovio 可视化乐谱(纯 JS)"
121
  )
122
 
123
  if __name__ == "__main__":
 
7
  from basic_pitch.inference import predict_and_save
8
  from basic_pitch import ICASSP_2022_MODEL_PATH
9
  from music21 import converter
 
10
 
11
  # 加载环境变量
12
  load_dotenv()
13
  MUSICGEN_API_URL = os.getenv("MUSICGEN_API_URL")
14
+ VEROVIO_API_URL = os.getenv("VEROVIO_API_URL")
15
 
16
  # 确保输出目录存在
17
  Path("output").mkdir(exist_ok=True)
18
 
19
+
20
+ def wav_to_musicxml(wav_path: str, timestamp: str) -> Path:
21
  output_dir = Path("output")
22
 
23
  # 清理旧 MIDI 文件
 
45
  musicxml_path = output_dir / f"generated_{timestamp}.musicxml"
46
  score.write("musicxml", fp=musicxml_path)
47
 
48
+ return musicxml_path
 
 
 
49
 
50
 
51
+ def render_musicxml_via_verovio_api(musicxml_path: Path) -> str:
52
+ if not VEROVIO_API_URL:
53
+ return "❌ 未配置 VEROVIO_API_URL"
54
 
55
+ try:
56
+ with open(musicxml_path, "rb") as f:
57
+ files = {'file': f}
58
+ response = requests.post(VEROVIO_API_URL, files=files)
59
+ except Exception as e:
60
+ return f"❌ 调用 Verovio API 失败: {e}"
61
 
62
+ if response.status_code != 200:
63
+ return f"❌ Verovio API 错误 {response.status_code}: {response.text}"
 
 
 
 
 
64
 
65
+ try:
66
+ svg = response.json()["svg"]
67
+ svg_b64 = base64.b64encode(svg.encode("utf-8")).decode("utf-8")
68
+ html = f'<img src="data:image/svg+xml;base64,{svg_b64}" style="width:100%; max-height:600px;" />'
69
+ return html
70
+ except Exception as e:
71
+ return f"⚠️ SVG 解析失败:{e}"
72
 
73
 
74
  def generate_music_and_score(melody_file, prompt):
 
95
 
96
  # Step 2: 转 MusicXML
97
  try:
98
+ musicxml_path = wav_to_musicxml(wav_out_path, timestamp)
99
  except Exception as e:
100
  return wav_out_path, f"⚠️ 音乐生成成功,但乐谱转换失败:{e}"
101
 
102
+ # Step 3: 生成 SVG via Verovio API
103
+ html = render_musicxml_via_verovio_api(musicxml_path)
104
+ return wav_out_path, html
105
 
106
 
107
  demo = gr.Interface(
 
112
  ],
113
  outputs=[
114
  gr.Audio(type="filepath", label="🎵 生成的音乐"),
115
+ gr.HTML(label="🎼 乐谱预览(由 Verovio 渲染)")
116
  ],
117
  title="🎵 MusicGen + 乐谱生成器",
118
+ description="上传哼唱音频和描述,生成音乐并以 Verovio 渲染 SVG 乐谱"
119
  )
120
 
121
  if __name__ == "__main__":