Ableton Live Integration Progress #
Overview #
Creating offline HTML bundles of AC pieces (specifically notepat) that can be loaded inside Ableton Live's Max for Live devices.
Goals #
- ✅ Generate self-contained HTML bundles for JavaScript pieces like
notepat - ✅ Bundle should work completely offline (no network requests)
- ✅ Show correct author (
@jeffrey) instead of@aesthetic - ✅ No
$prefix for JS pieces (only for KidLisp) - ✅ Suppress MIDI connection errors in console
- ✅ Piece loads correctly (was showing
noise16default instead ofnotepat) - ❌ Audio engine not working - currently silent
- ❌ Prompt HUD label missing - font glyph issue
- ❌ Fonts making network requests instead of loading from VFS
Completed Work #
1. Bundle Generation Infrastructure #
- File:
system/netlify/functions/bundle-html.js - Added support for JS piece bundles via
?piece=notepatparameter - Created
createJSPieceBundle()function that:- Discovers all ES module dependencies recursively
- Loads font glyphs from
disks/drawings/font_1/ - Minifies code using
@swc/wasm - Creates import maps for blob URLs
- Generates gzip-compressed self-extracting HTML
2. Fixed Author Display #
- Changed hardcoded
@aestheticto@jeffreyfor JS pieces - Made
$prefix conditional onisKidLispflag
3. Fixed MIDI Error Spam #
- Added MIDI-related messages to console suppression filter
4. Fixed Piece Not Loading #
- Issue: Piece was staying on default
noise16instead of loadingnotepat - Root cause: VFS fetch interceptor path resolution
- Added debug logging to VFS fetch interceptor
- Parse flow:
parse("notepat")→path="aesthetic.computer/disks/notepat" - In pack mode:
fullUrlbecomes../disks/notepat.mjs#timestamp - VFS interceptor strips
../and#...to getdisks/notepat.mjs
5. VFS (Virtual File System) Implementation #
// Fetch interceptor in bundle HTML
window.fetch = function(url, options) {
let vfsPath = decodeURIComponent(urlStr)
.replace(/^https?:\/\/[^\/]+\//g, '')
.replace(/^aesthetic\.computer\//g, '')
.replace(/#.*$/g, '')
.replace(/\?.*$/g, '');
vfsPath = vfsPath.replace(/^\.\.\/+/g, '').replace(/^\.\/+/g, '').replace(/^\/+/g, '');
console.log('[VFS] fetch:', urlStr, '->', vfsPath, 'exists:', !!window.VFS[vfsPath]);
// ...
};
Current Issues #
Issue 1: Audio Silent #
Status: In Progress
Root Cause Found: Audio worklet loading is explicitly skipped in PACK mode!
In bios.mjs lines 2056-2059:
if (isPackMode) {
if (debug) console.log("🎭 Skipping audio worklet loading in PACK mode");
return;
}
Why it was skipped: AudioWorklet.addModule() requires a URL, and the worklet files (speaker.mjs) have ES module imports that can't be resolved without a server.
Solution in progress:
-
✅ Created bundled version of speaker worklet:
lib/speaker-bundled.mjs(~50KB)- Used esbuild to bundle
speaker.mjswith all dependencies:sound/volume.mjssound/synth.mjssound/bubble.mjsnum.mjs(lerp, within, clamp functions)pack-mode.mjs
- Used esbuild to bundle
-
✅ Added
speaker-bundled.mjsto ESSENTIAL_FILES in bundle-html.js -
🔄 Need to modify
bios.mjsto:- In PACK mode, load worklet from VFS via blob URL
- Create blob URL from
window.VFS['lib/speaker-bundled.mjs'] - Use that blob URL with
audioContext.audioWorklet.addModule()
Issue 2: Fonts Making Network Requests #
Status: Investigating
Font glyphs ARE being bundled into VFS (lines 406-425 of bundle-html.js), but requests might not be matching VFS paths correctly.
Line 743 returns empty response for missing fonts instead of serving bundled content - this might be the issue.
Issue 3: HUD Label Missing #
Status: Blocked by Issue 2
The prompt HUD corner label uses font glyphs. If fonts aren't loading from VFS, the label won't render.
Files Modified #
| File | Changes |
|---|---|
system/netlify/functions/bundle-html.js |
Added JS piece bundling, VFS fetch interceptor, font loading |
system/public/aesthetic.computer/bios.mjs |
(Pending) Worklet blob URL loading for PACK mode |
system/public/aesthetic.computer/lib/speaker-bundled.mjs |
NEW - Pre-bundled speaker worklet |
Bundle Architecture #
HTML Bundle (gzip compressed)
├── Self-extracting script (decompresses on load)
├── VFS (Virtual File System) JSON object
│ ├── boot.mjs
│ ├── bios.mjs
│ ├── lib/*.mjs (all dependencies)
│ ├── disks/notepat.mjs (the piece)
│ ├── disks/drawings/font_1/**/*.json (font glyphs)
│ └── lib/speaker-bundled.mjs (bundled audio worklet)
├── Import Map (maps module paths to blob URLs)
├── Fetch Interceptor (serves VFS content for fetch() calls)
└── Bootstrap (loads boot.mjs from blob URL)
Commands Used #
# Bundle speaker worklet with esbuild
/workspaces/aesthetic-computer/system/node_modules/@esbuild/linux-arm64/bin/esbuild \
--bundle --format=esm \
--outfile=/tmp/speaker-bundled.mjs \
/workspaces/aesthetic-computer/system/public/aesthetic.computer/lib/speaker.mjs
# Generate bundle (from browser)
https://localhost:8888/api/bundle-html?piece=notepat&nocache=1
# Copy bundle to Mac
scp notepat.html jas@host.docker.internal:~/Desktop/
Next Steps #
- Fix Audio: Modify
bios.mjsto load bundled worklet from VFS blob URL in PACK mode - Fix Fonts: Debug VFS path matching for font glyph requests
- Test in M4L: Load bundle in Max for Live and verify full functionality
- Cleanup: Remove debug logging, optimize bundle size
Related Files #
ac-m4l/- Max for Live devicessystem/netlify/functions/bundle-html.js- Bundle generationsystem/public/aesthetic.computer/bios.mjs- Audio systemsystem/public/aesthetic.computer/lib/speaker.mjs- Speaker worklet (original)system/public/aesthetic.computer/lib/speaker-bundled.mjs- Speaker worklet (bundled)system/public/aesthetic.computer/disks/notepat.mjs- The piece being bundled