Nodes/ComfyTV/MIDI Editor
ComfyUI Node

MIDI Editor

Draw MIDI on a piano roll that lives in seconds, not beats

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
MIDI Editor
  • midi
  • midi
force_run_token0
project_id
parent_output_id0
events_json

The MIDI Editor is ComfyTV's answer to "I don't want to write out a score in MusicXML just to hear something." It's a piano roll that lives right on the node, and the thing that makes it different from every other MIDI editor you've opened is that the horizontal axis is seconds, not beats. That sounds like a small thing and it isn't. For fixing an actual MIDI performance - nudging a note so it lands on time, moving a chord that drags - a time-domain grid is exactly what you want. Score editors think in measures; this thinks in real time.

It slots into the ComfyTV music chain: Score → Score Performer → Score Synth → Muse Reverb → finished audio. The MIDI Editor is the hands-on alternative to Score, and its midi output feeds the same downstream synth stages, so you can draw a part, audition it, and render it through the SoundFont synthesizer without ever touching sheet music.

What you actually do with it

You draw notes onto the grid and organize them into MIDI channels, each with a General MIDI instrument plus a dedicated drum channel. There's mute/solo while you work and a velocity lane, DAW-style - per-note loudness carries through to the final render. Hit ▶ Run and the backend writes a Standard MIDI File; the midi output is a COMFYTV_AUDIO payload pointing at that exported .mid, ready to wire into Score Synth, the SF2 synthesizer, or any Audio stage.

You can also feed a MIDI file in: the optional midi input imports a wired file into the roll, channels, programs and all. That's the "download a backing track's MIDI, edit it, re-synth it" workflow, and it works well.

The inputs you can ignore

Like every ComfyTV stage, the info schema is front-loaded with plumbing: force_run_token, project_id, parent_output_id, and events_json are all internal, populated by ComfyTV's frontend. Don't touch them. All the real editing happens on the node's card - the schema is how the state travels, not how you work. That's a theme across every ComfyTV stage, and this is the node where it's easiest to get scared off by the schema. Don't be.

Install

ComfyTV is one pack, one install:

cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV

Restart ComfyUI and the stages appear under the ComfyTV category (this one under ComfyTV/Music). ComfyUI Manager also finds it if you search "ComfyTV". On ComfyUI Desktop or macOS, clone into the running instance's custom_nodes by absolute path - the common symptom of getting it wrong is a successful clone and no nodes anywhere. Verify custom_nodes/ComfyTV/__init__.py exists at the top level, then fully restart the backend, not just the browser tab. ComfyTV ships zero extra Python dependencies - the heavy lifting is the frontend plus whatever ComfyUI already has - so there's no requirements.txt dance.

When it bites you

Two gotchas worth knowing. First, running with an empty roll fails with "the piano roll is empty" - ComfyTV won't write an empty MIDI file, which is correct behavior but confusing the first time. Second, the outputs are project snapshots, not native ComfyUI tensors; to get MIDI into native ComfyUI nodes you route through a Bridge node. And if you're coming from a beat-grid editor, expect a beat of adjustment - literally. Your first bar will be timed by the ruler, not by the time signature.

CategoryComfyTV/Music

Inputs (5)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
events_jsonSTRING
midioptCOMFYTV_AUDIO

Outputs (1)

NameTypeDescription
midiCOMFYTV_AUDIO