[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93149":3},{"id":4,"name":5,"fullName":6,"owner":5,"repo":5,"description":7,"homepage":8,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":19,"hasPages":19,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":15,"starSnapshotCount":15,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},93149,"muscriptor","muscriptor\u002Fmuscriptor","MuScriptor is a multi-instrument music transcription model developed by Kyutai and Mirelo.","",null,"Python",244,25,1,3,0,109,54.24,"MIT License",false,"main",[],"2026-07-22 04:02:08","\u003Cp align=\"center\">\n  \u003Cimg src=\"web\u002Flogo_muscriptor_final.png\" alt=\"MuScriptor logo\" width=\"300\">\n\u003C\u002Fp>\n\n# MuScriptor\n\nMuScriptor is a multi-instrument music transcription model developed by [Kyutai](https:\u002F\u002Fkyutai.org) and [Mirelo](https:\u002F\u002Fwww.mirelo.ai).\nMuScriptor is the first music transcription model that has been trained on a large scale dataset of 170k songs from classical music to heavy metal.\n\n[Online Demo](https:\u002F\u002Fmuscriptor.kyutai.org) | [Paper](https:\u002F\u002Farxiv.org\u002Fabs\u002F2607.08168v1) | [HuggingFace](https:\u002F\u002Fhuggingface.co\u002FMuScriptor)\n\n\u003C!-- TODO: record the demo GIF (web UI piano roll), save it as assets\u002Fdemo.gif,\n     then uncomment:\n\u003Cp align=\"center\">\n  \u003Cimg src=\"assets\u002Fdemo.gif\" alt=\"MuScriptor web UI: live piano roll while transcribing\" width=\"700\">\n\u003C\u002Fp>\n-->\n\n## HuggingFace login (required)\n\nThe model weights are hosted on [HuggingFace](https:\u002F\u002Fhuggingface.co\u002FMuScriptor)\nand gated behind their CC BY-NC 4.0 license, so downloading them — including\non the first `uvx muscriptor` run — requires a (free) HuggingFace account:\n\n1. Accept the model license on the model page, e.g.\n   [muscriptor-medium](https:\u002F\u002Fhuggingface.co\u002FMuScriptor\u002Fmuscriptor-medium)\n   (access is granted automatically).\n2. Authenticate on your machine:\n\n   ```bash\n   uvx hf auth login\n   ```\n\n   or set a token (create one at\n   [huggingface.co\u002Fsettings\u002Ftokens](https:\u002F\u002Fhuggingface.co\u002Fsettings\u002Ftokens)):\n\n   ```bash\n   export HF_TOKEN=hf_...\n   ```\n\nThe weights are then downloaded on first use and cached locally.\n\n## Try it locally\n\nYou can try it locally with the web UI with:\n\n```bash\nuvx muscriptor serve\n```\n\nor with the CLI:\n\n```bash\nuvx muscriptor transcribe\n```  \n\n> **Intel Macs:** PyTorch stopped shipping Intel-mac (x86_64) wheels after\n> torch 2.2.2, which supports Python ≤ 3.12, so you must tell uvx to use\n> Python 3.12:\n>\n> ```bash\n> uvx --python 3.12 muscriptor serve\n> ```\n>\n> If you install with pip\u002Fuv instead, use Python 3.10–3.12.\n\n\n## Installation\n\nwith uv (recommended):\n\n```bash\nuv add muscriptor\n```\n\n```bash\npip install muscriptor\n```\n\n## Models\n\nThree variants are published under the [MuScriptor](https:\u002F\u002Fhuggingface.co\u002FMuScriptor)\nHuggingFace organization. Everywhere a model is selected (`load_model()`, the\nCLI's `--model`, `serve --model`) you can pass the bare size keyword and the\nweights are downloaded and cached automatically. The architecture is a transformer decoder only. Here are the detailed model sizes:\n\n| Variant | Parameters | Layers | Dim | HuggingFace repo |\n|---|---|---|---|---|\n| `small` | 103M | 14 | 768 | [muscriptor-small](https:\u002F\u002Fhuggingface.co\u002FMuScriptor\u002Fmuscriptor-small) |\n| `medium` (default) | 307M | 24 | 1024 | [muscriptor-medium](https:\u002F\u002Fhuggingface.co\u002FMuScriptor\u002Fmuscriptor-medium) |\n| `large` | 1.4B | 48 | 1536 | [muscriptor-large](https:\u002F\u002Fhuggingface.co\u002FMuScriptor\u002Fmuscriptor-large) |\n\n`small` is the practical choice on CPU-only machines, `medium` is the default\nspeed\u002Faccuracy trade-off, and `large` is the most accurate but really wants a\nGPU. \n## Usage\n\n```python\nfrom pathlib import Path\nfrom muscriptor import TranscriptionModel\n\n# Downloads the default \"medium\" variant from HuggingFace (cached under\n# ~\u002F.cache\u002Fmuscriptor\u002F). Also accepts \"small\"\u002F\"large\", a local safetensors\n# path, or an hf:\u002F\u002F \u002F http(s):\u002F\u002F URL.\nmodel = TranscriptionModel.load_model()\n\n# Stream events as they're transcribed. Optionally tell the model which\n# instruments to expect — run `muscriptor list-instruments` for the names.\nfor event in model.transcribe(\"audio.wav\", instruments=[\"acoustic_piano\", \"drums\"]):\n    print(event)\n\n# Or get a MIDI file directly\nmidi_bytes = model.transcribe_to_midi(\"audio.wav\")\nPath(\"out.mid\").write_bytes(midi_bytes)\n```\n\n```python\nfrom dataclasses import dataclass\nfrom typing import Generator\n\n\n@dataclass\nclass NoteStartEvent:\n    pitch: int\n    # Start of the note in seconds, from the beginning of the audio.\n    start_time: float\n    # A unique index for this note, used to match the corresponding\n    # NoteEndEvent.\n    index: int\n    instrument: str\n\n\n@dataclass\nclass NoteEndEvent:\n    end_time: float\n    # The NoteStartEvent this end matches. Convenient for consumers —\n    # when serializing (e.g. to JSON) drop this field and rely on\n    # `start_event_index` to refer back to the start by id.\n    start_event: NoteStartEvent\n\n    @property\n    def start_event_index(self) -> int:\n        return self.start_event.index\n\n\n@dataclass\nclass ProgressEvent:\n    # A coarse progress anchor woven into the event stream: `completed` of\n    # `total` 5-second chunks have been transcribed. One is emitted up front\n    # with completed == 0 (so consumers learn `total`), then one per finished\n    # chunk. Advisory only — consumers that just build notes can ignore them.\n    completed: int\n    total: int\n\n\nclass TranscriptionModel:\n    ...\n    def transcribe(\n            self,\n            audio: str | Path | tuple[torch.Tensor, int],\n            use_sampling: bool = False,\n            temperature: float = 1.0,\n            cfg_coef: float = 1.0,\n            instruments: list[str] | None = None,\n            batch_size: int | None = None,\n            no_eos_is_ok: bool = True,\n            beam_size: int = 1,\n        ) -> Generator[NoteStartEvent | NoteEndEvent | ProgressEvent, None, None]:\n        \"\"\"Transcribe audio into a stream of note events.\n\n        Args:\n            audio: Path to an audio file, or a tuple `(tensor, sample_rate)`\n                with a float tensor of shape [T] or [1, T] at `sample_rate`\n                Hz. The tuple form is useful when the audio is already\n                loaded in memory.\n            use_sampling: Use temperature sampling instead of greedy decoding.\n            temperature: Sampling temperature (only used when use_sampling=True).\n            cfg_coef: Classifier-free guidance coefficient. Keep to 1 for the released models (they are post-RL)\n            instruments: Optional list of instrument group names to\n                condition the model on (exact names, e.g.\n                [\"acoustic_piano\", \"drums\"]). Run `muscriptor\n                list-instruments` (or GET \u002Finstruments on the server)\n                for the full list of valid names.\n            batch_size: Number of 5-second chunks processed per forward\n                pass. `None` (default) picks a value based on the device:\n                1 on CPU, 4 on GPU. Use `batch_size=1` for the lowest\n                streaming latency — larger batches process several chunks\n                together, so events belonging to later chunks of a batch\n                won't arrive until the whole batch finishes. Within a\n                batch, events are always yielded in temporal order; all\n                events from chunk N are emitted before any event from\n                chunk N+1.\n            no_eos_is_ok: If True, a chunk that doesn't emit EOS within\n                the generation budget produces a warning instead of raising.\n            beam_size: Beam search width. 1 (default) uses greedy decoding\n                (or sampling, with use_sampling=True); >= 2 enables beam\n                search, which is slower but can be more accurate.\n\n        Returns:\n            Generator of NoteStartEvent, NoteEndEvent and ProgressEvent\n            objects. Every\n            NoteStartEvent is guaranteed to be followed by exactly one\n            matching NoteEndEvent later in the stream (with the same\n            `index`). Drum hits appear as a NoteStartEvent immediately\n            followed by its matching NoteEndEvent at the same start time\n            plus a tiny duration. Note: this tokenizer does not preserve\n            velocity (loudness) — only onset\u002Foffset timing, pitch, and\n            instrument are recovered.\n        \"\"\"\n\n    def transcribe_to_midi(\n            self,\n            audio: str | Path | tuple[torch.Tensor, int],\n            use_sampling: bool = False,\n            temperature: float = 1.0,\n            cfg_coef: float = 1.0,\n            instruments: list[str] | None = None,\n            batch_size: int | None = None,\n            no_eos_is_ok: bool = True,\n            beam_size: int = 1,\n        ) -> bytes:\n        \"\"\"Same as `transcribe`, but returns a MIDI file as bytes instead\n        of a generator of events. Useful when you want to save the MIDI\n        to disk or send it over a network without going through the\n        event stream.\n        \"\"\"\n```\n\n\n## CLI\n\n```bash\n# Transcribe to MIDI (defaults to \u003Caudio_file>.mid next to the input)\nmuscriptor transcribe audio.wav -o out.mid\n\n# Pick a model variant: small \u002F medium \u002F large (default: medium),\n# a local safetensors path, or an hf:\u002F\u002F \u002F http(s):\u002F\u002F URL\nmuscriptor transcribe audio.wav --model large\n\n# Tell the model which instruments to expect (comma-separated names;\n# run `muscriptor list-instruments` for the full list). Case-insensitive,\n# and unambiguous abbreviations work: 'timp,dist' = timpani + distorted\n# electric guitar\nmuscriptor transcribe audio.wav --instruments acoustic_piano,drums\n\n# Get the event stream instead of MIDI: json (single array) or\n# jsonl (one event per line, streamed while transcribing); -o - = stdout\nmuscriptor transcribe audio.wav --format jsonl -o -\n\n# Decoding options: temperature sampling, or beam search (slower, can be\n# more accurate)\nmuscriptor transcribe audio.wav --sampling -t 0.8\nmuscriptor transcribe audio.wav --beam-size 4\n\n# Render a stereo check-mix of the result (left channel = original audio,\n# right channel = synthesized MIDI; requires fluidsynth on PATH)\nmuscriptor transcribe audio.wav -o out.mid --auralize check.wav\n```\n\nSee `muscriptor transcribe --help` for the full list of options.\n\n## Web UI\n\nA browser client is included under `web\u002F`. The FastAPI server serves both\nthe UI and a POST `\u002Ftranscribe` endpoint that streams `NoteStart`\u002F`NoteEnd`\nevents back as Server-Sent Events. The UI accepts an audio file (WAV, or any\nformat soundfile\u002Flibsndfile can read — mp3, flac, ogg, m4a, …) via drag-and-drop,\nrenders a live piano roll while events arrive, auto-plays once enough notes\nare available, and crossfades between the original WAV and the synthesized\nMIDI playback.\n\n### One-time setup\n\n```bash\nuv sync\ncd web && pnpm install && pnpm run build && cd ..\n```\n\n`pnpm run build` is required once — it outputs to `muscriptor\u002Fweb_dist\u002F`,\nwhich the FastAPI server auto-mounts if it exists (and which ships inside\nthe PyPI wheel, so `uvx muscriptor serve` works without a checkout).\n\nThe soundfonts are not bundled: the server fetches\n`MuseScore_General.sf2` (215 MB, used by `\u002Fauralize`) and\n`MuseScore_General.sf3` (38 MB, the compressed build the UI plays) from\n[MuScriptor\u002Fassets](https:\u002F\u002Fhuggingface.co\u002FMuScriptor\u002Fassets) on first use\nand caches them locally (see `muscriptor\u002Fsoundfonts.py`).\n\n### Run\n\n```bash\nuv run muscriptor serve \\\n    --model medium \\\n    --device cuda \\\n    --host 0.0.0.0 \\\n    --port 8222\n```\n\n`--model` accepts a size keyword (`small`, `medium`, `large`) that downloads\nthe matching variant from HuggingFace (cached under `~\u002F.cache\u002Fmuscriptor\u002F`),\na local safetensors path, or an `hf:\u002F\u002F` \u002F `http(s):\u002F\u002F` URL. It defaults to\n`medium` when omitted.\n\nThen open \u003Chttp:\u002F\u002F127.0.0.1:8222\u002F> (or the LAN address of the host) and drop\na WAV onto the page.\n\n- Drop `--device cuda` if running CPU-only.\n- `--host 0.0.0.0` makes it reachable on the LAN; the default `127.0.0.1`\n  is local-only.\n- Playback runs a full SoundFont synthesizer ([SpessaSynth](https:\u002F\u002Fgithub.com\u002Fspessasus\u002Fspessasynth_lib))\n  in the browser, fed with `MuseScore_General.sf3` — the same soundfont the\n  `\u002Fauralize` endpoint uses, served by the app itself from `\u002Fsoundfonts\u002F`\n  (cached server-side), no third-party CDN.\n\n## License\n\nThe code in this repository is released under the [MIT license](LICENSE).\n\nThe model weights, published on\n[HuggingFace](https:\u002F\u002Fhuggingface.co\u002FMuScriptor), are released under the\n[CC BY-NC 4.0 license](https:\u002F\u002Fcreativecommons.org\u002Flicenses\u002Fby-nc\u002F4.0\u002F)\n(non-commercial use).\n\nThe MuseScore General SoundFont downloaded for playback \u002F auralization is\ndistributed under its own (MIT) license.\n\n## Citation\n\n```bibtex\n@misc{rouard2026muscriptoropenmodelmultiinstrument,\n      title={MuScriptor: An Open Model for Multi-Instrument Music Transcription}, \n      author={Simon Rouard and Michael Krause and Axel Roebel and Carl-Johann Simon-Gabriel and Alexandre Défossez},\n      year={2026},\n      eprint={2607.08168},\n      archivePrefix={arXiv},\n      primaryClass={cs.SD},\n      url={https:\u002F\u002Farxiv.org\u002Fabs\u002F2607.08168}, \n}\n```\n","MuScriptor 是一个面向多乐器的自动音乐转录模型，可将单声道音频（如钢琴、吉他、交响乐等混合演奏）转换为结构化乐谱表示（如钢琴卷帘、MIDI事件序列）。其核心基于Transformer解码器架构，支持small\u002Fmedium\u002Flarge三种规模模型，在17万首涵盖古典至重金属的高质量音频-乐谱对数据集上训练，兼顾跨流派泛化能力与实时推理可行性。适用于音乐教育辅助、即兴演奏记录、乐谱数字化归档及AI作曲前期处理等专业与半专业场景。",2,"2026-07-12 02:30:02","CREATED_QUERY"]