It looks like .mid is not an audio file (it can contain many audio files). You will likely need to bring in another library for this. quick search led me to https://pypi.org/project/midi2audio/
Hi, MIDI format indeed contains musical instructions rather than sound, requiring a synthesizer or soundfont for playback. In Jupyter, music21 (a Python library for music representation) can display scores with my_stream.show(), using an installed software like MuseScore, or play MIDI via my_stream.show('midi'). I developed Djalgo, a Python package for music composition using Jupyter and music21. As local installation is complex, I’m considering using Pyodide and Marimo on marimo.app. However, I need to solve display issues for both scores and MIDI. I’m considering developing a JavaScript MIDI player and integrating score rendering via e.g. ABCjs to overcome these challenges. However, I couldn't find a way to run JavaScript in Marimo cells, e.g.
Plain Text
python
import marimo as mo
def create_abc_score(abc_notation):
return mo.Html(f"""
<div id="notation"></div>
<script src="https://paulrosen.github.io/abcjs/dist/abcjs-basic-min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {{
var abcNotation = `{abc_notation}`;
abcjs.renderAbc("notation", abcNotation);
}});
</script>
""")
_abc = """
X:1
T:Simple Scale
M:4/4
L:1/4
K:C
C D E F|G A B c|
"""
_score = create_abc_score(_abc)
_score
import marimo as mo
import anywidget
import traitlets
class ABCjsWidget(anywidget.AnyWidget):
abc = traitlets.Unicode().tag(sync=True)
_esm = """
import * as abcjs from "https://cdn.jsdelivr.net/npm/abcjs@6.2.2/+esm";
export function render({ model, el }) {
function updateABC() {
el.innerHTML = '';
abcjs.renderAbc(el, model.get('abc'));
}
model.on('change:abc', updateABC);
updateABC();
}
export default { render };
"""
abc_state = mo.state("T:C-major scale\nX:1\nM:4/4\nL:1/4\nK:C\nCDEF|GABC")
widget = mo.ui.anywidget(ABCjsWidget(abc=abc_state[0]._value))
widget
Add a reply
Sign up and join the conversation on Discord
\"\"\") _abc = \"\"\"\nX:1\nT:Simple Scale\nM:4/4\nL:1/4\nK:C\nC D E F|G A B c|\n\"\"\" _score = create_abc_score(_abc)\n_score","dateCreated":"2024-07-24T14:04:53.418Z","dateModified":"2024-07-24T14:04:53.418Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"commentCount":0,"comment":[],"position":3,"upvoteCount":0},{"@type":"Comment","text":"if you need to run javascript, we recommend using Anywidget which is a plugin framework that we support: https://anywidget.dev/en/notebooks/counter/","dateCreated":"2024-07-24T14:48:59.611Z","dateModified":"2024-07-24T14:48:59.611Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/f8fa96b8-7157-405f-ad21-315db95af3b0","name":"Myles Scolnick","identifier":"f8fa96b8-7157-405f-ad21-315db95af3b0","image":"https://cdn.discordapp.com/avatars/760705447354433546/5b5b6140bd57e475c427a7b4bfae3b70.webp?size=256"},"commentCount":0,"comment":[],"position":4,"upvoteCount":0},{"@type":"Comment","text":"Hi @Myles Scolnick, I played a bit with ABCjs, anywidget and Marimo, but without success. It's working in Jupyter, though. Have I done anything wrong?# cell 1\nimport anywidget\nimport traitlets\nimport marimo as mo class ABCjsWidget(anywidget.AnyWidget): abc = traitlets.Unicode(\"X:1\\nT:Scale\\nM:4/4\\nL:1/4\\nK:C\\nCDEF|GABC'|\").tag(sync=True) _esm = \"\"\" import * as abcjs from \"https://cdn.jsdelivr.net/npm/abcjs@6.2.2/+esm\"; export function render({ model, el }) { function updateABC() { el.innerHTML = ''; abcjs.renderAbc(el, model.get('abc')); } model.on('change:abc', updateABC); updateABC(); } \"\"\" widget = mo.ui.anywidget(ABCjsWidget())\n# widget = ABCjsWidget() # jupyter # cell 2\nwidget.abc = \"\"\"\nX:1\nT:Ode to Joy\nM:4/4\nL:1/4\nK:C\nEEFG|GFED|CCDE|E2D2|\n\"\"\" # cell 3\nwidget`","dateCreated":"2024-07-26T20:57:34.634Z","dateModified":"2024-07-26T20:57:34.634Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"commentCount":0,"comment":[],"position":5,"upvoteCount":0},{"@type":"Comment","text":"since you are technically mutating state- we may not be re-rendering this (which is a marimo requirement, no mutating state) Given this is an any widget, we can possibly handle this like we do with mo.state","dateCreated":"2024-07-26T21:47:59.369Z","dateModified":"2024-07-26T21:47:59.369Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/f8fa96b8-7157-405f-ad21-315db95af3b0","name":"Myles Scolnick","identifier":"f8fa96b8-7157-405f-ad21-315db95af3b0","image":"https://cdn.discordapp.com/avatars/760705447354433546/5b5b6140bd57e475c427a7b4bfae3b70.webp?size=256"},"commentCount":0,"comment":[],"position":6,"upvoteCount":0},{"@type":"Comment","text":"Thanks for the tip! But even without state mutation, nothing is displayed.import marimo as mo\nimport anywidget\nimport traitlets class ABCjsWidget(anywidget.AnyWidget): abc = traitlets.Unicode(\"\"\" T:C-major scale X:1 M:4/4 L:1/4 K:C CDEF|GABC \"\"\").tag(sync=True) _esm = \"\"\" import * as abcjs from \"https://cdn.jsdelivr.net/npm/abcjs@6.2.2/+esm\"; export function render({ model, el }) { function updateABC() { el.innerHTML = ''; abcjs.renderAbc(el, model.get('abc')); } model.on('change:abc', updateABC); updateABC(); } \"\"\" mo.ui.anywidget(ABCjsWidget())","dateCreated":"2024-07-27T03:02:25.098Z","dateModified":"2024-07-27T03:02:25.098Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"commentCount":0,"comment":[],"position":7,"upvoteCount":0},{"@type":"Comment","text":"Maybe that's an issue displaying the svg outcome?","dateCreated":"2024-07-29T14:11:36.941Z","dateModified":"2024-07-29T14:11:36.941Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"commentCount":0,"comment":[],"position":8,"upvoteCount":0},{"@type":"Comment","text":"You need to add export default { render }; at the bottom","dateCreated":"2024-07-29T14:27:29.890Z","dateModified":"2024-07-29T14:27:29.890Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/f8fa96b8-7157-405f-ad21-315db95af3b0","name":"Myles Scolnick","identifier":"f8fa96b8-7157-405f-ad21-315db95af3b0","image":"https://cdn.discordapp.com/avatars/760705447354433546/5b5b6140bd57e475c427a7b4bfae3b70.webp?size=256"},"commentCount":0,"comment":[],"position":9,"upvoteCount":0},{"@type":"Comment","text":"_esm = \"\"\" import * as abcjs from \"https://cdn.jsdelivr.net/npm/abcjs@6.2.2/+esm\"; export function render({ model, el }) { function updateABC() { el.innerHTML = ''; abcjs.renderAbc(el, model.get('abc')); } model.on('change:abc', updateABC); updateABC(); } export default { render }; \"\"\"","dateCreated":"2024-07-29T14:27:43.520Z","dateModified":"2024-07-29T14:27:43.520Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/f8fa96b8-7157-405f-ad21-315db95af3b0","name":"Myles Scolnick","identifier":"f8fa96b8-7157-405f-ad21-315db95af3b0","image":"https://cdn.discordapp.com/avatars/760705447354433546/5b5b6140bd57e475c427a7b4bfae3b70.webp?size=256"},"commentCount":0,"comment":[],"position":10,"upvoteCount":0},{"@type":"Comment","text":"this might actually be fixed in the latest marimo as well, actually export default { render }; seems required","dateCreated":"2024-07-29T14:28:35.532Z","dateModified":"2024-07-29T14:28:35.532Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/f8fa96b8-7157-405f-ad21-315db95af3b0","name":"Myles Scolnick","identifier":"f8fa96b8-7157-405f-ad21-315db95af3b0","image":"https://cdn.discordapp.com/avatars/760705447354433546/5b5b6140bd57e475c427a7b4bfae3b70.webp?size=256"},"commentCount":0,"comment":[],"position":11,"upvoteCount":0},{"@type":"Comment","text":"Wow, magic!!! Thanks++!Edit: the code with mo.state.import marimo as mo\nimport anywidget\nimport traitlets class ABCjsWidget(anywidget.AnyWidget): abc = traitlets.Unicode().tag(sync=True) _esm = \"\"\" import * as abcjs from \"https://cdn.jsdelivr.net/npm/abcjs@6.2.2/+esm\"; export function render({ model, el }) { function updateABC() { el.innerHTML = ''; abcjs.renderAbc(el, model.get('abc')); } model.on('change:abc', updateABC); updateABC(); } export default { render }; \"\"\" abc_state = mo.state(\"T:C-major scale\\nX:1\\nM:4/4\\nL:1/4\\nK:C\\nCDEF|GABC\")\nwidget = mo.ui.anywidget(ABCjsWidget(abc=abc_state[0]._value))\nwidget","dateCreated":"2024-07-29T18:05:53.486Z","dateModified":"2024-07-29T18:05:53.486Z","author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"commentCount":0,"comment":[],"position":12,"upvoteCount":0}],"author":{"@type":"Person","url":"https://marimo.hall.community/members/6cc38e83-e2c0-479b-9c40-5f3c098a054b","name":"essi","identifier":"6cc38e83-e2c0-479b-9c40-5f3c098a054b","image":"https://cdn.discordapp.com/embed/avatars/3.png"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0}}]