Vansh Chugh commited on
Commit
fed4376
·
1 Parent(s): 376a57c

initial deploy

Browse files
Files changed (6) hide show
  1. .gitignore +5 -0
  2. README.md +6 -5
  3. SOURCES.md +4 -0
  4. app.py +137 -0
  5. model.json +12 -0
  6. requirements.txt +2 -0
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .DS_Store
4
+ .venv/
5
+ MuScriptor-repo/
README.md CHANGED
@@ -1,13 +1,14 @@
1
  ---
2
  title: MuScriptor
3
- emoji: 🏆
4
- colorFrom: indigo
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.20.0
8
- python_version: '3.12'
9
  app_file: app.py
10
  pinned: false
 
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
  title: MuScriptor
3
+ emoji: 📜
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 5.28.0
8
+ python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
11
+ license: cc-by-nc-4.0
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
SOURCES.md ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Sources — MuScriptor
2
+
3
+ - Source repo: https://github.com/muscriptor/muscriptor
4
+ - Paper: https://arxiv.org/html/2607.08168v1
app.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ sys.stdout.reconfigure(line_buffering=True)
4
+
5
+ try:
6
+ import spaces
7
+ except ImportError:
8
+ # keep @spaces.GPU usable as a no-op; ZeroGPU requires this exact name.
9
+ class spaces:
10
+ class GPU:
11
+ def __init__(self, func=None, duration=60):
12
+ self.func = func
13
+
14
+ def __call__(self, *args, **kwargs):
15
+ if self.func is not None:
16
+ return self.func(*args, **kwargs)
17
+ func = args[0]
18
+ return func
19
+
20
+ import tempfile
21
+
22
+ import gradio as gr
23
+ import torch
24
+ from pyharp import ModelCard, build_endpoint
25
+
26
+ from muscriptor import TranscriptionModel
27
+ from muscriptor.tokenizer.mt3 import resolve_instrument_names
28
+
29
+ model_card = ModelCard(
30
+ name="MuScriptor",
31
+ description=(
32
+ "Multi-instrument audio-to-MIDI transcription, trained on 170k songs "
33
+ "from classical music to heavy metal."
34
+ ),
35
+ author="Simon Rouard, Michael Krause, Axel Roebel, Carl-Johann Simon-Gabriel, Alexandre Défossez (Kyutai x Mirelo)",
36
+ tags=["transcription", "midi", "multi-instrument"],
37
+ )
38
+
39
+ _models: dict[str, TranscriptionModel] = {}
40
+
41
+
42
+ def _get_model(variant: str) -> TranscriptionModel:
43
+ """Load and cache a TranscriptionModel for a given size, one per variant.
44
+
45
+ small/medium run on CPU; large runs on GPU. Built directly on its target
46
+ device inside this GPU-decorated call, per ZeroGPU rules.
47
+ """
48
+ if variant not in _models:
49
+ device = "cuda" if variant == "large" else "cpu"
50
+ _models[variant] = TranscriptionModel.load_model(variant, device=device)
51
+ return _models[variant]
52
+
53
+
54
+ def _parse_instruments(text: str) -> list[str] | None:
55
+ """Turn the comma-separated instruments box into exact group names.
56
+
57
+ Accepts unambiguous abbreviations, same as the CLI's --instruments.
58
+ Blank input means "no restriction, let the model decide".
59
+ """
60
+ tokens = [t for t in text.split(",") if t.strip()]
61
+ if not tokens:
62
+ return None
63
+ try:
64
+ return resolve_instrument_names(tokens)
65
+ except ValueError as e:
66
+ raise gr.Error(str(e))
67
+
68
+
69
+ @spaces.GPU
70
+ @torch.inference_mode()
71
+ def process_fn(
72
+ input_audio_path: str,
73
+ variant: str,
74
+ instruments_text: str,
75
+ use_sampling: bool,
76
+ temperature: float,
77
+ ) -> str:
78
+ model = _get_model(variant)
79
+ instruments = _parse_instruments(instruments_text)
80
+
81
+ midi_bytes = model.transcribe_to_midi(
82
+ input_audio_path,
83
+ use_sampling=use_sampling,
84
+ temperature=temperature,
85
+ instruments=instruments,
86
+ )
87
+
88
+ with tempfile.NamedTemporaryFile(suffix=".mid", delete=False) as f:
89
+ f.write(midi_bytes)
90
+ output_midi_path = f.name
91
+
92
+ return output_midi_path
93
+
94
+
95
+ with gr.Blocks() as demo:
96
+ input_components = [
97
+ gr.Audio(type="filepath", label="Input Audio").harp_required(True),
98
+ gr.Dropdown(
99
+ choices=["small", "medium", "large"],
100
+ value="medium",
101
+ label="Model Size",
102
+ info="small = fastest, least accurate. medium = balanced (default, per repo). large = most accurate, slower.",
103
+ ),
104
+ gr.Textbox(
105
+ value="",
106
+ label="Instruments",
107
+ info="Comma-separated instrument names to restrict decoding to, e.g. acoustic_piano,violin,trumpet,drums,etc. Leave blank to let the model detect instruments on its own.",
108
+ ),
109
+ gr.Checkbox(
110
+ value=False,
111
+ label="Use Sampling",
112
+ info="Temperature sampling instead of greedy decoding (default: False, per repo).",
113
+ ),
114
+ gr.Slider(
115
+ minimum=0.1,
116
+ maximum=2.0,
117
+ step=0.1,
118
+ value=1.0,
119
+ label="Temperature",
120
+ info="Only used when Use Sampling is on (default: 1.0, per repo).",
121
+ ),
122
+ ]
123
+ output_components = [
124
+ gr.File(type="filepath", file_types=[".mid", ".midi"], label="Output MIDI").set_info(
125
+ "Transcribed MIDI notes."
126
+ ),
127
+ ]
128
+
129
+ build_endpoint(
130
+ model_card=model_card,
131
+ input_components=input_components,
132
+ output_components=output_components,
133
+ process_fn=process_fn,
134
+ )
135
+
136
+ if __name__ == "__main__":
137
+ demo.queue().launch(pwa=True)
model.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "MuScriptor",
3
+ "package_dir": null,
4
+ "package_source": "pip install muscriptor (published package, not vendored)",
5
+ "entry_point": "muscriptor.TranscriptionModel",
6
+ "checkpoints": {
7
+ "small": {"repo": "MuScriptor/muscriptor-small", "filename": "model.safetensors", "size_mb": 412},
8
+ "medium": {"repo": "MuScriptor/muscriptor-medium", "filename": "model.safetensors", "size_mb": 1228},
9
+ "large": {"repo": "MuScriptor/muscriptor-large", "filename": "model.safetensors", "size_mb": 5466}
10
+ },
11
+ "checkpoint_hosting": "gated on MuScriptor's own HF org, downloaded at runtime by muscriptor.TranscriptionModel.load_model() via hf_hub_download; requires HF_TOKEN Space secret from an account that has accepted the CC BY-NC 4.0 license on all three muscriptor-* repos"
12
+ }
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ git+https://github.com/TEAMuP-dev/pyharp.git@develop
2
+ muscriptor