#!/usr/bin/env python3 """ 创建HTML可视化页面 """ import os import json import music21 from music21 import converter def create_html_visualizer(midi_path, output_dir="output"): """创建HTML可视化页面""" print("正在创建HTML可视化页面...") # 加载MIDI文件 score = music21.converter.parse(midi_path) # 提取音符数据 voice_data = [] voice_names = ['Soprano', 'Alto', 'Tenor', 'Bass'] voice_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4'] for i, part in enumerate(score.parts): if i >= 4: break part_notes = [] for element in part.flat.notes: if hasattr(element, 'pitch'): part_notes.append({ 'pitch': element.pitch.midi, 'note_name': element.pitch.nameWithOctave, 'start': float(element.offset), 'duration': float(element.quarterLength), 'velocity': element.volume.velocity if hasattr(element.volume, 'velocity') else 80 }) elif hasattr(element, 'pitches'): for p in element.pitches: part_notes.append({ 'pitch': p.midi, 'note_name': p.nameWithOctave, 'start': float(element.offset), 'duration': float(element.quarterLength), 'velocity': element.volume.velocity if hasattr(element.volume, 'velocity') else 80 }) voice_data.append({ 'name': voice_names[i], 'color': voice_colors[i], 'notes': part_notes }) # 创建HTML内容 html_content = f""" 四声部可视化

🎵 四声部可视化结果

0
总音符数
4
声部数量
0
时长(拍)
{generate_voice_sections(voice_data)}

📁 文件下载

下载 MusicXML 下载 MIDI

""" # 保存HTML文件 html_path = os.path.join(output_dir, "visualization.html") with open(html_path, 'w', encoding='utf-8') as f: f.write(html_content) print(f"HTML可视化页面已保存到: {html_path}") return html_path def generate_voice_sections(voice_data): """生成声部HTML部分""" html = "" for voice in voice_data: html += f"""
{voice['name']} ({len(voice['notes'])} 个音符)
""" # 显示前50个音符 for note in voice['notes'][:50]: html += f'
{note["note_name"]}
' if len(voice['notes']) > 50: html += f'
...还有{len(voice["notes"]) - 50}个音符
' html += """
""" return html def main(): output_dir = "output" midi_path = os.path.join(output_dir, "four_voice_score.mid") if not os.path.exists(midi_path): print(f"错误:MIDI文件 {midi_path} 不存在") return html_path = create_html_visualizer(midi_path, output_dir) print(f"\n✅ 可视化完成!") print(f"在浏览器中打开: file://{os.path.abspath(html_path)}") if __name__ == "__main__": main()