ohfiftyb252 commited on
Commit
2697437
Β·
verified Β·
1 Parent(s): ab5d34d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +140 -0
app.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Music Transcriber - Gradio Web App for Hugging Face Spaces"""
3
+
4
+ import gradio as gr
5
+ from pathlib import Path
6
+ import tempfile
7
+ import os
8
+
9
+ # Redirect caches to /tmp for HF Spaces
10
+ os.environ['HF_HOME'] = '/tmp/hf_cache'
11
+ os.environ['TORCH_HOME'] = '/tmp/hf_cache/torch'
12
+ os.environ['TRANSFORMERS_CACHE'] = '/tmp/hf_cache'
13
+
14
+ def transcribe_audio(audio_file, model_size, instruments):
15
+ """Transcribe audio to MIDI with progress tracking."""
16
+ if audio_file is None:
17
+ return None, "❌ Please upload an audio file first.", 0
18
+
19
+ from muscriptor import TranscriptionModel
20
+ from muscriptor.events import ProgressEvent
21
+
22
+ # Parse instrument filter
23
+ instrument_group = None
24
+ instrument_names = []
25
+ if instruments:
26
+ try:
27
+ from muscriptor.tokenizer.mt3 import MT3_FULL_PLUS_GROUP_NAMES
28
+ names = [n.strip().lower() for n in instruments.split(",")]
29
+ valid_names = [n for n in names if n in MT3_FULL_PLUS_GROUP_NAMES]
30
+ instrument_group = " ".join(str(MT3_FULL_PLUS_GROUP_NAMES[n]) for n in valid_names)
31
+ instrument_names = valid_names
32
+ except Exception:
33
+ pass
34
+
35
+ try:
36
+ model = TranscriptionModel.load_model(model_size)
37
+ except Exception as e:
38
+ return None, f"❌ Model load failed: {e}", 0
39
+
40
+ output_path = Path(tempfile.mktemp(suffix='.mid'))
41
+
42
+ try:
43
+ note_events = []
44
+ progress_status = "Starting..."
45
+
46
+ for event in model.transcribe(str(audio_file), instrument_group=instrument_group):
47
+ if isinstance(event, ProgressEvent):
48
+ progress_status = f"🎹 Processing: {int(event.fraction * 100)}%"
49
+ elif hasattr(event, 'note_id'):
50
+ note_events.append(event)
51
+
52
+ midi_bytes = model.transcribe_to_midi(str(audio_file), instrument_group=instrument_group)
53
+ output_path.write_bytes(midi_bytes)
54
+
55
+ msg = f"βœ… Complete!\n🎼 {len(note_events)} notes detected\nπŸ“ MIDI ready for download"
56
+ if instrument_names:
57
+ msg += f"\nπŸ” Filtered: {', '.join(instrument_names)}"
58
+
59
+ return str(output_path), msg, len(note_events)
60
+
61
+ except Exception as e:
62
+ if output_path.exists():
63
+ output_path.unlink()
64
+ return None, f"❌ Error: {e}", 0
65
+
66
+ def list_instruments():
67
+ """Return list of available instruments."""
68
+ try:
69
+ from muscriptor.tokenizer.mt3 import MT3_FULL_PLUS_GROUP_NAMES
70
+ instruments = sorted(MT3_FULL_PLUS_GROUP_NAMES.keys())
71
+ return "\n".join(f"β€’ {name}" for name in instruments)
72
+ except Exception:
73
+ return "Could not load instrument list. Install muscriptor first."
74
+
75
+ # Build Gradio Interface
76
+ with gr.Blocks(
77
+ title="🎡 Music Transcriber",
78
+ theme=gr.themes.Soft(primary_hue="purple"),
79
+ css="""
80
+ .gradio-container { max-width: 900px !important; }
81
+ .note-count { font-size: 2rem; font-weight: bold; color: #8b5cf6; text-align: center; padding: 1rem; }
82
+ .instructions { font-size: 0.9rem; color: #6b7280; }
83
+ """
84
+ ) as demo:
85
+
86
+ gr.Markdown("# 🎡 Music Transcriber\nTurn audio into MIDI using AI. Upload a song, select model size, and get your transcription!")
87
+
88
+ with gr.Row():
89
+ with gr.Column(scale=1):
90
+ audio_input = gr.Audio(
91
+ type="filepath",
92
+ label="Upload Audio (MP3, WAV, FLAC, OGG, M4A)",
93
+ interactive=True
94
+ )
95
+
96
+ with gr.Row():
97
+ model_select = gr.Radio(
98
+ choices=[("Small (~100M) - Fastest ⚑", "small"),
99
+ ("Medium (~300M) - Balanced πŸ‘", "medium"),
100
+ ("Large (~1.3B) - Best Quality 🌟", "large")],
101
+ value="medium",
102
+ label="Model Size"
103
+ )
104
+
105
+ instrument_input = gr.Textbox(
106
+ label="Filter Instruments (optional)",
107
+ placeholder="e.g., acoustic_piano, acoustic_guitar, electric_bass",
108
+ info="Comma-separated instrument names. Leave blank for all instruments."
109
+ )
110
+
111
+ transcribe_btn = gr.Button("🎹 Transcribe Audio", variant="primary", size="lg")
112
+
113
+ with gr.Column(scale=1):
114
+ status_output = gr.Textbox(label="Status", lines=4)
115
+ note_count_output = gr.HTML('<div class="note-count">0</div>')
116
+ midi_output = gr.File(label="Download MIDI", visible=False)
117
+
118
+ # List instruments accordion
119
+ with gr.Accordion("πŸ“‹ View Available Instruments", open=False):
120
+ gr.Markdown("```")
121
+ inst_list = gr.Markdown(label="Instruments")
122
+ gr.Markdown("```")
123
+
124
+ # Button callbacks
125
+ transcribe_btn.click(
126
+ fn=transcribe_audio,
127
+ inputs=[audio_input, model_select, instrument_input],
128
+ outputs=[midi_output, status_output, note_count_output]
129
+ ).then(
130
+ lambda path, notes: (gr.update(visible=bool(path)), f"<div class='note-count'>{notes}</div>"),
131
+ inputs=[midi_output, note_count_output],
132
+ outputs=[midi_output, note_count_output]
133
+ )
134
+
135
+ # Initialize instrument list
136
+ gr.Markdown("Click the accordion above to see all available instruments.")
137
+ inst_list.value = list_instruments()
138
+
139
+ if __name__ == "__main__":
140
+ demo.launch()