Spaces:
Sleeping
Sleeping
| tags: [gradio-custom-component, File, MIDI, LLM] | |
| title: gradio_midijamsession | |
| short_description: Human AI Jam Sessions with Music LLMs | |
| colorFrom: blue | |
| colorTo: yellow | |
| sdk: docker | |
| pinned: false | |
| app_file: space.py | |
| # `gradio_midijamsession` | |
| <img alt="Static Badge" src="https://img.shields.io/badge/version%20-%200.0.1%20-%20orange"> | |
| Human AI Jam Sessions with Music LLMs | |
| ## Installation | |
| ```bash | |
| pip install gradio_midijamsession | |
| ``` | |
| ## Usage | |
| ```python | |
| """ | |
| Demo app for MidiJamSession component. | |
| Transposes all incoming MIDI notes by +2 semitones. | |
| """ | |
| import gradio as gr | |
| from gradio_midijamsession import MidiJamSession | |
| import io | |
| from processor import transpose_midi | |
| # Create the Gradio interface | |
| with gr.Blocks(title="MIDI Jam Session Demo") as demo: | |
| gr.Markdown(""" | |
| # 🎹 MIDI Jam Session Demo | |
| This demo shows the MidiJamSession component in action: | |
| 1. **Select your MIDI input device** - Connect your MIDI keyboard or controller | |
| 2. **Select your MIDI output device** - Choose where to send the processed MIDI | |
| 3. **Play some notes** - The component will record your input | |
| 4. **Wait 5 seconds** - After inactivity, the recording is sent for processing | |
| 5. **Listen to the result** - Notes are transposed up by 2 semitones and played back | |
| ## How it works | |
| - The frontend uses the **Web MIDI API** to capture live MIDI input | |
| - After 5 seconds of inactivity, the recording is converted to a MIDI file using **@tonejs/midi** | |
| - The backend receives the MIDI file and uses **mido** to transpose all notes by +2 semitones | |
| - The processed MIDI is sent back and played on your selected output device | |
| """) | |
| midi_session = MidiJamSession( | |
| label="MIDI Jam Session", | |
| bpm=120, | |
| interactive=True, | |
| ) | |
| # Connect the processing function | |
| midi_session.change( | |
| fn=transpose_midi, | |
| inputs=midi_session, | |
| outputs=midi_session, | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |
| ``` | |
| ## `MidiJamSession` | |
| ### Initialization | |
| <table> | |
| <thead> | |
| <tr> | |
| <th align="left">name</th> | |
| <th align="left" style="width: 25%;">type</th> | |
| <th align="left">default</th> | |
| <th align="left">description</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td align="left"><code>value</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| str | bytes | Callable | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">Default MIDI file to display, given as a str file path, URL, or bytes.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>bpm</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| int | |
| ``` | |
| </td> | |
| <td align="left"><code>value = 120</code></td> | |
| <td align="left">The tempo to use when creating MIDI files from recorded messages. Defaults to 120.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>label</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| str | I18nData | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">The label for this component.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>every</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| Timer | float | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">Continuously calls `value` to recalculate it if `value` is a function.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>inputs</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| Component | Sequence[Component] | set[Component] | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">Components that are used as inputs to calculate `value` if `value` is a function.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>show_label</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| bool | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">If True, will display label.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>container</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| bool | |
| ``` | |
| </td> | |
| <td align="left"><code>value = True</code></td> | |
| <td align="left">If True, will place the component in a container.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>scale</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| int | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">Relative size compared to adjacent Components.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>min_width</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| int | |
| ``` | |
| </td> | |
| <td align="left"><code>value = 160</code></td> | |
| <td align="left">Minimum pixel width.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>height</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| int | str | float | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">The height of the component.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>interactive</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| bool | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">If True, will allow users to interact with MIDI devices.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>visible</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| bool | Literal['hidden'] | |
| ``` | |
| </td> | |
| <td align="left"><code>value = True</code></td> | |
| <td align="left">If False, component will be hidden.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>elem_id</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| str | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">An optional string that is assigned as the id of this component in the HTML DOM.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>elem_classes</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| list[str] | str | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">An optional list of strings that are assigned as the classes of this component.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>render</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| bool | |
| ``` | |
| </td> | |
| <td align="left"><code>value = True</code></td> | |
| <td align="left">If False, component will not render in the Blocks context.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>key</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| int | str | tuple[int | str, ...] | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = None</code></td> | |
| <td align="left">In a gr.render, Components with the same key across re-renders are treated as the same component.</td> | |
| </tr> | |
| <tr> | |
| <td align="left"><code>preserved_by_key</code></td> | |
| <td align="left" style="width: 25%;"> | |
| ```python | |
| list[str] | str | None | |
| ``` | |
| </td> | |
| <td align="left"><code>value = "value"</code></td> | |
| <td align="left">A list of parameters from this component's constructor to preserve across re-renders.</td> | |
| </tr> | |
| </tbody></table> | |
| ### Events | |
| | name | description | | |
| |:-----|:------------| | |
| | `change` | Triggered when the value of the MidiJamSession changes either because of user input (e.g. a user types in a textbox) OR because of a function update (e.g. an image receives a value from the output of an event trigger). See `.input()` for a listener that is only triggered by user input. | | |
| | `upload` | This listener is triggered when the user uploads a file into the MidiJamSession. | | |
| | `clear` | This listener is triggered when the user clears the MidiJamSession using the clear button for the component. | | |
| ### User function | |
| The impact on the users predict function varies depending on whether the component is used as an input or output for an event (or both). | |
| - When used as an Input, the component only impacts the input signature of the user function. | |
| - When used as an output, the component only impacts the return signature of the user function. | |
| The code snippet below is accurate in cases where the component is used as both an input and an output. | |
| - **As output:** Is passed, the MIDI file contents as bytes. | |
| - **As input:** Should return, mIDI data as a file path (str/Path) or raw bytes. | |
| ```python | |
| def predict( | |
| value: bytes| None | |
| ) -> str| bytes| pathlib.Path| None: | |
| return value | |
| ``` | |