[{"data":1,"prerenderedAt":7911},["ShallowReactive",2],{"navigation":3,"/blog/software-development/what-is-watermarked-song-post":734,"/blog/software-development/what-is-watermarked-song-surround":975,"/blog/software-development/what-is-watermarked-song-related":980},[4,70,207,312,721],{"title":5,"path":6,"stem":7,"children":8,"page":69},"Case Study","/blog/case-study","blog/case-study",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,65],{"title":10,"path":11,"stem":12},"Ambistream – Multi-Layer Streaming Platform","/blog/case-study/ambistream-building-a-multi-layer-streaming-platform-from-a-spark-of-an-idea","blog/case-study/ambistream-building-a-multi-layer-streaming-platform-from-a-spark-of-an-idea",{"title":14,"path":15,"stem":16},"Custom Chromecast & AirPlay Casting App","/blog/case-study/chromecast-airplay-casting-app-case-study","blog/case-study/chromecast-airplay-casting-app-case-study",{"title":18,"path":19,"stem":20},"Direct Music Licensing Platform Case Study","/blog/case-study/dlm-music-catalog-case-study","blog/case-study/dlm-music-catalog-case-study",{"title":22,"path":23,"stem":24},"Assembly Instructions App - Galeco Mobile App","/blog/case-study/galeco-mobile-app-case-study","blog/case-study/galeco-mobile-app-case-study",{"title":26,"path":27,"stem":28},"MemoSonic: Building an Audio Memory Game","/blog/case-study/how-we-built-memosonic-accessible-audio-memory-game-flutter","blog/case-study/how-we-built-memosonic-accessible-audio-memory-game-flutter",{"title":30,"path":31,"stem":32},"Loyalty Program App for Shopping Mall","/blog/case-study/loyalty-program-application-case-study","blog/case-study/loyalty-program-application-case-study",{"title":34,"path":35,"stem":36},"Mobile Application for Music Catalogs","/blog/case-study/mobile-app-for-music-catalog","blog/case-study/mobile-app-for-music-catalog",{"title":38,"path":39,"stem":40},"Universal Music Data Parser for 20+ Platforms","/blog/case-study/musicdata-lab-universal-music-data-parser-case-study","blog/case-study/musicdata-lab-universal-music-data-parser-case-study",{"title":42,"path":43,"stem":44},"Panther ML/AI Pricing Recommendation Tool","/blog/case-study/panther-pricing-recommendation-tool-case-study","blog/case-study/panther-pricing-recommendation-tool-case-study",{"title":46,"path":47,"stem":48},"4D Grupa Roofing Wholesalers Platform","/blog/case-study/roofing-wholesalers-website-case-study","blog/case-study/roofing-wholesalers-website-case-study",{"title":50,"path":51,"stem":52},"Talent Alpha HR Frontend Platform","/blog/case-study/talent-alpha-hr-platform-case-study","blog/case-study/talent-alpha-hr-platform-case-study",{"title":54,"path":55,"stem":56},"Ticketing & Events Platform Development","/blog/case-study/ticketing-events-platform-case-study","blog/case-study/ticketing-events-platform-case-study",{"title":58,"path":59,"stem":60},"Turn Fans into Superfans — Roadie.co","/blog/case-study/turn-fans-into-superfans-roadie-co","blog/case-study/turn-fans-into-superfans-roadie-co",{"title":62,"path":63,"stem":64},"Walkative 2.0 Global Booking Engine","/blog/case-study/walkative-2-booking-platform-case-study","blog/case-study/walkative-2-booking-platform-case-study",{"title":66,"path":67,"stem":68},"Why Merch Is the New Royalty Check, and How Tech Is Closing the Gap","/blog/case-study/why-merch-is-the-new-royalty-check","blog/case-study/why-merch-is-the-new-royalty-check",false,{"title":71,"path":72,"stem":73,"children":74,"page":69},"Music Data","/blog/music-data","blog/music-data",[75,79,83,87,91,95,99,103,107,111,115,119,123,127,131,135,139,143,147,151,155,159,163,167,171,175,179,183,187,191,195,199,203],{"title":76,"path":77,"stem":78},"13 Distributors, 5 File Formats, Zero Standards -The Reality of Music Royalty Data","/blog/music-data/13-distributors-5-file-formats-zero-standards-the-reality-of-music-royalty-data","blog/music-data/13-distributors-5-file-formats-zero-standards-the-reality-of-music-royalty-data",{"title":80,"path":81,"stem":82},"830 Ways to Say Spotify - Normalizing Music Streaming Data","/blog/music-data/830-ways-to-say-spotify-normalizing-music-streaming-data","blog/music-data/830-ways-to-say-spotify-normalizing-music-streaming-data",{"title":84,"path":85,"stem":86},"Why Music Companies Need AI-Powered Analytics (And How We Built One)","/blog/music-data/ai-powered-analytics-dashboard-django-clickhouse-ollama","blog/music-data/ai-powered-analytics-dashboard-django-clickhouse-ollama",{"title":88,"path":89,"stem":90},"AI Rehearsal: Spaced Repetition for Your Musical Ideas","/blog/music-data/ai-rehearsal-spaced-repetition-for-musical-ideas","blog/music-data/ai-rehearsal-spaced-repetition-for-musical-ideas",{"title":92,"path":93,"stem":94},"Audio Project Organization Is a Mess — Here's Why","/blog/music-data/audio-project-organization-mess","blog/music-data/audio-project-organization-mess",{"title":96,"path":97,"stem":98},"Why Audio Search Is Still Broken and How to Fix It with Embeddings","/blog/music-data/audio-search-broken-fix-with-embeddings","blog/music-data/audio-search-broken-fix-with-embeddings",{"title":100,"path":101,"stem":102},"AI Song Structure Analysis: Intro, Verse, Chorus","/blog/music-data/automatic-song-structure-analysis-how-ai-detects-intro-verse-chorus","blog/music-data/automatic-song-structure-analysis-how-ai-detects-intro-verse-chorus",{"title":104,"path":105,"stem":106},"The Broken Feedback Loop in Music Collaboration","/blog/music-data/broken-feedback-loop-music-collaboration","blog/music-data/broken-feedback-loop-music-collaboration",{"title":108,"path":109,"stem":110},"Building a Claude Skill for DDEX Validation: Automate Music Metadata Checks with AI","/blog/music-data/building-a-claude-skill-for-ddex-validation-music-metadata","blog/music-data/building-a-claude-skill-for-ddex-validation-music-metadata",{"title":112,"path":113,"stem":114},"Building a Custom Music Delivery Platform on the Revelator API","/blog/music-data/building-a-custom-music-delivery-platform-on-the-revelator-api","blog/music-data/building-a-custom-music-delivery-platform-on-the-revelator-api",{"title":116,"path":117,"stem":118},"Building a Suno AI Remix App with Nuxt & Firebase","/blog/music-data/building-a-suno-remix-app-with-nuxt-and-firebase","blog/music-data/building-a-suno-remix-app-with-nuxt-and-firebase",{"title":120,"path":121,"stem":122},"C2PA & DDEX: Authenticity Meets Rights in the Age of AI Music","/blog/music-data/c2pa-and-ddex-authenticity-meets-rights-in-the-age-of-ai-music","blog/music-data/c2pa-and-ddex-authenticity-meets-rights-in-the-age-of-ai-music",{"title":124,"path":125,"stem":126},"C2PA in Music: A Claude MCP for Reading Content Provenance","/blog/music-data/c2pa-in-music-mcp","blog/music-data/c2pa-in-music-mcp",{"title":128,"path":129,"stem":130},"Data Modeling in MongoDB Using Design Patterns","/blog/music-data/data-modeling-in-mongodb-with-the-usage-of-design-patterns","blog/music-data/data-modeling-in-mongodb-with-the-usage-of-design-patterns",{"title":132,"path":133,"stem":134},"Office Hours with MusicTech Lab's DDEX Expert","/blog/music-data/ddex-office-hours-musictech","blog/music-data/ddex-office-hours-musictech",{"title":136,"path":137,"stem":138},"DDEX Open Source Projects Review","/blog/music-data/ddex-open-source-projects-review","blog/music-data/ddex-open-source-projects-review",{"title":140,"path":141,"stem":142},"Extracting Data from Ableton .als and .asd Files","/blog/music-data/extracting-data-from-ableton-als-asd-files","blog/music-data/extracting-data-from-ableton-als-asd-files",{"title":144,"path":145,"stem":146},"Maciej Dulski on Sound Connections Podcast","/blog/music-data/from-startups-to-musictech-maciej-dulski-on-sound-connections-podcast","blog/music-data/from-startups-to-musictech-maciej-dulski-on-sound-connections-podcast",{"title":148,"path":149,"stem":150},"How to Transcribe Video to Text Using OpenAI Whisper","/blog/music-data/how-to-transcribe-video-to-text-using-whisper","blog/music-data/how-to-transcribe-video-to-text-using-whisper",{"title":152,"path":153,"stem":154},"Epidemic Sound MCP with Claude for Devs","/blog/music-data/how-to-use-epidemic-sound-mcp-with-claude","blog/music-data/how-to-use-epidemic-sound-mcp-with-claude",{"title":156,"path":157,"stem":158},"Hybrid Database Model in Django for Speed","/blog/music-data/hybrid-database-model-in-django-as-a-performance-booster","blog/music-data/hybrid-database-model-in-django-as-a-performance-booster",{"title":160,"path":161,"stem":162},"Introduction to generating DDEX file using Python","/blog/music-data/introduction-to-generating-ddex-file-using-python","blog/music-data/introduction-to-generating-ddex-file-using-python",{"title":164,"path":165,"stem":166},"Maintaining Music Tech Tools: The SLA Dilemma for Small Teams","/blog/music-data/maintaining-music-tech-tools-the-sla-dilemma-for-small-teams","blog/music-data/maintaining-music-tech-tools-the-sla-dilemma-for-small-teams",{"title":168,"path":169,"stem":170},"Querying Bandcamp Revenue Reports with Natural Language — Meet mtl-bandcamp-mcp","/blog/music-data/mtl-bandcamp-mcp-open-source-revenue-dashboard","blog/music-data/mtl-bandcamp-mcp-open-source-revenue-dashboard",{"title":172,"path":173,"stem":174},"mtl-metadata-mcp: Open Source Audio Metadata Embedding for Claude Code","/blog/music-data/mtl-metadata-mcp-open-source-audio-metadata-embedding","blog/music-data/mtl-metadata-mcp-open-source-audio-metadata-embedding",{"title":176,"path":177,"stem":178},"MusicTech Resources for Builders","/blog/music-data/musictech-resources-curated-insights-for-the-musictech-builders","blog/music-data/musictech-resources-curated-insights-for-the-musictech-builders",{"title":180,"path":181,"stem":182},"Poland's Creative Tech and MusicTech Rise","/blog/music-data/polands-creative-tech-sector-is-on-the-rise-and-musictech-is-part-of-it","blog/music-data/polands-creative-tech-sector-is-on-the-rise-and-musictech-is-part-of-it",{"title":184,"path":185,"stem":186},"Batch ISRC Enrichment That Turns Messy Catalogs Into Clean Data","/blog/music-data/scout-isrc-metadata-enrichment-spotify-musicbrainz","blog/music-data/scout-isrc-metadata-enrichment-spotify-musicbrainz",{"title":188,"path":189,"stem":190},"Music Self-Publishing: The Emuze.me Story","/blog/music-data/self-publishing-in-the-music-industry-a-tale-of-emuze-me","blog/music-data/self-publishing-in-the-music-industry-a-tale-of-emuze-me",{"title":192,"path":193,"stem":194},"Understanding the API First Approach","/blog/music-data/understanding-the-api-first-approach","blog/music-data/understanding-the-api-first-approach",{"title":196,"path":197,"stem":198},"The Voice Memo Graveyard Problem","/blog/music-data/voice-memo-graveyard-problem","blog/music-data/voice-memo-graveyard-problem",{"title":200,"path":201,"stem":202},"Which Database for Music Data? Redshift vs BigQuery vs ClickHouse and When to Use Each","/blog/music-data/which-database-for-music-data-redshift-vs-bigquery-vs-clickhouse","blog/music-data/which-database-for-music-data-redshift-vs-bigquery-vs-clickhouse",{"title":204,"path":205,"stem":206},"Why we decided to use wavesurfer.js","/blog/music-data/why-we-decided-to-use-wavesurfer","blog/music-data/why-we-decided-to-use-wavesurfer",{"title":208,"path":209,"stem":210,"children":211,"page":69},"Newsletter","/blog/newsletter","blog/newsletter",[212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,304,308],{"title":213,"path":214,"stem":215},"Music Industry Tech Openings (April 2024 Update)","/blog/newsletter/music-industry-tech-openings-april-2024-update","blog/newsletter/music-industry-tech-openings-april-2024-update",{"title":217,"path":218,"stem":219},"Music Industry Tech Openings (April 2025 Update)","/blog/newsletter/music-industry-tech-openings-april-2025-update","blog/newsletter/music-industry-tech-openings-april-2025-update",{"title":221,"path":222,"stem":223},"Music Industry Tech Openings (August 2024 Update)","/blog/newsletter/music-industry-tech-openings-august-2024-update","blog/newsletter/music-industry-tech-openings-august-2024-update",{"title":225,"path":226,"stem":227},"Music Industry Tech Openings (December 2024 Update)","/blog/newsletter/music-industry-tech-openings-december-2024-update","blog/newsletter/music-industry-tech-openings-december-2024-update",{"title":229,"path":230,"stem":231},"Music Industry Tech Openings (February 2025 Update)","/blog/newsletter/music-industry-tech-openings-february-2025-update","blog/newsletter/music-industry-tech-openings-february-2025-update",{"title":233,"path":234,"stem":235},"Music Industry Tech Openings (January 2025 Update)","/blog/newsletter/music-industry-tech-openings-january-2025-update","blog/newsletter/music-industry-tech-openings-january-2025-update",{"title":237,"path":238,"stem":239},"Music Industry Tech Openings (July 2024 Update)","/blog/newsletter/music-industry-tech-openings-july-2024-update","blog/newsletter/music-industry-tech-openings-july-2024-update",{"title":241,"path":242,"stem":243},"Music Industry Tech Openings (June 2024 Update)","/blog/newsletter/music-industry-tech-openings-june-2024-update","blog/newsletter/music-industry-tech-openings-june-2024-update",{"title":245,"path":246,"stem":247},"Music Industry Tech Openings (March 2025 Update)","/blog/newsletter/music-industry-tech-openings-march-2025-update","blog/newsletter/music-industry-tech-openings-march-2025-update",{"title":249,"path":250,"stem":251},"Music Industry Tech Openings (May 2024 Update)","/blog/newsletter/music-industry-tech-openings-may-2024-update","blog/newsletter/music-industry-tech-openings-may-2024-update",{"title":253,"path":254,"stem":255},"Music Industry Tech Openings (May 2025 Update)","/blog/newsletter/music-industry-tech-openings-may-2025","blog/newsletter/music-industry-tech-openings-may-2025",{"title":257,"path":258,"stem":259},"Music Industry Tech Openings (November 2024 Update)","/blog/newsletter/music-industry-tech-openings-november-2024-update","blog/newsletter/music-industry-tech-openings-november-2024-update",{"title":261,"path":262,"stem":263},"Music Industry Tech Openings (October 2024 Update)","/blog/newsletter/music-industry-tech-openings-october-2024-update","blog/newsletter/music-industry-tech-openings-october-2024-update",{"title":265,"path":266,"stem":267},"Music Industry Tech Openings (September 2024 Update)","/blog/newsletter/music-industry-tech-openings-september-2024-update","blog/newsletter/music-industry-tech-openings-september-2024-update",{"title":269,"path":270,"stem":271},"MusicTech Insights #1 by Maciej Dulski","/blog/newsletter/musictech-insights-1-curated-by-maciej-dulski","blog/newsletter/musictech-insights-1-curated-by-maciej-dulski",{"title":273,"path":274,"stem":275},"Provenance, Not Detection, Is the Durable Answer","/blog/newsletter/musictech-insights-10-curated-by-jim-anderson","blog/newsletter/musictech-insights-10-curated-by-jim-anderson",{"title":277,"path":278,"stem":279},"What CMOs can teach us about innovation in uncertain times","/blog/newsletter/musictech-insights-10-curated-by-joanna-kurkowska","blog/newsletter/musictech-insights-10-curated-by-joanna-kurkowska",{"title":281,"path":282,"stem":283},"Feeling the MusicTech Momentum","/blog/newsletter/musictech-insights-2-curated-by-maciej-dulski","blog/newsletter/musictech-insights-2-curated-by-maciej-dulski",{"title":285,"path":286,"stem":287},"AI in Music: Hype, Hope, and a Human Touch","/blog/newsletter/musictech-insights-3-curated-by-drew-thurlow","blog/newsletter/musictech-insights-3-curated-by-drew-thurlow",{"title":289,"path":290,"stem":291},"The Music Metadata Conundrum","/blog/newsletter/musictech-insights-4-curated-by-amanda-schupf","blog/newsletter/musictech-insights-4-curated-by-amanda-schupf",{"title":293,"path":294,"stem":295},"7 Rounds in the First 10 Days of November 2025","/blog/newsletter/musictech-insights-5-curated-by-maciej-dulski","blog/newsletter/musictech-insights-5-curated-by-maciej-dulski",{"title":297,"path":298,"stem":299},"The End of an Era: It's All About to Crash","/blog/newsletter/musictech-insights-6-curated-by-sigurdur-arnason","blog/newsletter/musictech-insights-6-curated-by-sigurdur-arnason",{"title":301,"path":302,"stem":303},"Low-Code Magic Won't Solve MusicTech Reality","/blog/newsletter/musictech-insights-7-curated-by-mariusz-smenzyk","blog/newsletter/musictech-insights-7-curated-by-mariusz-smenzyk",{"title":305,"path":306,"stem":307},"The New Economics of Game Music","/blog/newsletter/musictech-insights-8-curated-by-kenny-vaughan","blog/newsletter/musictech-insights-8-curated-by-kenny-vaughan",{"title":309,"path":310,"stem":311},"Music Business Meets Direct-to-Fan","/blog/newsletter/musictech-insights-9-curated-by-yaw-asamani","blog/newsletter/musictech-insights-9-curated-by-yaw-asamani",{"title":313,"path":314,"stem":315,"children":316,"page":69},"Software Development","/blog/software-development","blog/software-development",[317,321,325,329,333,337,341,345,349,353,357,361,365,369,373,377,381,385,389,393,397,401,405,409,413,417,421,425,429,433,437,441,445,449,453,457,461,465,469,473,477,481,485,489,493,497,501,505,509,513,517,521,525,529,533,537,541,545,549,553,557,561,565,569,573,577,581,585,589,593,597,601,605,609,613,617,621,625,629,633,637,641,645,649,653,657,661,665,669,673,677,681,685,689,693,697,701,705,709,713,717],{"title":318,"path":319,"stem":320},"Benefits of Outsourcing Software Development","/blog/software-development/10-benefits-of-outsourcing-software-development-services","blog/software-development/10-benefits-of-outsourcing-software-development-services",{"title":322,"path":323,"stem":324},"10 Steps to Find the Best MVP Developers","/blog/software-development/10-steps-to-find-the-best-mvp-developers-for-your-startup-idea","blog/software-development/10-steps-to-find-the-best-mvp-developers-for-your-startup-idea",{"title":326,"path":327,"stem":328},"1,200 Looms Later: How Async Video Became My Development Superpower","/blog/software-development/1200-looms-how-async-video-became-our-development-superpower","blog/software-development/1200-looms-how-async-video-became-our-development-superpower",{"title":330,"path":331,"stem":332},"Communication Strategy in Outsourcing Projects","/blog/software-development/5-steps-to-implement-an-effective-communication-strategy-in-outsourcing-software-development-project","blog/software-development/5-steps-to-implement-an-effective-communication-strategy-in-outsourcing-software-development-project",{"title":334,"path":335,"stem":336},"7 Best Practices for Outsourcing Software Development","/blog/software-development/7-best-practices-for-outsourcing-software-development","blog/software-development/7-best-practices-for-outsourcing-software-development",{"title":338,"path":339,"stem":340},"9 Reasons Why Saleor.io Is Best for eCommerce","/blog/software-development/9-reasons-why-the-saleor-io-platform-is-the-best-choice-for-your-ecommerce-website","blog/software-development/9-reasons-why-the-saleor-io-platform-is-the-best-choice-for-your-ecommerce-website",{"title":342,"path":343,"stem":344},"A Look at Bravelab.io’s Clutch 2021 Year In Review","/blog/software-development/a-look-at-bravelab-ios-clutch-2021-year-in-review","blog/software-development/a-look-at-bravelab-ios-clutch-2021-year-in-review",{"title":346,"path":347,"stem":348},"A quick introduction to profit sharing implementation","/blog/software-development/a-quick-introduction-to-profit-sharing-implementation","blog/software-development/a-quick-introduction-to-profit-sharing-implementation",{"title":350,"path":351,"stem":352},"AI Audio Similarity Search: The Future of Sound Library Discovery","/blog/software-development/ai-audio-similarity-search-for-sound-libraries","blog/software-development/ai-audio-similarity-search-for-sound-libraries",{"title":354,"path":355,"stem":356},"Automate Repetitive Tasks for Better Results","/blog/software-development/automate-repetitive-tasks-to-improve-your-business-performance","blog/software-development/automate-repetitive-tasks-to-improve-your-business-performance",{"title":358,"path":359,"stem":360},"Automating Success: The Art of Unified Documentation","/blog/software-development/automating-success-the-art-of-unified-documentation","blog/software-development/automating-success-the-art-of-unified-documentation",{"title":362,"path":363,"stem":364},"Brave 3.0 Website Redesign, Part 2: Solution","/blog/software-development/brave-3-0-how-we-conducted-website-redesign-part-2-solution","blog/software-development/brave-3-0-how-we-conducted-website-redesign-part-2-solution",{"title":366,"path":367,"stem":368},"Brave 3.0, Part 4: Tech Stack and Recap","/blog/software-development/brave-3-0-part-4-technologies-behind-and-final-series-recap","blog/software-development/brave-3-0-part-4-technologies-behind-and-final-series-recap",{"title":370,"path":371,"stem":372},"Brave 3.0 – redesign process part 1. The Challenge","/blog/software-development/brave-3-0-redesign-process-part-1-challenge","blog/software-development/brave-3-0-redesign-process-part-1-challenge",{"title":374,"path":375,"stem":376},"Brave 3.0 – redesign process, part 3. Lesson learned","/blog/software-development/brave-3-0-redesign-process-part-3-lesson-learned","blog/software-development/brave-3-0-redesign-process-part-3-lesson-learned",{"title":378,"path":379,"stem":380},"Bravelab.io: Top Software Developer by Clutch","/blog/software-development/bravelab-io-is-recognized-as-a-top-custom-software-developer-by-clutch","blog/software-development/bravelab-io-is-recognized-as-a-top-custom-software-developer-by-clutch",{"title":382,"path":383,"stem":384},"Bravelab.io: Top Developer in Poland by Clutch","/blog/software-development/bravelab-io-named-top-software-developer-in-poland-by-clutch","blog/software-development/bravelab-io-named-top-software-developer-in-poland-by-clutch",{"title":386,"path":387,"stem":388},"MusicTech Lab Partners with LALAL.AI","/blog/software-development/bravelab-partners-with-the-audio-lalal-ai","blog/software-development/bravelab-partners-with-the-audio-lalal-ai",{"title":390,"path":391,"stem":392},"MusicTech Lab Partners with The Audio Programmer","/blog/software-development/bravelab-partners-with-the-audio-programmer","blog/software-development/bravelab-partners-with-the-audio-programmer",{"title":394,"path":395,"stem":396},"Bravelab's team about productivity","/blog/software-development/bravelabs-team-about-productivity","blog/software-development/bravelabs-team-about-productivity",{"title":398,"path":399,"stem":400},"Braveloper","/blog/software-development/braveloper","blog/software-development/braveloper",{"title":402,"path":403,"stem":404},"Bravely App: Boost Productivity with Django","/blog/software-development/bravely-app-how-to-be-more-productive-with-django-quick","blog/software-development/bravely-app-how-to-be-more-productive-with-django-quick",{"title":406,"path":407,"stem":408},"DIY MIDI Controller for Ableton with Arduino","/blog/software-development/building-a-diy-midi-controller-for-ableton-live-with-arduino","blog/software-development/building-a-diy-midi-controller-for-ableton-live-with-arduino",{"title":410,"path":411,"stem":412},"C2PA in Ableton: Making AI Music Provenance Visible Inside Your DAW","/blog/software-development/c2pa-in-ableton-max-for-live","blog/software-development/c2pa-in-ableton-max-for-live",{"title":414,"path":415,"stem":416},"Change Detection mechanism in Angular","/blog/software-development/change-detection-mechanism-in-angular","blog/software-development/change-detection-mechanism-in-angular",{"title":418,"path":419,"stem":420},"Communication Channels in Remote Work","/blog/software-development/comparison-of-the-communication-channels-in-remote-work","blog/software-development/comparison-of-the-communication-channels-in-remote-work",{"title":422,"path":423,"stem":424},"Connecting Your Max for Live Device to a Cloud API","/blog/software-development/connecting-your-max-for-live-device-to-a-cloud-api","blog/software-development/connecting-your-max-for-live-device-to-a-cloud-api",{"title":426,"path":427,"stem":428},"From Voice Memo to Studio: The Cross-Platform Problem for Creators","/blog/software-development/cross-platform-problem-for-creators","blog/software-development/cross-platform-problem-for-creators",{"title":430,"path":431,"stem":432},"Cultural transformation through the pandemic era","/blog/software-development/cultural-transformation-through-the-pandemic-era","blog/software-development/cultural-transformation-through-the-pandemic-era",{"title":434,"path":435,"stem":436},"D-Commerce Decoded: Cutting Through the Hype","/blog/software-development/d-commerce-decoded-cutting-through-the-hype","blog/software-development/d-commerce-decoded-cutting-through-the-hype",{"title":438,"path":439,"stem":440},"Dev Meeting 002: Intro to DDD","/blog/software-development/dev-meeting-002-introduction-to-domain-driven-design-ddd","blog/software-development/dev-meeting-002-introduction-to-domain-driven-design-ddd",{"title":442,"path":443,"stem":444},"Dev Meeting 003: Web3 Primer","/blog/software-development/dev-meeting-003-web3-primer","blog/software-development/dev-meeting-003-web3-primer",{"title":446,"path":447,"stem":448},"Dev Meeting 004: Introduction to Event Storming","/blog/software-development/dev-meeting-004-introduction-to-event-storming","blog/software-development/dev-meeting-004-introduction-to-event-storming",{"title":450,"path":451,"stem":452},"Dev Meeting 001: Kubernetes is a Framework","/blog/software-development/dev-meeting-kubernetes-is-a-framework","blog/software-development/dev-meeting-kubernetes-is-a-framework",{"title":454,"path":455,"stem":456},"Did You Know? 10 Developer Tips from Real Codebases","/blog/software-development/did-you-know-dev-tips-part-1","blog/software-development/did-you-know-dev-tips-part-1",{"title":458,"path":459,"stem":460},"10 Surprising MusicTech Facts (Part 2)","/blog/software-development/did-you-know-musictech-facts-part-2","blog/software-development/did-you-know-musictech-facts-part-2",{"title":462,"path":463,"stem":464},"Django-cms and GraphQL","/blog/software-development/django-cms-and-graphql","blog/software-development/django-cms-and-graphql",{"title":466,"path":467,"stem":468},"Does Zappa make it super easy?","/blog/software-development/does-zappa-make-it-super-easy","blog/software-development/does-zappa-make-it-super-easy",{"title":470,"path":471,"stem":472},"Establishing cooperation between Netlify and Bravelab","/blog/software-development/establishing-cooperation-between-netlify-and-bravelab","blog/software-development/establishing-cooperation-between-netlify-and-bravelab",{"title":474,"path":475,"stem":476},"Export Ableton Locators to JSON via Max for Live","/blog/software-development/exporting-ableton-live-locators-to-json-with-max-for-live","blog/software-development/exporting-ableton-live-locators-to-json-with-max-for-live",{"title":478,"path":479,"stem":480},"IT Outsourcing: Success and Failure Factors","/blog/software-development/factors-that-contribute-to-the-success-or-failure-of-an-it-outsourcing-project","blog/software-development/factors-that-contribute-to-the-success-or-failure-of-an-it-outsourcing-project",{"title":482,"path":483,"stem":484},"Flutter 2022 Strategy: Analyzing the Roadmap","/blog/software-development/flutter-strategy-for-2022-analyzing-the-new-flutter-roadmap","blog/software-development/flutter-strategy-for-2022-analyzing-the-new-flutter-roadmap",{"title":486,"path":487,"stem":488},"Git Better #1 — Commit Message Convention","/blog/software-development/git-better-1-see-more-with-a-commit-message-convention","blog/software-development/git-better-1-see-more-with-a-commit-message-convention",{"title":490,"path":491,"stem":492},"Hasura in action. How to use it with Django","/blog/software-development/hasura-in-action","blog/software-development/hasura-in-action",{"title":494,"path":495,"stem":496},"Holacracy why and where we are","/blog/software-development/holacracy-why-and-where-we-are","blog/software-development/holacracy-why-and-where-we-are",{"title":498,"path":499,"stem":500},"How does JavaScript work","/blog/software-development/how-does-javascript-work","blog/software-development/how-does-javascript-work",{"title":502,"path":503,"stem":504},"How important is good UX/UI design?","/blog/software-development/how-important-is-good-ux-ui-design","blog/software-development/how-important-is-good-ux-ui-design",{"title":506,"path":507,"stem":508},"How repetitive tasks impact your business","/blog/software-development/how-repetitive-tasks-impact-your-business","blog/software-development/how-repetitive-tasks-impact-your-business",{"title":510,"path":511,"stem":512},"Becoming a Vue.js Dev: Do Paid Trials Work?","/blog/software-development/how-to-become-a-vue-js-developer-and-whether-paid-trials-in-it-work-out","blog/software-development/how-to-become-a-vue-js-developer-and-whether-paid-trials-in-it-work-out",{"title":514,"path":515,"stem":516},"How to Build an MVP in 6 Steps","/blog/software-development/how-to-build-a-minimum-viable-product-mvp-in-6-steps","blog/software-development/how-to-build-a-minimum-viable-product-mvp-in-6-steps",{"title":518,"path":519,"stem":520},"How to conduct workshops for creative industry?","/blog/software-development/how-to-conduct-workshops-for-creative-industry","blog/software-development/how-to-conduct-workshops-for-creative-industry",{"title":522,"path":523,"stem":524},"How to easily create form in Angular","/blog/software-development/how-to-easily-create-form-in-angular","blog/software-development/how-to-easily-create-form-in-angular",{"title":526,"path":527,"stem":528},"How to export orders in Saleor.io to XLSX file","/blog/software-development/how-to-export-orders-in-saleor-io-to-xlsx-file","blog/software-development/how-to-export-orders-in-saleor-io-to-xlsx-file",{"title":530,"path":531,"stem":532},"Handling High Loads on E-Commerce Platforms","/blog/software-development/how-to-handle-high-loads-on-e-commerce-platform-with-ease","blog/software-development/how-to-handle-high-loads-on-e-commerce-platform-with-ease",{"title":534,"path":535,"stem":536},"How to launch Saleor.io shop instance within 40h","/blog/software-development/how-to-launch-saleor-io-shop-instance-within-40h","blog/software-development/how-to-launch-saleor-io-shop-instance-within-40h",{"title":538,"path":539,"stem":540},"First Steps to Build a Business Relationship","/blog/software-development/how-to-make-the-first-step-to-establish-a-business-relationship","blog/software-development/how-to-make-the-first-step-to-establish-a-business-relationship",{"title":542,"path":543,"stem":544},"Multi-Tenant Apps with Django and Saleor.io","/blog/software-development/how-to-manage-tenants-in-the-multitenant-app-based-on-django-tenants-and-saleor-io-platform","blog/software-development/how-to-manage-tenants-in-the-multitenant-app-based-on-django-tenants-and-saleor-io-platform",{"title":546,"path":547,"stem":548},"Notion Backup Tool Built in 3 Days with Python","/blog/software-development/how-we-built-a-notion-backup-tool-in-3-days-with-pythonvue-and-why","blog/software-development/how-we-built-a-notion-backup-tool-in-3-days-with-pythonvue-and-why",{"title":550,"path":551,"stem":552},"Important new features in Python 3.8","/blog/software-development/important-new-features-in-python-3-8","blog/software-development/important-new-features-in-python-3-8",{"title":554,"path":555,"stem":556},"Installing Proxmox on dedicated server from OVH","/blog/software-development/installing-proxmox-on-dedicated-server-from-ovh","blog/software-development/installing-proxmox-on-dedicated-server-from-ovh",{"title":558,"path":559,"stem":560},"Integrating SignNow E-Signatures into Your Django Application","/blog/software-development/integrating-signnow-e-signatures-into-your-django-application","blog/software-development/integrating-signnow-e-signatures-into-your-django-application",{"title":562,"path":563,"stem":564},"Tempus Metronome and GetSongBPM API","/blog/software-development/integrating-tempus-metronome-with-the-getsongbpm-api-what-bpm-really-means-and-how-to-use-it","blog/software-development/integrating-tempus-metronome-with-the-getsongbpm-api-what-bpm-really-means-and-how-to-use-it",{"title":566,"path":567,"stem":568},"Introducing MusicTech Poland","/blog/software-development/introducing-musictech-poland","blog/software-development/introducing-musictech-poland",{"title":570,"path":571,"stem":572},"Vue.js as a Frontend for Saleor.io","/blog/software-development/is-it-possible-to-use-vue-js-as-a-frontend-for-saleor-io-platform","blog/software-development/is-it-possible-to-use-vue-js-as-a-frontend-for-saleor-io-platform",{"title":574,"path":575,"stem":576},"Is your business ready for the cashless era?","/blog/software-development/is-your-business-ready-for-the-cashless-era","blog/software-development/is-your-business-ready-for-the-cashless-era",{"title":578,"path":579,"stem":580},"Is your face ready to buy?","/blog/software-development/is-your-face-ready-to-buy","blog/software-development/is-your-face-ready-to-buy",{"title":582,"path":583,"stem":584},"JS Frameworks: Trends and Opportunities","/blog/software-development/javascript-trending-frameworks-and-market-opportunities","blog/software-development/javascript-trending-frameworks-and-market-opportunities",{"title":586,"path":587,"stem":588},"Kanban Board: Boost Your Team Productivity","/blog/software-development/kanban-board-methodology-hack-your-companys-productivity","blog/software-development/kanban-board-methodology-hack-your-companys-productivity",{"title":590,"path":591,"stem":592},"Verified Human Cert MCP Server: Prove Your Music Is Human-Made, Right from the Terminal","/blog/software-development/mcp-verified-human-cert-open-source","blog/software-development/mcp-verified-human-cert-open-source",{"title":594,"path":595,"stem":596},"Migrating from TravisCI to Github Actions","/blog/software-development/migrating-from-travisci-to-github-actions","blog/software-development/migrating-from-travisci-to-github-actions",{"title":598,"path":599,"stem":600},"MusicTech Lab: Top Software Developer by Clutch","/blog/software-development/musictechlab-is-recognized-as-a-top-custom-software-developer-by-clutch","blog/software-development/musictechlab-is-recognized-as-a-top-custom-software-developer-by-clutch",{"title":602,"path":603,"stem":604},"MusicTech Lab x Verified Human: Building a Trust Layer for Human-Made Music","/blog/software-development/musictechlab_blog_verified_human_partnership","blog/software-development/musictechlab_blog_verified_human_partnership",{"title":606,"path":607,"stem":608},"MusicXML: Standard for Music Notation","/blog/software-development/musicxml-standard-for-music-notation-and-education","blog/software-development/musicxml-standard-for-music-notation-and-education",{"title":610,"path":611,"stem":612},"Only a few books but dozens of ideas","/blog/software-development/only-a-few-books-but-dozens-of-ideas","blog/software-development/only-a-few-books-but-dozens-of-ideas",{"title":614,"path":615,"stem":616},"Overdue Invoices and Issue Tracker Integration","/blog/software-development/overdue-invoices-integration-with-the-issue-tracking-system","blog/software-development/overdue-invoices-integration-with-the-issue-tracking-system",{"title":618,"path":619,"stem":620},"Performing SAML SSO using JWT in Django","/blog/software-development/performing-saml-sso-using-jwt-in-django","blog/software-development/performing-saml-sso-using-jwt-in-django",{"title":622,"path":623,"stem":624},"Progressive Web Apps for Mobile Development","/blog/software-development/progressive-web-apps-a-new-way-of-creating-mobile-application","blog/software-development/progressive-web-apps-a-new-way-of-creating-mobile-application",{"title":626,"path":627,"stem":628},"Recruitment System: Gmail, Jira, and CRM","/blog/software-development/recruitment-system-integrating-gmail-bravely-jira-slack-and-copper-crm","blog/software-development/recruitment-system-integrating-gmail-bravely-jira-slack-and-copper-crm",{"title":630,"path":631,"stem":632},"Scratch Me: Chrome Extension for Leads","/blog/software-development/scratch-me-a-simple-chrome-extension-which-will-increase-your-productivity","blog/software-development/scratch-me-a-simple-chrome-extension-which-will-increase-your-productivity",{"title":634,"path":635,"stem":636},"Scratch Me – integration with the Copper CRM","/blog/software-development/scratch-me-integration-with-the-copper-crm","blog/software-development/scratch-me-integration-with-the-copper-crm",{"title":638,"path":639,"stem":640},"SignNow MCP Server: E-Signatures Straight from Claude Code","/blog/software-development/signnow-mcp-server-e-signatures-from-claude-code","blog/software-development/signnow-mcp-server-e-signatures-from-claude-code",{"title":642,"path":643,"stem":644},"Music Industry Tech Openings (March 2024 Update)","/blog/software-development/technical-job-opportunities-in-the-music-industry","blog/software-development/technical-job-opportunities-in-the-music-industry",{"title":646,"path":647,"stem":648},"Thanks app – a Management 3.0 solution","/blog/software-development/thanks-app-a-management-3-0-solution","blog/software-development/thanks-app-a-management-3-0-solution",{"title":650,"path":651,"stem":652},"Colonial Pipeline Case: 7 Security Reminders","/blog/software-development/the-case-of-colonial-pipeline-and-7-security-reminders","blog/software-development/the-case-of-colonial-pipeline-and-7-security-reminders",{"title":654,"path":655,"stem":656},"The Evolution and Future of E-commerce Platforms","/blog/software-development/the-evolution-and-future-of-e-commerce-platforms","blog/software-development/the-evolution-and-future-of-e-commerce-platforms",{"title":658,"path":659,"stem":660},"The Gender Gap in the Tech Industry","/blog/software-development/the-gender-gap-in-the-tech-industry","blog/software-development/the-gender-gap-in-the-tech-industry",{"title":662,"path":663,"stem":664},"First Attempt to Implement 4DX at Bravelab.io","/blog/software-development/the-very-first-attempt-to-implement-4dx-in-bravelab-io","blog/software-development/the-very-first-attempt-to-implement-4dx-in-bravelab-io",{"title":666,"path":667,"stem":668},"The WTF Scale: IT Project Complexity","/blog/software-development/the-wtf-programming-scale-measuring-it-project-complexity","blog/software-development/the-wtf-programming-scale-measuring-it-project-complexity",{"title":670,"path":671,"stem":672},"Top 10 articles through the eyes of our developers","/blog/software-development/top-10-articles-through-the-eyes-of-our-developers","blog/software-development/top-10-articles-through-the-eyes-of-our-developers",{"title":674,"path":675,"stem":676},"Top 6 apps made with Flutter","/blog/software-development/top-6-apps-made-with-flutter","blog/software-development/top-6-apps-made-with-flutter",{"title":678,"path":679,"stem":680},"Uber 101: How Uber Made It to the Top","/blog/software-development/uber-101-how-this-ride-sharing-behemoth-made-it-to-the-top","blog/software-development/uber-101-how-this-ride-sharing-behemoth-made-it-to-the-top",{"title":682,"path":683,"stem":684},"MusicTech Lab Partners with Music Glue","/blog/software-development/unifying-artists-and-audiences-exploring-music-glue","blog/software-development/unifying-artists-and-audiences-exploring-music-glue",{"title":686,"path":687,"stem":688},"Why AI Will Defeat Traditional HR","/blog/software-development/warning-why-artificial-intelligence-will-defeat-traditional-hr","blog/software-development/warning-why-artificial-intelligence-will-defeat-traditional-hr",{"title":690,"path":691,"stem":692},"What is a Discovery Document?","/blog/software-development/what-is-discovery-document","blog/software-development/what-is-discovery-document",{"title":694,"path":695,"stem":696},"What is Flutter, and Why is it Worth Considering?","/blog/software-development/what-is-flutter-and-why-is-it-worth-considering","blog/software-development/what-is-flutter-and-why-is-it-worth-considering",{"title":698,"path":699,"stem":700},"What is a Watermarked Song?","/blog/software-development/what-is-watermarked-song","blog/software-development/what-is-watermarked-song",{"title":702,"path":703,"stem":704},"Choosing a Frontend Framework for the Web","/blog/software-development/which-framework-should-you-choose-for-the-frontend-web-platform-development","blog/software-development/which-framework-should-you-choose-for-the-frontend-web-platform-development",{"title":706,"path":707,"stem":708},"Why DAWs Are the Wrong Tool for Starting a Song","/blog/software-development/why-daws-wrong-tool-for-starting-song","blog/software-development/why-daws-wrong-tool-for-starting-song",{"title":710,"path":711,"stem":712},"Why the Programming World Loves Python","/blog/software-development/why-the-programming-world-loves-python","blog/software-development/why-the-programming-world-loves-python",{"title":714,"path":715,"stem":716},"Why We Don't Build Chat From Scratch (And Neither Should You)","/blog/software-development/why-we-dont-build-chat-from-scratch","blog/software-development/why-we-dont-build-chat-from-scratch",{"title":718,"path":719,"stem":720},"Why we use Sanity.io","/blog/software-development/why-we-use-sanity-io","blog/software-development/why-we-use-sanity-io",{"title":722,"path":723,"stem":724,"children":725,"page":69},"Sportstech","/blog/sportstech","blog/sportstech",[726,730],{"title":727,"path":728,"stem":729},"BeatBuddy Replay: Video Analysis App Challenges","/blog/sportstech/beatbuddy-replay-video-analysis-app-for-swimmers-flutter","blog/sportstech/beatbuddy-replay-video-analysis-app-for-swimmers-flutter",{"title":731,"path":732,"stem":733},"How to Create a Watch Face App for Garmin Watch","/blog/sportstech/how-to-create-watch-face-app-for-garmin-watch","blog/sportstech/how-to-create-watch-face-app-for-garmin-watch",{"id":735,"title":698,"authors":736,"badge":742,"body":743,"category":951,"client":742,"date":952,"description":953,"extension":954,"faq":742,"featured":69,"featuredOrder":742,"hidden":69,"image":955,"keyTakeaways":957,"meta":969,"navigation":958,"path":699,"seo":970,"status":742,"stem":700,"tags":971,"teaser":742,"__hash__":974},"posts/blog/software-development/what-is-watermarked-song.md",[737],{"name":738,"to":739,"avatar":740},"Mariusz Smenżyk","https://www.linkedin.com/in/mariusz-smenzyk/",{"src":741},"/images/people/mariusz-smenzyk2.webp",null,{"type":744,"value":745,"toc":942},"minimark",[746,750,758,763,789,793,796,818,821,832,836,863,877,881,884,920,935,939],[747,748,749],"p",{},"A watermarked song contains a hidden, inaudible signal embedded in the audio data. This signal acts as a digital fingerprint — it identifies the track, its owner, and sometimes the specific recipient who received the file. The watermark is designed to survive common transformations like compression, format conversion, and even re-recording.",[747,751,752,753,757],{},"Unlike visible watermarks on images, audio watermarks are ",[754,755,756],"strong",{},"imperceptible to the listener",". The audio quality stays intact, but specialized software can detect and decode the embedded data when needed.",[759,760,762],"h2",{"id":761},"why-watermarks-matter","Why Watermarks Matter",[764,765,772,777,781,785],"div",{"className":766},[767,768,769,770,771],"grid","grid-cols-1","md:grid-cols-2","gap-4","my-8",[773,774],"spotlight-card",{"description":775,"title":776},"Labels, artists, and publishers embed watermarks to deter unauthorized distribution. If a track leaks, the watermark traces it back to the source.","Copyright Protection",[773,778],{"description":779,"title":780},"When music is licensed for films, ads, or TV shows, watermarks ensure the right rights holders get compensated. They act as proof of origin.","Ownership & Licensing",[773,782],{"description":783,"title":784},"If a watermarked pre-release track appears on piracy sites, the embedded data identifies exactly who received that copy — narrowing down the leak.","Anti-Piracy",[773,786],{"description":787,"title":788},"Streaming platforms and content distributors scan uploaded files for watermarks to detect copyright infringement and enforce licensing agreements automatically.","Monitoring & Detection",[759,790,792],{"id":791},"how-audio-watermarking-works","How Audio Watermarking Works",[747,794,795],{},"The basic process involves embedding a signal into the audio that is:",[797,798,799,806,812],"ol",{},[800,801,802,805],"li",{},[754,803,804],{},"Inaudible"," — the listener can't tell the difference between a watermarked and unwatermarked version",[800,807,808,811],{},[754,809,810],{},"Robust"," — the signal survives MP3 compression, re-encoding, cropping, and even analog re-recording",[800,813,814,817],{},[754,815,816],{},"Detectable"," — specialized software can extract the watermark and read its payload (owner ID, timestamp, recipient)",[747,819,820],{},"There are two main approaches:",[764,822,824,828],{"className":823},[767,768,769,770,771],[773,825],{"description":826,"title":827},"The watermark is spread across the audio spectrum, making it nearly impossible to remove without destroying the audio quality. Used by most commercial systems.","Spread Spectrum",[773,829],{"description":830,"title":831},"The watermark is hidden in parts of the audio that the human ear can't perceive — exploiting the same principles that make MP3 compression work.","Psychoacoustic Masking",[759,833,835],{"id":834},"real-world-use-cases","Real-World Use Cases",[837,838,839,845,851,857],"ul",{},[800,840,841,844],{},[754,842,843],{},"Pre-release distribution"," — labels send watermarked copies to press and radio. Each copy has a unique watermark tied to the recipient. If the track leaks before release, the source is identified within minutes.",[800,846,847,850],{},[754,848,849],{},"Sync licensing"," — when a song is placed in a commercial or film, the watermark confirms which version was used and who holds the rights.",[800,852,853,856],{},[754,854,855],{},"Streaming royalties"," — some platforms use fingerprinting (a related technology) alongside watermarks to match plays to rights holders and calculate royalties accurately.",[800,858,859,862],{},[754,860,861],{},"Content ID systems"," — platforms like YouTube use audio fingerprinting to detect copyrighted content in user uploads and route revenue to the correct rights holders.",[864,865,866],"note",{},[747,867,868,869,872,873,876],{},"Audio watermarking and audio fingerprinting are related but different. Watermarking ",[754,870,871],{},"embeds"," data into the audio file. Fingerprinting ",[754,874,875],{},"generates"," a unique signature from the audio for matching purposes. Both are used in modern music rights management.",[759,878,880],{"id":879},"tools-and-services","Tools and Services",[747,882,883],{},"Several companies provide commercial audio watermarking solutions:",[837,885,886,896,904,912],{},[800,887,888,895],{},[889,890,894],"a",{"href":891,"rel":892},"https://www.digimarc.com/",[893],"nofollow","Digimarc"," — enterprise-grade watermarking for audio and other media",[800,897,898,903],{},[889,899,902],{"href":900,"rel":901},"https://www.audiblemagic.com/",[893],"Audible Magic"," — content identification and compliance",[800,905,906,911],{},[889,907,910],{"href":908,"rel":909},"https://www.kantar.com/",[893],"Civolution (now part of Kantar)"," — broadcast monitoring with audio watermarks",[800,913,914,919],{},[889,915,918],{"href":916,"rel":917},"https://www.bmat.com/",[893],"BMAT"," — music monitoring and identification used by collecting societies worldwide",[747,921,922,923,928,929,934],{},"For open-source experimentation, Python libraries like ",[889,924,927],{"href":925,"rel":926},"https://github.com/jiaaro/pydub",[893],"pydub"," and ",[889,930,933],{"href":931,"rel":932},"https://librosa.org/",[893],"librosa"," can be used to explore basic watermarking concepts, though production-grade watermarking requires specialized algorithms.",[759,936,938],{"id":937},"key-takeaway","Key Takeaway",[747,940,941],{},"Watermarked songs are a critical layer of protection in the digital music supply chain. They're invisible to listeners but provide traceable proof of ownership, licensing, and distribution — making them essential for anyone working in music rights, distribution, or anti-piracy.",{"title":943,"searchDepth":944,"depth":944,"links":945},"",2,[946,947,948,949,950],{"id":761,"depth":944,"text":762},{"id":791,"depth":944,"text":792},{"id":834,"depth":944,"text":835},{"id":879,"depth":944,"text":880},{"id":937,"depth":944,"text":938},"software-development","2023-09-07T00:00:00.000Z","What are watermarked songs and why do they matter? Learn how audio watermarks protect copyright, track ownership, prevent piracy, and authenticate music.","md",{"src":956},"/images/blog/musictechlab_blog_what-is-watermarked-song.webp",{"enabled":958,"items":959},true,[960,963,966],{"text":961,"icon":962},"Audio watermarks are inaudible signals that survive compression, re-encoding, and even re-recording.","i-lucide-music",{"text":964,"icon":965},"If a pre-release track leaks, the unique watermark identifies the exact recipient within minutes.","i-lucide-shield",{"text":967,"icon":968},"Spread spectrum and psychoacoustic masking are the two main watermarking techniques in use.","i-lucide-cpu",{},{"title":698,"description":953},[972,973],"musictech","music-production","5lSYUc9pqJwmtnCuasZH-PkPdCdUhMqyWZ3gnhh8JEM",[976,978],{"title":694,"path":695,"stem":696,"description":977,"children":-1},"Why Flutter is worth considering for cross-platform development. Explore its widget-based architecture, Dart foundation, and mobile, web, and desktop support.",{"title":702,"path":703,"stem":704,"description":979,"children":-1},"Comparing React, Angular, and Vue for frontend web development. Learn which framework fits your project scope, team experience, and configuration needs best.",[981,1120,3855,7069],{"id":982,"title":390,"authors":983,"badge":742,"body":986,"category":951,"client":742,"date":1101,"description":1102,"extension":954,"faq":742,"featured":69,"featuredOrder":742,"hidden":69,"image":1103,"keyTakeaways":1105,"meta":1115,"navigation":958,"path":391,"seo":1116,"status":742,"stem":392,"tags":1117,"teaser":742,"__hash__":1118,"score":1119},"posts/blog/software-development/bravelab-partners-with-the-audio-programmer.md",[984],{"name":738,"to":739,"avatar":985},{"src":741},{"type":744,"value":987,"toc":1097},[988,997,1001,1021,1037,1066,1070,1073,1076],[747,989,990,991,996],{},"MusicTech Lab has partnered with ",[889,992,995],{"href":993,"rel":994},"https://www.theaudioprogrammer.com/",[893],"The Audio Programmer",", the largest online community for audio development. The goal is simple: connect audio developers with real-world music tech projects, and bring deeper technical knowledge into how we build products.",[759,998,1000],{"id":999},"who-is-the-audio-programmer","Who Is The Audio Programmer?",[747,1002,1003,1010,1011,1014,1015,1020],{},[754,1004,1005],{},[889,1006,1009],{"href":1007,"rel":1008},"https://www.linkedin.com/in/joshhodge/",[893],"Joshua Hodge"," started ",[889,1012,995],{"href":993,"rel":1013},[893]," in 2017 as a ",[889,1016,1019],{"href":1017,"rel":1018},"https://www.youtube.com/theaudioprogrammer",[893],"YouTube channel",", teaching people how to build their own audio apps and plug-ins. It has since grown into a global community of over 40,000 developers, producers, and audio enthusiasts. The company, based in London, now operates across three areas:",[764,1022,1025,1029,1033],{"className":1023},[767,768,1024,770,771],"md:grid-cols-3",[773,1026],{"description":1027,"title":1028},"Tutorials, books, live meetups, and resources covering VST plugin development, DSP, [JUCE](https://juce.com/), Rust for audio, and AI in music production.","Learn",[773,1030],{"description":1031,"title":1032},"Recruitment services connecting companies with experienced audio developers and specialists.","Hire",[773,1034],{"description":1035,"title":1036},"Custom audio plugin and app development with an in-house team of audio engineers.","Create",[1038,1039,1040],"tip",{},[747,1041,1042,1043,1048,1049,1048,1054,1059,1060,1065],{},"Trusted by companies like ",[889,1044,1047],{"href":1045,"rel":1046},"https://www.ableton.com/",[893],"Ableton",", ",[889,1050,1053],{"href":1051,"rel":1052},"https://focusrite.com/",[893],"Focusrite",[889,1055,1058],{"href":1056,"rel":1057},"https://www.native-instruments.com/",[893],"Native Instruments",", and ",[889,1061,1064],{"href":1062,"rel":1063},"https://www.universalmusic.com/",[893],"Universal Music Group"," — The Audio Programmer is where audio developers go to learn, collaborate, and find work.",[759,1067,1069],{"id":1068},"what-this-partnership-means","What This Partnership Means",[747,1071,1072],{},"For MusicTech Lab, this partnership opens a direct line to the audio development world. When our clients need custom audio processing, plug-in development, or DSP expertise, we can tap into a network of specialists who live and breathe this stuff.",[747,1074,1075],{},"For The Audio Programmer community, it means access to real projects — from streaming platforms and royalty engines to music production tools. The kind of work that turns side skills into professional experience.",[764,1077,1082,1089,1093],{"className":1078},[1079,1080,1081,771],"flex","flex-wrap","gap-3",[1083,1084],"u-button",{"color":1085,"label":1086,"target":1087,"to":993,"variant":1088},"primary","Website","_blank","subtle",[1083,1090],{"color":1091,"label":1092,"target":1087,"to":1017,"variant":1088},"neutral","YouTube",[1083,1094],{"color":1091,"label":1095,"target":1087,"to":1096,"variant":1088},"Discord","https://www.theaudioprogrammer.com/discord",{"title":943,"searchDepth":944,"depth":944,"links":1098},[1099,1100],{"id":999,"depth":944,"text":1000},{"id":1068,"depth":944,"text":1069},"2024-01-22T00:00:00.000Z","MusicTech Lab partners with The Audio Programmer community to connect audio developers with real-world music tech projects and deepen collaboration in audio development.",{"src":1104},"/images/blog/musictechlab_blog_musictechlab-partners-with-the-audio-programmer.webp",{"enabled":958,"items":1106},[1107,1110,1112],{"text":1108,"icon":1109},"The Audio Programmer community has over 40,000 audio developers and producers.","i-lucide-users",{"text":1111,"icon":962},"Trusted by Ableton, Focusrite, Native Instruments, and Universal Music Group.",{"text":1113,"icon":1114},"Partnership connects audio dev specialists with real-world music tech projects.","i-lucide-handshake",{},{"title":390,"description":1102},[972,973],"RVvwwibQQQRDpssN2ytFiOYLE9yf0-nbhY9M00Lm8UM",4,{"id":1121,"title":422,"authors":1122,"badge":1125,"body":1128,"category":951,"client":742,"date":3832,"description":3833,"extension":954,"faq":742,"featured":958,"featuredOrder":1637,"hidden":69,"image":3834,"keyTakeaways":3836,"meta":3850,"navigation":958,"path":423,"seo":3851,"status":742,"stem":424,"tags":3852,"teaser":742,"__hash__":3854,"score":1423},"posts/blog/software-development/connecting-your-max-for-live-device-to-a-cloud-api.md",[1123],{"name":738,"to":739,"avatar":1124},{"src":741},{"label":1126,"color":1127},"MusicTech","#9C27B0",{"type":744,"value":1129,"toc":3796},[1130,1134,1141,1148,1168,1171,1175,1178,1238,1241,1243,1247,1260,1273,1280,1294,1299,1355,1357,1361,1364,1368,1371,1376,1688,1693,1882,1886,1897,1899,1903,1906,1910,1932,1936,1939,2463,2473,2475,2479,2486,2492,2495,2503,2509,2511,2515,2520,2901,2910,2912,2916,2919,3263,3268,3290,3292,3296,3303,3309,3313,3377,3381,3384,3394,3397,3399,3403,3407,3410,3428,3432,3435,3451,3455,3458,3474,3476,3529,3531,3535,3545,3582,3585,3587,3591,3595,3618,3622,3643,3645,3649,3652,3716,3718,3722,3725,3756,3758,3762,3776,3778,3782,3785,3792],[759,1131,1133],{"id":1132},"introduction","Introduction",[747,1135,1136,1137,1140],{},"In our ",[889,1138,1139],{"href":475},"previous article",", we built a Max for Live device that exports arrangement locators to JSON. The data stayed local - displayed in the device UI or saved to a file.",[747,1142,1143,1144,1147],{},"Now let's take it further: ",[754,1145,1146],{},"sending that data to a cloud API"," where it can be stored, visualized, and integrated with other tools.",[764,1149,1152],{"className":1150},[1079,1151],"justify-center",[764,1153,1159],{"className":1154},[1155,1156,1157,1158],"bg-neutral-800","p-4","rounded-xl","max-w-md",[747,1160,1161],{},[1162,1163],"img",{"alt":1164,"src":1165,"className":1166},"Ableton Live with Max for Live device sending data to Cloud API","/images/blog/musictechlab_blog_ableton-api-full-integration.webp",[1167],"rounded-lg",[1169,1170],"hr",{},[759,1172,1174],{"id":1173},"why-connect-to-an-api","Why Connect to an API?",[747,1176,1177],{},"Local JSON files are useful, but they have limitations:",[1179,1180,1181,1194],"table",{},[1182,1183,1184],"thead",{},[1185,1186,1187,1191],"tr",{},[1188,1189,1190],"th",{},"Local Files",[1188,1192,1193],{},"Cloud API",[1195,1196,1197,1206,1214,1222,1230],"tbody",{},[1185,1198,1199,1203],{},[1200,1201,1202],"td",{},"Manual file management",[1200,1204,1205],{},"Automatic storage",[1185,1207,1208,1211],{},[1200,1209,1210],{},"Single machine access",[1200,1212,1213],{},"Access from anywhere",[1185,1215,1216,1219],{},[1200,1217,1218],{},"No version history",[1200,1220,1221],{},"Full export history",[1185,1223,1224,1227],{},[1200,1225,1226],{},"No visualization",[1200,1228,1229],{},"Browser-based timeline view",[1185,1231,1232,1235],{},[1200,1233,1234],{},"Manual sharing",[1200,1236,1237],{},"Team collaboration",[747,1239,1240],{},"By connecting your Max for Live device to an API, every export becomes part of a searchable, visualized database.",[1169,1242],{},[759,1244,1246],{"id":1245},"architecture-overview-c4-model","Architecture Overview (C4 Model)",[747,1248,1249,1250,1255,1256,1259],{},"We use the ",[889,1251,1254],{"href":1252,"rel":1253},"https://c4model.com/",[893],"C4 model"," to document the system architecture. Here's the ",[754,1257,1258],{},"System Landscape"," showing all actors and systems:",[764,1261,1263],{"className":1262},[1079,1151],[764,1264,1266],{"className":1265},[1155,1156,1157,1158],[747,1267,1268],{},[1162,1269],{"alt":1270,"src":1271,"className":1272},"C4 System Landscape - Music Producer, Ableton Live, and Export API","/images/blog/musictechlab_blog_ableton-api-c4-landscape.webp",[1167],[747,1274,1275,1276,1279],{},"And the ",[754,1277,1278],{},"Container View"," showing internal components:",[764,1281,1283],{"className":1282},[1079,1151],[764,1284,1287],{"className":1285},[1155,1156,1157,1286],"max-w-xs",[747,1288,1289],{},[1162,1290],{"alt":1291,"src":1292,"className":1293},"C4 Container View - Max for Live Device, Export API, Database","/images/blog/musictechlab_blog_ableton-api-c4-containers.webp",[1167],[1295,1296,1298],"h3",{"id":1297},"key-components","Key Components",[1179,1300,1301,1314],{},[1182,1302,1303],{},[1185,1304,1305,1308,1311],{},[1188,1306,1307],{},"Container",[1188,1309,1310],{},"Technology",[1188,1312,1313],{},"Responsibility",[1195,1315,1316,1329,1342],{},[1185,1317,1318,1323,1326],{},[1200,1319,1320],{},[754,1321,1322],{},"Max for Live Device",[1200,1324,1325],{},"JavaScript, Node for Max",[1200,1327,1328],{},"Extracts metadata from Ableton, sends to API",[1185,1330,1331,1336,1339],{},[1200,1332,1333],{},[754,1334,1335],{},"Export API",[1200,1337,1338],{},"FastAPI, Cloud Run",[1200,1340,1341],{},"Receives, validates, stores exports",[1185,1343,1344,1349,1352],{},[1200,1345,1346],{},[754,1347,1348],{},"Database",[1200,1350,1351],{},"PostgreSQL (Cloud SQL)",[1200,1353,1354],{},"Persistent storage with JSON sections",[1169,1356],{},[759,1358,1360],{"id":1359},"the-api-receiving-ableton-exports","The API: Receiving Ableton Exports",[747,1362,1363],{},"Our API is built with FastAPI and deployed on Google Cloud Run. Here's the core endpoint:",[1295,1365,1367],{"id":1366},"post-apiabletonexports","POST /api/ableton/exports",[747,1369,1370],{},"Receives and stores project metadata from Ableton Live.",[747,1372,1373],{},[754,1374,1375],{},"Request Schema:",[1377,1378,1382],"pre",{"className":1379,"code":1380,"language":1381,"meta":943,"style":943},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"project\": \"my_track\",\n  \"bpm\": 103.34,\n  \"time_signature\": {\n    \"numerator\": 4,\n    \"denominator\": 4\n  },\n  \"downbeat_seconds\": 0,\n  \"sections\": [\n    { \"label\": \"INTRO\", \"time_seconds\": 0 },\n    { \"label\": \"VERSE\", \"time_seconds\": 16 },\n    { \"label\": \"CHORUS\", \"time_seconds\": 48 }\n  ],\n  \"exported_at\": \"2026-01-27T14:30:00Z\",\n  \"file_path\": \"/Users/producer/Music/my_track.als\"\n}\n","json",[1383,1384,1385,1394,1421,1439,1453,1472,1487,1493,1510,1525,1564,1599,1635,1641,1662,1682],"code",{"__ignoreMap":943},[1386,1387,1390],"span",{"class":1388,"line":1389},"line",1,[1386,1391,1393],{"class":1392},"sMK4o","{\n",[1386,1395,1396,1399,1403,1406,1409,1412,1416,1418],{"class":1388,"line":944},[1386,1397,1398],{"class":1392},"  \"",[1386,1400,1402],{"class":1401},"spNyl","project",[1386,1404,1405],{"class":1392},"\"",[1386,1407,1408],{"class":1392},":",[1386,1410,1411],{"class":1392}," \"",[1386,1413,1415],{"class":1414},"sfazB","my_track",[1386,1417,1405],{"class":1392},[1386,1419,1420],{"class":1392},",\n",[1386,1422,1424,1426,1429,1431,1433,1437],{"class":1388,"line":1423},3,[1386,1425,1398],{"class":1392},[1386,1427,1428],{"class":1401},"bpm",[1386,1430,1405],{"class":1392},[1386,1432,1408],{"class":1392},[1386,1434,1436],{"class":1435},"sbssI"," 103.34",[1386,1438,1420],{"class":1392},[1386,1440,1441,1443,1446,1448,1450],{"class":1388,"line":1119},[1386,1442,1398],{"class":1392},[1386,1444,1445],{"class":1401},"time_signature",[1386,1447,1405],{"class":1392},[1386,1449,1408],{"class":1392},[1386,1451,1452],{"class":1392}," {\n",[1386,1454,1456,1459,1463,1465,1467,1470],{"class":1388,"line":1455},5,[1386,1457,1458],{"class":1392},"    \"",[1386,1460,1462],{"class":1461},"sBMFI","numerator",[1386,1464,1405],{"class":1392},[1386,1466,1408],{"class":1392},[1386,1468,1469],{"class":1435}," 4",[1386,1471,1420],{"class":1392},[1386,1473,1475,1477,1480,1482,1484],{"class":1388,"line":1474},6,[1386,1476,1458],{"class":1392},[1386,1478,1479],{"class":1461},"denominator",[1386,1481,1405],{"class":1392},[1386,1483,1408],{"class":1392},[1386,1485,1486],{"class":1435}," 4\n",[1386,1488,1490],{"class":1388,"line":1489},7,[1386,1491,1492],{"class":1392},"  },\n",[1386,1494,1496,1498,1501,1503,1505,1508],{"class":1388,"line":1495},8,[1386,1497,1398],{"class":1392},[1386,1499,1500],{"class":1401},"downbeat_seconds",[1386,1502,1405],{"class":1392},[1386,1504,1408],{"class":1392},[1386,1506,1507],{"class":1435}," 0",[1386,1509,1420],{"class":1392},[1386,1511,1513,1515,1518,1520,1522],{"class":1388,"line":1512},9,[1386,1514,1398],{"class":1392},[1386,1516,1517],{"class":1401},"sections",[1386,1519,1405],{"class":1392},[1386,1521,1408],{"class":1392},[1386,1523,1524],{"class":1392}," [\n",[1386,1526,1528,1531,1533,1536,1538,1540,1542,1545,1547,1550,1552,1555,1557,1559,1561],{"class":1388,"line":1527},10,[1386,1529,1530],{"class":1392},"    {",[1386,1532,1411],{"class":1392},[1386,1534,1535],{"class":1461},"label",[1386,1537,1405],{"class":1392},[1386,1539,1408],{"class":1392},[1386,1541,1411],{"class":1392},[1386,1543,1544],{"class":1414},"INTRO",[1386,1546,1405],{"class":1392},[1386,1548,1549],{"class":1392},",",[1386,1551,1411],{"class":1392},[1386,1553,1554],{"class":1461},"time_seconds",[1386,1556,1405],{"class":1392},[1386,1558,1408],{"class":1392},[1386,1560,1507],{"class":1435},[1386,1562,1563],{"class":1392}," },\n",[1386,1565,1567,1569,1571,1573,1575,1577,1579,1582,1584,1586,1588,1590,1592,1594,1597],{"class":1388,"line":1566},11,[1386,1568,1530],{"class":1392},[1386,1570,1411],{"class":1392},[1386,1572,1535],{"class":1461},[1386,1574,1405],{"class":1392},[1386,1576,1408],{"class":1392},[1386,1578,1411],{"class":1392},[1386,1580,1581],{"class":1414},"VERSE",[1386,1583,1405],{"class":1392},[1386,1585,1549],{"class":1392},[1386,1587,1411],{"class":1392},[1386,1589,1554],{"class":1461},[1386,1591,1405],{"class":1392},[1386,1593,1408],{"class":1392},[1386,1595,1596],{"class":1435}," 16",[1386,1598,1563],{"class":1392},[1386,1600,1602,1604,1606,1608,1610,1612,1614,1617,1619,1621,1623,1625,1627,1629,1632],{"class":1388,"line":1601},12,[1386,1603,1530],{"class":1392},[1386,1605,1411],{"class":1392},[1386,1607,1535],{"class":1461},[1386,1609,1405],{"class":1392},[1386,1611,1408],{"class":1392},[1386,1613,1411],{"class":1392},[1386,1615,1616],{"class":1414},"CHORUS",[1386,1618,1405],{"class":1392},[1386,1620,1549],{"class":1392},[1386,1622,1411],{"class":1392},[1386,1624,1554],{"class":1461},[1386,1626,1405],{"class":1392},[1386,1628,1408],{"class":1392},[1386,1630,1631],{"class":1435}," 48",[1386,1633,1634],{"class":1392}," }\n",[1386,1636,1638],{"class":1388,"line":1637},13,[1386,1639,1640],{"class":1392},"  ],\n",[1386,1642,1644,1646,1649,1651,1653,1655,1658,1660],{"class":1388,"line":1643},14,[1386,1645,1398],{"class":1392},[1386,1647,1648],{"class":1401},"exported_at",[1386,1650,1405],{"class":1392},[1386,1652,1408],{"class":1392},[1386,1654,1411],{"class":1392},[1386,1656,1657],{"class":1414},"2026-01-27T14:30:00Z",[1386,1659,1405],{"class":1392},[1386,1661,1420],{"class":1392},[1386,1663,1665,1667,1670,1672,1674,1676,1679],{"class":1388,"line":1664},15,[1386,1666,1398],{"class":1392},[1386,1668,1669],{"class":1401},"file_path",[1386,1671,1405],{"class":1392},[1386,1673,1408],{"class":1392},[1386,1675,1411],{"class":1392},[1386,1677,1678],{"class":1414},"/Users/producer/Music/my_track.als",[1386,1680,1681],{"class":1392},"\"\n",[1386,1683,1685],{"class":1388,"line":1684},16,[1386,1686,1687],{"class":1392},"}\n",[747,1689,1690],{},[754,1691,1692],{},"Response:",[1377,1694,1696],{"className":1379,"code":1695,"language":1381,"meta":943,"style":943},"{\n  \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"project_name\": \"my_track\",\n  \"bpm\": 103.34,\n  \"time_signature\": { \"numerator\": 4, \"denominator\": 4 },\n  \"downbeat_seconds\": 0,\n  \"sections\": [...],\n  \"exported_at\": \"2026-01-27T14:30:00Z\",\n  \"created_at\": \"2026-01-27T14:30:05Z\",\n  \"is_duplicate\": false\n}\n",[1383,1697,1698,1702,1722,1741,1755,1792,1806,1826,1844,1864,1878],{"__ignoreMap":943},[1386,1699,1700],{"class":1388,"line":1389},[1386,1701,1393],{"class":1392},[1386,1703,1704,1706,1709,1711,1713,1715,1718,1720],{"class":1388,"line":944},[1386,1705,1398],{"class":1392},[1386,1707,1708],{"class":1401},"id",[1386,1710,1405],{"class":1392},[1386,1712,1408],{"class":1392},[1386,1714,1411],{"class":1392},[1386,1716,1717],{"class":1414},"550e8400-e29b-41d4-a716-446655440000",[1386,1719,1405],{"class":1392},[1386,1721,1420],{"class":1392},[1386,1723,1724,1726,1729,1731,1733,1735,1737,1739],{"class":1388,"line":1423},[1386,1725,1398],{"class":1392},[1386,1727,1728],{"class":1401},"project_name",[1386,1730,1405],{"class":1392},[1386,1732,1408],{"class":1392},[1386,1734,1411],{"class":1392},[1386,1736,1415],{"class":1414},[1386,1738,1405],{"class":1392},[1386,1740,1420],{"class":1392},[1386,1742,1743,1745,1747,1749,1751,1753],{"class":1388,"line":1119},[1386,1744,1398],{"class":1392},[1386,1746,1428],{"class":1401},[1386,1748,1405],{"class":1392},[1386,1750,1408],{"class":1392},[1386,1752,1436],{"class":1435},[1386,1754,1420],{"class":1392},[1386,1756,1757,1759,1761,1763,1765,1768,1770,1772,1774,1776,1778,1780,1782,1784,1786,1788,1790],{"class":1388,"line":1455},[1386,1758,1398],{"class":1392},[1386,1760,1445],{"class":1401},[1386,1762,1405],{"class":1392},[1386,1764,1408],{"class":1392},[1386,1766,1767],{"class":1392}," {",[1386,1769,1411],{"class":1392},[1386,1771,1462],{"class":1461},[1386,1773,1405],{"class":1392},[1386,1775,1408],{"class":1392},[1386,1777,1469],{"class":1435},[1386,1779,1549],{"class":1392},[1386,1781,1411],{"class":1392},[1386,1783,1479],{"class":1461},[1386,1785,1405],{"class":1392},[1386,1787,1408],{"class":1392},[1386,1789,1469],{"class":1435},[1386,1791,1563],{"class":1392},[1386,1793,1794,1796,1798,1800,1802,1804],{"class":1388,"line":1474},[1386,1795,1398],{"class":1392},[1386,1797,1500],{"class":1401},[1386,1799,1405],{"class":1392},[1386,1801,1408],{"class":1392},[1386,1803,1507],{"class":1435},[1386,1805,1420],{"class":1392},[1386,1807,1808,1810,1812,1814,1816,1819,1823],{"class":1388,"line":1489},[1386,1809,1398],{"class":1392},[1386,1811,1517],{"class":1401},[1386,1813,1405],{"class":1392},[1386,1815,1408],{"class":1392},[1386,1817,1818],{"class":1392}," [",[1386,1820,1822],{"class":1821},"sTEyZ","...",[1386,1824,1825],{"class":1392},"],\n",[1386,1827,1828,1830,1832,1834,1836,1838,1840,1842],{"class":1388,"line":1495},[1386,1829,1398],{"class":1392},[1386,1831,1648],{"class":1401},[1386,1833,1405],{"class":1392},[1386,1835,1408],{"class":1392},[1386,1837,1411],{"class":1392},[1386,1839,1657],{"class":1414},[1386,1841,1405],{"class":1392},[1386,1843,1420],{"class":1392},[1386,1845,1846,1848,1851,1853,1855,1857,1860,1862],{"class":1388,"line":1512},[1386,1847,1398],{"class":1392},[1386,1849,1850],{"class":1401},"created_at",[1386,1852,1405],{"class":1392},[1386,1854,1408],{"class":1392},[1386,1856,1411],{"class":1392},[1386,1858,1859],{"class":1414},"2026-01-27T14:30:05Z",[1386,1861,1405],{"class":1392},[1386,1863,1420],{"class":1392},[1386,1865,1866,1868,1871,1873,1875],{"class":1388,"line":1527},[1386,1867,1398],{"class":1392},[1386,1869,1870],{"class":1401},"is_duplicate",[1386,1872,1405],{"class":1392},[1386,1874,1408],{"class":1392},[1386,1876,1877],{"class":1392}," false\n",[1386,1879,1880],{"class":1388,"line":1566},[1386,1881,1687],{"class":1392},[1295,1883,1885],{"id":1884},"idempotency","Idempotency",[747,1887,1888,1889,1892,1893,1896],{},"The API is ",[754,1890,1891],{},"idempotent"," - if you accidentally export the same project twice with the same timestamp, it returns the existing record with ",[1383,1894,1895],{},"is_duplicate: true"," instead of creating a duplicate.",[1169,1898],{},[759,1900,1902],{"id":1901},"extending-the-max-for-live-device","Extending the Max for Live Device",[747,1904,1905],{},"Now let's modify our JavaScript to send data to the API.",[1295,1907,1909],{"id":1908},"the-challenge-max-for-live-http-requests","The Challenge: Max for Live HTTP Requests",[747,1911,1912,1913,1916,1917,1920,1921,1916,1924,1927,1928,1931],{},"Max for Live's JavaScript environment doesn't have native ",[1383,1914,1915],{},"fetch()"," or ",[1383,1918,1919],{},"XMLHttpRequest",". Instead, we use the ",[1383,1922,1923],{},"jweb",[1383,1925,1926],{},"maxurl"," objects, or - the simplest approach - shell out to ",[1383,1929,1930],{},"curl",".",[1295,1933,1935],{"id":1934},"core-logic-marker_exportjs","Core Logic (marker_export.js)",[747,1937,1938],{},"The JavaScript extends our previous export script with API communication:",[1377,1940,1944],{"className":1941,"code":1942,"language":1943,"meta":943,"style":943},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","// Pseudo-code: marker_export.js\n\nfunction bang() {\n  // 1. Get project data from Live via LiveAPI\n  song = new LiveAPI(\"live_set\")\n\n  name = song.get(\"name\")           // Project name\n  bpm = song.get(\"tempo\")           // BPM\n  sigNum = song.get(\"signature_numerator\")\n  sigDen = song.get(\"signature_denominator\")\n\n  // 2. Collect all locators (cue points)\n  locatorIds = song.get(\"cue_points\")\n  sections = []\n\n  for each locatorId:\n    locator = new LiveAPI(\"id \" + locatorId)\n    sections.push({\n      label: locator.get(\"name\"),      // \"INTRO\", \"VERSE\", etc.\n      time_seconds: locator.get(\"time\") // Position in seconds\n    })\n\n  // 3. Build payload matching API schema\n  payload = {\n    project: name,\n    bpm: bpm,\n    time_signature: { numerator: sigNum, denominator: sigDen },\n    sections: sections,\n    exported_at: now()\n  }\n\n  // 4. Display in UI + send to API\n  outlet(0, JSON.stringify(payload))  // → textedit (preview)\n  outlet(1, payload)                   // → node.script (API sender)\n}\n","javascript",[1383,1945,1946,1952,1957,1971,1976,2004,2008,2038,2065,2089,2113,2117,2122,2146,2156,2160,2174,2202,2217,2248,2277,2285,2290,2296,2306,2319,2332,2362,2374,2388,2394,2399,2405,2437,2458],{"__ignoreMap":943},[1386,1947,1948],{"class":1388,"line":1389},[1386,1949,1951],{"class":1950},"sHwdD","// Pseudo-code: marker_export.js\n",[1386,1953,1954],{"class":1388,"line":944},[1386,1955,1956],{"emptyLinePlaceholder":958},"\n",[1386,1958,1959,1962,1966,1969],{"class":1388,"line":1423},[1386,1960,1961],{"class":1401},"function",[1386,1963,1965],{"class":1964},"s2Zo4"," bang",[1386,1967,1968],{"class":1392},"()",[1386,1970,1452],{"class":1392},[1386,1972,1973],{"class":1388,"line":1119},[1386,1974,1975],{"class":1950},"  // 1. Get project data from Live via LiveAPI\n",[1386,1977,1978,1981,1984,1987,1990,1994,1996,1999,2001],{"class":1388,"line":1455},[1386,1979,1980],{"class":1821},"  song",[1386,1982,1983],{"class":1392}," =",[1386,1985,1986],{"class":1392}," new",[1386,1988,1989],{"class":1964}," LiveAPI",[1386,1991,1993],{"class":1992},"swJcz","(",[1386,1995,1405],{"class":1392},[1386,1997,1998],{"class":1414},"live_set",[1386,2000,1405],{"class":1392},[1386,2002,2003],{"class":1992},")\n",[1386,2005,2006],{"class":1388,"line":1474},[1386,2007,1956],{"emptyLinePlaceholder":958},[1386,2009,2010,2013,2015,2018,2020,2023,2025,2027,2030,2032,2035],{"class":1388,"line":1489},[1386,2011,2012],{"class":1821},"  name",[1386,2014,1983],{"class":1392},[1386,2016,2017],{"class":1821}," song",[1386,2019,1931],{"class":1392},[1386,2021,2022],{"class":1964},"get",[1386,2024,1993],{"class":1992},[1386,2026,1405],{"class":1392},[1386,2028,2029],{"class":1414},"name",[1386,2031,1405],{"class":1392},[1386,2033,2034],{"class":1992},")           ",[1386,2036,2037],{"class":1950},"// Project name\n",[1386,2039,2040,2043,2045,2047,2049,2051,2053,2055,2058,2060,2062],{"class":1388,"line":1495},[1386,2041,2042],{"class":1821},"  bpm",[1386,2044,1983],{"class":1392},[1386,2046,2017],{"class":1821},[1386,2048,1931],{"class":1392},[1386,2050,2022],{"class":1964},[1386,2052,1993],{"class":1992},[1386,2054,1405],{"class":1392},[1386,2056,2057],{"class":1414},"tempo",[1386,2059,1405],{"class":1392},[1386,2061,2034],{"class":1992},[1386,2063,2064],{"class":1950},"// BPM\n",[1386,2066,2067,2070,2072,2074,2076,2078,2080,2082,2085,2087],{"class":1388,"line":1512},[1386,2068,2069],{"class":1821},"  sigNum",[1386,2071,1983],{"class":1392},[1386,2073,2017],{"class":1821},[1386,2075,1931],{"class":1392},[1386,2077,2022],{"class":1964},[1386,2079,1993],{"class":1992},[1386,2081,1405],{"class":1392},[1386,2083,2084],{"class":1414},"signature_numerator",[1386,2086,1405],{"class":1392},[1386,2088,2003],{"class":1992},[1386,2090,2091,2094,2096,2098,2100,2102,2104,2106,2109,2111],{"class":1388,"line":1527},[1386,2092,2093],{"class":1821},"  sigDen",[1386,2095,1983],{"class":1392},[1386,2097,2017],{"class":1821},[1386,2099,1931],{"class":1392},[1386,2101,2022],{"class":1964},[1386,2103,1993],{"class":1992},[1386,2105,1405],{"class":1392},[1386,2107,2108],{"class":1414},"signature_denominator",[1386,2110,1405],{"class":1392},[1386,2112,2003],{"class":1992},[1386,2114,2115],{"class":1388,"line":1566},[1386,2116,1956],{"emptyLinePlaceholder":958},[1386,2118,2119],{"class":1388,"line":1601},[1386,2120,2121],{"class":1950},"  // 2. Collect all locators (cue points)\n",[1386,2123,2124,2127,2129,2131,2133,2135,2137,2139,2142,2144],{"class":1388,"line":1637},[1386,2125,2126],{"class":1821},"  locatorIds",[1386,2128,1983],{"class":1392},[1386,2130,2017],{"class":1821},[1386,2132,1931],{"class":1392},[1386,2134,2022],{"class":1964},[1386,2136,1993],{"class":1992},[1386,2138,1405],{"class":1392},[1386,2140,2141],{"class":1414},"cue_points",[1386,2143,1405],{"class":1392},[1386,2145,2003],{"class":1992},[1386,2147,2148,2151,2153],{"class":1388,"line":1643},[1386,2149,2150],{"class":1821},"  sections",[1386,2152,1983],{"class":1392},[1386,2154,2155],{"class":1992}," []\n",[1386,2157,2158],{"class":1388,"line":1664},[1386,2159,1956],{"emptyLinePlaceholder":958},[1386,2161,2162,2165,2168,2171],{"class":1388,"line":1684},[1386,2163,2164],{"class":1821},"  for",[1386,2166,2167],{"class":1821}," each",[1386,2169,2170],{"class":1461}," locatorId",[1386,2172,2173],{"class":1392},":\n",[1386,2175,2177,2180,2182,2184,2186,2188,2190,2193,2195,2198,2200],{"class":1388,"line":2176},17,[1386,2178,2179],{"class":1821},"    locator",[1386,2181,1983],{"class":1392},[1386,2183,1986],{"class":1392},[1386,2185,1989],{"class":1964},[1386,2187,1993],{"class":1992},[1386,2189,1405],{"class":1392},[1386,2191,2192],{"class":1414},"id ",[1386,2194,1405],{"class":1392},[1386,2196,2197],{"class":1392}," +",[1386,2199,2170],{"class":1821},[1386,2201,2003],{"class":1992},[1386,2203,2205,2208,2210,2213,2215],{"class":1388,"line":2204},18,[1386,2206,2207],{"class":1821},"    sections",[1386,2209,1931],{"class":1392},[1386,2211,2212],{"class":1964},"push",[1386,2214,1993],{"class":1992},[1386,2216,1393],{"class":1392},[1386,2218,2220,2223,2225,2228,2230,2232,2234,2236,2238,2240,2243,2245],{"class":1388,"line":2219},19,[1386,2221,2222],{"class":1992},"      label",[1386,2224,1408],{"class":1392},[1386,2226,2227],{"class":1821}," locator",[1386,2229,1931],{"class":1392},[1386,2231,2022],{"class":1964},[1386,2233,1993],{"class":1992},[1386,2235,1405],{"class":1392},[1386,2237,2029],{"class":1414},[1386,2239,1405],{"class":1392},[1386,2241,2242],{"class":1992},")",[1386,2244,1549],{"class":1392},[1386,2246,2247],{"class":1950},"      // \"INTRO\", \"VERSE\", etc.\n",[1386,2249,2251,2254,2256,2258,2260,2262,2264,2266,2269,2271,2274],{"class":1388,"line":2250},20,[1386,2252,2253],{"class":1992},"      time_seconds",[1386,2255,1408],{"class":1392},[1386,2257,2227],{"class":1821},[1386,2259,1931],{"class":1392},[1386,2261,2022],{"class":1964},[1386,2263,1993],{"class":1992},[1386,2265,1405],{"class":1392},[1386,2267,2268],{"class":1414},"time",[1386,2270,1405],{"class":1392},[1386,2272,2273],{"class":1992},") ",[1386,2275,2276],{"class":1950},"// Position in seconds\n",[1386,2278,2280,2283],{"class":1388,"line":2279},21,[1386,2281,2282],{"class":1392},"    }",[1386,2284,2003],{"class":1992},[1386,2286,2288],{"class":1388,"line":2287},22,[1386,2289,1956],{"emptyLinePlaceholder":958},[1386,2291,2293],{"class":1388,"line":2292},23,[1386,2294,2295],{"class":1950},"  // 3. Build payload matching API schema\n",[1386,2297,2299,2302,2304],{"class":1388,"line":2298},24,[1386,2300,2301],{"class":1821},"  payload",[1386,2303,1983],{"class":1392},[1386,2305,1452],{"class":1392},[1386,2307,2309,2312,2314,2317],{"class":1388,"line":2308},25,[1386,2310,2311],{"class":1992},"    project",[1386,2313,1408],{"class":1392},[1386,2315,2316],{"class":1821}," name",[1386,2318,1420],{"class":1392},[1386,2320,2322,2325,2327,2330],{"class":1388,"line":2321},26,[1386,2323,2324],{"class":1992},"    bpm",[1386,2326,1408],{"class":1392},[1386,2328,2329],{"class":1821}," bpm",[1386,2331,1420],{"class":1392},[1386,2333,2335,2338,2340,2342,2345,2347,2350,2352,2355,2357,2360],{"class":1388,"line":2334},27,[1386,2336,2337],{"class":1992},"    time_signature",[1386,2339,1408],{"class":1392},[1386,2341,1767],{"class":1392},[1386,2343,2344],{"class":1992}," numerator",[1386,2346,1408],{"class":1392},[1386,2348,2349],{"class":1821}," sigNum",[1386,2351,1549],{"class":1392},[1386,2353,2354],{"class":1992}," denominator",[1386,2356,1408],{"class":1392},[1386,2358,2359],{"class":1821}," sigDen",[1386,2361,1563],{"class":1392},[1386,2363,2365,2367,2369,2372],{"class":1388,"line":2364},28,[1386,2366,2207],{"class":1992},[1386,2368,1408],{"class":1392},[1386,2370,2371],{"class":1821}," sections",[1386,2373,1420],{"class":1392},[1386,2375,2377,2380,2382,2385],{"class":1388,"line":2376},29,[1386,2378,2379],{"class":1992},"    exported_at",[1386,2381,1408],{"class":1392},[1386,2383,2384],{"class":1964}," now",[1386,2386,2387],{"class":1992},"()\n",[1386,2389,2391],{"class":1388,"line":2390},30,[1386,2392,2393],{"class":1392},"  }\n",[1386,2395,2397],{"class":1388,"line":2396},31,[1386,2398,1956],{"emptyLinePlaceholder":958},[1386,2400,2402],{"class":1388,"line":2401},32,[1386,2403,2404],{"class":1950},"  // 4. Display in UI + send to API\n",[1386,2406,2408,2411,2413,2416,2418,2421,2423,2426,2428,2431,2434],{"class":1388,"line":2407},33,[1386,2409,2410],{"class":1964},"  outlet",[1386,2412,1993],{"class":1992},[1386,2414,2415],{"class":1435},"0",[1386,2417,1549],{"class":1392},[1386,2419,2420],{"class":1821}," JSON",[1386,2422,1931],{"class":1392},[1386,2424,2425],{"class":1964},"stringify",[1386,2427,1993],{"class":1992},[1386,2429,2430],{"class":1821},"payload",[1386,2432,2433],{"class":1992},"))  ",[1386,2435,2436],{"class":1950},"// → textedit (preview)\n",[1386,2438,2440,2442,2444,2447,2449,2452,2455],{"class":1388,"line":2439},34,[1386,2441,2410],{"class":1964},[1386,2443,1993],{"class":1992},[1386,2445,2446],{"class":1435},"1",[1386,2448,1549],{"class":1392},[1386,2450,2451],{"class":1821}," payload",[1386,2453,2454],{"class":1992},")                   ",[1386,2456,2457],{"class":1950},"// → node.script (API sender)\n",[1386,2459,2461],{"class":1388,"line":2460},35,[1386,2462,1687],{"class":1392},[747,2464,2465,2468,2469,2472],{},[754,2466,2467],{},"Key insight:"," LiveAPI returns arrays for most properties, so always handle ",[1383,2470,2471],{},"Array.isArray()"," checks.",[1169,2474],{},[759,2476,2478],{"id":2477},"alternative-using-nodescript","Alternative: Using node.script",[747,2480,2481,2482,2485],{},"For a more robust solution, use the ",[1383,2483,2484],{},"node.script"," object which runs a Node.js script directly within Max:",[747,2487,2488],{},[1162,2489],{"alt":2490,"src":2491},"Max for Live patcher with node.script for API communication","/images/blog/musictechlab_blog_ableton-api-max-patcher.webp",[747,2493,2494],{},"The patcher architecture:",[1377,2496,2501],{"className":2497,"code":2499,"language":2500},[2498],"language-text","┌─────────────────┐     ┌──────────────────────┐     ┌────────────────┐\n│   textbutton    │────▶│  js marker_export.js │────▶│   textedit     │\n│    \"Export\"     │     │                      │     │  (JSON output) │\n└─────────────────┘     └──────────┬───────────┘     └────────────────┘\n                                   │\n                                   ▼\n                        ┌──────────────────────────────────────┐\n                        │  node.script api_sender.js           │\n                        │  @autostart 1 @outlets 1             │\n                        └──────────────────┬───────────────────┘\n                                           │\n                                           ▼\n                                 ┌────────────────┐\n                                 │   textedit     │\n                                 │ (API status)   │\n                                 └────────────────┘\n","text",[1383,2502,2499],{"__ignoreMap":943},[747,2504,2505,2506,2508],{},"The ",[1383,2507,2484],{}," object runs a Node.js script within Max, providing full access to npm packages and modern JavaScript features.",[1169,2510],{},[759,2512,2514],{"id":2513},"the-api-sender-api_senderjs","The API Sender (api_sender.js)",[747,2516,2505,2517,2519],{},[1383,2518,2484],{}," object runs a Node.js script that handles HTTP communication:",[1377,2521,2523],{"className":1941,"code":2522,"language":1943,"meta":943,"style":943},"// Pseudo-code: api_sender.js\n\nconst Max = require('max-api');\nconst API_URL = \"https://your-api.run.app/api/ableton/exports\";\n\nMax.addHandler(\"export\", async (jsonString) => {\n  // 1. Parse incoming data from marker_export.js\n  const payload = JSON.parse(jsonString);\n\n  // 2. POST to API\n  const response = await fetch(API_URL, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(payload)\n  });\n\n  // 3. Handle response\n  const result = await response.json();\n\n  if (result.is_duplicate) {\n    Max.outlet(\"status\", \"Already exported\");\n  } else {\n    Max.outlet(\"status\", \"Saved: \" + result.id);\n  }\n});\n",[1383,2524,2525,2530,2534,2563,2581,2585,2623,2628,2652,2656,2661,2686,2703,2730,2749,2758,2762,2767,2788,2792,2810,2842,2851,2888,2892],{"__ignoreMap":943},[1386,2526,2527],{"class":1388,"line":1389},[1386,2528,2529],{"class":1950},"// Pseudo-code: api_sender.js\n",[1386,2531,2532],{"class":1388,"line":944},[1386,2533,1956],{"emptyLinePlaceholder":958},[1386,2535,2536,2539,2542,2545,2548,2550,2553,2556,2558,2560],{"class":1388,"line":1423},[1386,2537,2538],{"class":1401},"const",[1386,2540,2541],{"class":1821}," Max ",[1386,2543,2544],{"class":1392},"=",[1386,2546,2547],{"class":1964}," require",[1386,2549,1993],{"class":1821},[1386,2551,2552],{"class":1392},"'",[1386,2554,2555],{"class":1414},"max-api",[1386,2557,2552],{"class":1392},[1386,2559,2242],{"class":1821},[1386,2561,2562],{"class":1392},";\n",[1386,2564,2565,2567,2570,2572,2574,2577,2579],{"class":1388,"line":1119},[1386,2566,2538],{"class":1401},[1386,2568,2569],{"class":1821}," API_URL ",[1386,2571,2544],{"class":1392},[1386,2573,1411],{"class":1392},[1386,2575,2576],{"class":1414},"https://your-api.run.app/api/ableton/exports",[1386,2578,1405],{"class":1392},[1386,2580,2562],{"class":1392},[1386,2582,2583],{"class":1388,"line":1455},[1386,2584,1956],{"emptyLinePlaceholder":958},[1386,2586,2587,2590,2592,2595,2597,2599,2602,2604,2606,2609,2612,2616,2618,2621],{"class":1388,"line":1474},[1386,2588,2589],{"class":1821},"Max",[1386,2591,1931],{"class":1392},[1386,2593,2594],{"class":1964},"addHandler",[1386,2596,1993],{"class":1821},[1386,2598,1405],{"class":1392},[1386,2600,2601],{"class":1414},"export",[1386,2603,1405],{"class":1392},[1386,2605,1549],{"class":1392},[1386,2607,2608],{"class":1401}," async",[1386,2610,2611],{"class":1392}," (",[1386,2613,2615],{"class":2614},"sHdIc","jsonString",[1386,2617,2242],{"class":1392},[1386,2619,2620],{"class":1401}," =>",[1386,2622,1452],{"class":1392},[1386,2624,2625],{"class":1388,"line":1489},[1386,2626,2627],{"class":1950},"  // 1. Parse incoming data from marker_export.js\n",[1386,2629,2630,2633,2635,2637,2639,2641,2644,2646,2648,2650],{"class":1388,"line":1495},[1386,2631,2632],{"class":1401},"  const",[1386,2634,2451],{"class":1821},[1386,2636,1983],{"class":1392},[1386,2638,2420],{"class":1821},[1386,2640,1931],{"class":1392},[1386,2642,2643],{"class":1964},"parse",[1386,2645,1993],{"class":1992},[1386,2647,2615],{"class":1821},[1386,2649,2242],{"class":1992},[1386,2651,2562],{"class":1392},[1386,2653,2654],{"class":1388,"line":1512},[1386,2655,1956],{"emptyLinePlaceholder":958},[1386,2657,2658],{"class":1388,"line":1527},[1386,2659,2660],{"class":1950},"  // 2. POST to API\n",[1386,2662,2663,2665,2668,2670,2674,2677,2679,2682,2684],{"class":1388,"line":1566},[1386,2664,2632],{"class":1401},[1386,2666,2667],{"class":1821}," response",[1386,2669,1983],{"class":1392},[1386,2671,2673],{"class":2672},"s7zQu"," await",[1386,2675,2676],{"class":1964}," fetch",[1386,2678,1993],{"class":1992},[1386,2680,2681],{"class":1821},"API_URL",[1386,2683,1549],{"class":1392},[1386,2685,1452],{"class":1392},[1386,2687,2688,2691,2693,2696,2699,2701],{"class":1388,"line":1601},[1386,2689,2690],{"class":1992},"    method",[1386,2692,1408],{"class":1392},[1386,2694,2695],{"class":1392}," '",[1386,2697,2698],{"class":1414},"POST",[1386,2700,2552],{"class":1392},[1386,2702,1420],{"class":1392},[1386,2704,2705,2708,2710,2712,2714,2717,2719,2721,2723,2726,2728],{"class":1388,"line":1637},[1386,2706,2707],{"class":1992},"    headers",[1386,2709,1408],{"class":1392},[1386,2711,1767],{"class":1392},[1386,2713,2695],{"class":1392},[1386,2715,2716],{"class":1992},"Content-Type",[1386,2718,2552],{"class":1392},[1386,2720,1408],{"class":1392},[1386,2722,2695],{"class":1392},[1386,2724,2725],{"class":1414},"application/json",[1386,2727,2552],{"class":1392},[1386,2729,1563],{"class":1392},[1386,2731,2732,2735,2737,2739,2741,2743,2745,2747],{"class":1388,"line":1643},[1386,2733,2734],{"class":1992},"    body",[1386,2736,1408],{"class":1392},[1386,2738,2420],{"class":1821},[1386,2740,1931],{"class":1392},[1386,2742,2425],{"class":1964},[1386,2744,1993],{"class":1992},[1386,2746,2430],{"class":1821},[1386,2748,2003],{"class":1992},[1386,2750,2751,2754,2756],{"class":1388,"line":1664},[1386,2752,2753],{"class":1392},"  }",[1386,2755,2242],{"class":1992},[1386,2757,2562],{"class":1392},[1386,2759,2760],{"class":1388,"line":1684},[1386,2761,1956],{"emptyLinePlaceholder":958},[1386,2763,2764],{"class":1388,"line":2176},[1386,2765,2766],{"class":1950},"  // 3. Handle response\n",[1386,2768,2769,2771,2774,2776,2778,2780,2782,2784,2786],{"class":1388,"line":2204},[1386,2770,2632],{"class":1401},[1386,2772,2773],{"class":1821}," result",[1386,2775,1983],{"class":1392},[1386,2777,2673],{"class":2672},[1386,2779,2667],{"class":1821},[1386,2781,1931],{"class":1392},[1386,2783,1381],{"class":1964},[1386,2785,1968],{"class":1992},[1386,2787,2562],{"class":1392},[1386,2789,2790],{"class":1388,"line":2219},[1386,2791,1956],{"emptyLinePlaceholder":958},[1386,2793,2794,2797,2799,2802,2804,2806,2808],{"class":1388,"line":2250},[1386,2795,2796],{"class":2672},"  if",[1386,2798,2611],{"class":1992},[1386,2800,2801],{"class":1821},"result",[1386,2803,1931],{"class":1392},[1386,2805,1870],{"class":1821},[1386,2807,2273],{"class":1992},[1386,2809,1393],{"class":1392},[1386,2811,2812,2815,2817,2820,2822,2824,2827,2829,2831,2833,2836,2838,2840],{"class":1388,"line":2279},[1386,2813,2814],{"class":1821},"    Max",[1386,2816,1931],{"class":1392},[1386,2818,2819],{"class":1964},"outlet",[1386,2821,1993],{"class":1992},[1386,2823,1405],{"class":1392},[1386,2825,2826],{"class":1414},"status",[1386,2828,1405],{"class":1392},[1386,2830,1549],{"class":1392},[1386,2832,1411],{"class":1392},[1386,2834,2835],{"class":1414},"Already exported",[1386,2837,1405],{"class":1392},[1386,2839,2242],{"class":1992},[1386,2841,2562],{"class":1392},[1386,2843,2844,2846,2849],{"class":1388,"line":2287},[1386,2845,2753],{"class":1392},[1386,2847,2848],{"class":2672}," else",[1386,2850,1452],{"class":1392},[1386,2852,2853,2855,2857,2859,2861,2863,2865,2867,2869,2871,2874,2876,2878,2880,2882,2884,2886],{"class":1388,"line":2292},[1386,2854,2814],{"class":1821},[1386,2856,1931],{"class":1392},[1386,2858,2819],{"class":1964},[1386,2860,1993],{"class":1992},[1386,2862,1405],{"class":1392},[1386,2864,2826],{"class":1414},[1386,2866,1405],{"class":1392},[1386,2868,1549],{"class":1392},[1386,2870,1411],{"class":1392},[1386,2872,2873],{"class":1414},"Saved: ",[1386,2875,1405],{"class":1392},[1386,2877,2197],{"class":1392},[1386,2879,2773],{"class":1821},[1386,2881,1931],{"class":1392},[1386,2883,1708],{"class":1821},[1386,2885,2242],{"class":1992},[1386,2887,2562],{"class":1392},[1386,2889,2890],{"class":1388,"line":2298},[1386,2891,2393],{"class":1392},[1386,2893,2894,2897,2899],{"class":1388,"line":2308},[1386,2895,2896],{"class":1392},"}",[1386,2898,2242],{"class":1821},[1386,2900,2562],{"class":1392},[747,2902,2903,2906,2907,2909],{},[754,2904,2905],{},"Why node.script?"," Unlike Max's built-in JS, ",[1383,2908,2484],{}," provides full Node.js runtime with npm packages, async/await, and modern fetch API.",[1169,2911],{},[759,2913,2915],{"id":2914},"the-api-implementation","The API Implementation",[747,2917,2918],{},"The backend is a FastAPI service with PostgreSQL storage:",[1377,2920,2924],{"className":2921,"code":2922,"language":2923,"meta":943,"style":943},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Pseudo-code: FastAPI endpoint\n\n@router.post(\"/ableton/exports\")\nasync def create_export(data: AbletonExportSchema, db: Session):\n\n    # 1. Idempotency check - prevent duplicates\n    existing = db.query(Export).filter(\n        project == data.project,\n        exported_at == data.exported_at\n    ).first()\n\n    if existing:\n        return { ...existing, is_duplicate: True }\n\n    # 2. Store new export\n    export = Export(\n        id = uuid4(),\n        project_name = data.project,\n        bpm = data.bpm,\n        sections = data.sections,    # JSON array\n        exported_at = data.exported_at\n    )\n\n    db.add(export)\n    db.commit()\n\n    return { ...export, is_duplicate: False }\n","python",[1383,2925,2926,2931,2935,2959,2993,2997,3002,3030,3047,3061,3071,3075,3085,3107,3111,3116,3128,3141,3156,3171,3189,3202,3207,3211,3227,3238,3242],{"__ignoreMap":943},[1386,2927,2928],{"class":1388,"line":1389},[1386,2929,2930],{"class":1950},"# Pseudo-code: FastAPI endpoint\n",[1386,2932,2933],{"class":1388,"line":944},[1386,2934,1956],{"emptyLinePlaceholder":958},[1386,2936,2937,2940,2943,2945,2948,2950,2952,2955,2957],{"class":1388,"line":1423},[1386,2938,2939],{"class":1392},"@",[1386,2941,2942],{"class":1964},"router",[1386,2944,1931],{"class":1392},[1386,2946,2947],{"class":1964},"post",[1386,2949,1993],{"class":1392},[1386,2951,1405],{"class":1392},[1386,2953,2954],{"class":1414},"/ableton/exports",[1386,2956,1405],{"class":1392},[1386,2958,2003],{"class":1392},[1386,2960,2961,2964,2967,2970,2972,2975,2977,2980,2982,2985,2987,2990],{"class":1388,"line":1119},[1386,2962,2963],{"class":1401},"async",[1386,2965,2966],{"class":1401}," def",[1386,2968,2969],{"class":1964}," create_export",[1386,2971,1993],{"class":1392},[1386,2973,2974],{"class":2614},"data",[1386,2976,1408],{"class":1392},[1386,2978,2979],{"class":1821}," AbletonExportSchema",[1386,2981,1549],{"class":1392},[1386,2983,2984],{"class":2614}," db",[1386,2986,1408],{"class":1392},[1386,2988,2989],{"class":1821}," Session",[1386,2991,2992],{"class":1392},"):\n",[1386,2994,2995],{"class":1388,"line":1455},[1386,2996,1956],{"emptyLinePlaceholder":958},[1386,2998,2999],{"class":1388,"line":1474},[1386,3000,3001],{"class":1950},"    # 1. Idempotency check - prevent duplicates\n",[1386,3003,3004,3007,3009,3011,3013,3016,3018,3021,3024,3027],{"class":1388,"line":1489},[1386,3005,3006],{"class":1821},"    existing ",[1386,3008,2544],{"class":1392},[1386,3010,2984],{"class":1821},[1386,3012,1931],{"class":1392},[1386,3014,3015],{"class":1964},"query",[1386,3017,1993],{"class":1392},[1386,3019,3020],{"class":1964},"Export",[1386,3022,3023],{"class":1392},").",[1386,3025,3026],{"class":1964},"filter",[1386,3028,3029],{"class":1392},"(\n",[1386,3031,3032,3035,3038,3041,3043,3045],{"class":1388,"line":1495},[1386,3033,3034],{"class":1964},"        project ",[1386,3036,3037],{"class":1392},"==",[1386,3039,3040],{"class":1964}," data",[1386,3042,1931],{"class":1392},[1386,3044,1402],{"class":1992},[1386,3046,1420],{"class":1392},[1386,3048,3049,3052,3054,3056,3058],{"class":1388,"line":1512},[1386,3050,3051],{"class":1964},"        exported_at ",[1386,3053,3037],{"class":1392},[1386,3055,3040],{"class":1964},[1386,3057,1931],{"class":1392},[1386,3059,3060],{"class":1992},"exported_at\n",[1386,3062,3063,3066,3069],{"class":1388,"line":1527},[1386,3064,3065],{"class":1392},"    ).",[1386,3067,3068],{"class":1964},"first",[1386,3070,2387],{"class":1392},[1386,3072,3073],{"class":1388,"line":1566},[1386,3074,1956],{"emptyLinePlaceholder":958},[1386,3076,3077,3080,3083],{"class":1388,"line":1601},[1386,3078,3079],{"class":2672},"    if",[1386,3081,3082],{"class":1821}," existing",[1386,3084,2173],{"class":1392},[1386,3086,3087,3090,3092,3095,3097,3100,3102,3105],{"class":1388,"line":1637},[1386,3088,3089],{"class":2672},"        return",[1386,3091,1767],{"class":1392},[1386,3093,3094],{"class":1821}," ...existing",[1386,3096,1549],{"class":1392},[1386,3098,3099],{"class":1821}," is_duplicate",[1386,3101,1408],{"class":1392},[1386,3103,3104],{"class":1392}," True",[1386,3106,1634],{"class":1392},[1386,3108,3109],{"class":1388,"line":1643},[1386,3110,1956],{"emptyLinePlaceholder":958},[1386,3112,3113],{"class":1388,"line":1664},[1386,3114,3115],{"class":1950},"    # 2. Store new export\n",[1386,3117,3118,3121,3123,3126],{"class":1388,"line":1684},[1386,3119,3120],{"class":1821},"    export ",[1386,3122,2544],{"class":1392},[1386,3124,3125],{"class":1964}," Export",[1386,3127,3029],{"class":1392},[1386,3129,3130,3133,3135,3138],{"class":1388,"line":2176},[1386,3131,3132],{"class":2614},"        id",[1386,3134,1983],{"class":1392},[1386,3136,3137],{"class":1964}," uuid4",[1386,3139,3140],{"class":1392},"(),\n",[1386,3142,3143,3146,3148,3150,3152,3154],{"class":1388,"line":2204},[1386,3144,3145],{"class":2614},"        project_name",[1386,3147,1983],{"class":1392},[1386,3149,3040],{"class":1964},[1386,3151,1931],{"class":1392},[1386,3153,1402],{"class":1992},[1386,3155,1420],{"class":1392},[1386,3157,3158,3161,3163,3165,3167,3169],{"class":1388,"line":2219},[1386,3159,3160],{"class":2614},"        bpm",[1386,3162,1983],{"class":1392},[1386,3164,3040],{"class":1964},[1386,3166,1931],{"class":1392},[1386,3168,1428],{"class":1992},[1386,3170,1420],{"class":1392},[1386,3172,3173,3176,3178,3180,3182,3184,3186],{"class":1388,"line":2250},[1386,3174,3175],{"class":2614},"        sections",[1386,3177,1983],{"class":1392},[1386,3179,3040],{"class":1964},[1386,3181,1931],{"class":1392},[1386,3183,1517],{"class":1992},[1386,3185,1549],{"class":1392},[1386,3187,3188],{"class":1950},"    # JSON array\n",[1386,3190,3191,3194,3196,3198,3200],{"class":1388,"line":2279},[1386,3192,3193],{"class":2614},"        exported_at",[1386,3195,1983],{"class":1392},[1386,3197,3040],{"class":1964},[1386,3199,1931],{"class":1392},[1386,3201,3060],{"class":1992},[1386,3203,3204],{"class":1388,"line":2287},[1386,3205,3206],{"class":1392},"    )\n",[1386,3208,3209],{"class":1388,"line":2292},[1386,3210,1956],{"emptyLinePlaceholder":958},[1386,3212,3213,3216,3218,3221,3223,3225],{"class":1388,"line":2298},[1386,3214,3215],{"class":1821},"    db",[1386,3217,1931],{"class":1392},[1386,3219,3220],{"class":1964},"add",[1386,3222,1993],{"class":1392},[1386,3224,2601],{"class":1964},[1386,3226,2003],{"class":1392},[1386,3228,3229,3231,3233,3236],{"class":1388,"line":2308},[1386,3230,3215],{"class":1821},[1386,3232,1931],{"class":1392},[1386,3234,3235],{"class":1964},"commit",[1386,3237,2387],{"class":1392},[1386,3239,3240],{"class":1388,"line":2321},[1386,3241,1956],{"emptyLinePlaceholder":958},[1386,3243,3244,3247,3249,3252,3254,3256,3258,3261],{"class":1388,"line":2334},[1386,3245,3246],{"class":2672},"    return",[1386,3248,1767],{"class":1392},[1386,3250,3251],{"class":1821}," ...export",[1386,3253,1549],{"class":1392},[1386,3255,3099],{"class":1821},[1386,3257,1408],{"class":1392},[1386,3259,3260],{"class":1392}," False",[1386,3262,1634],{"class":1392},[747,3264,3265],{},[754,3266,3267],{},"Key design decisions:",[837,3269,3270,3278,3284],{},[800,3271,3272,3274,3275],{},[754,3273,1885],{}," via unique constraint on ",[1383,3276,3277],{},"(project_name, exported_at)",[800,3279,3280,3283],{},[754,3281,3282],{},"Sections stored as JSON"," for flexibility",[800,3285,3286,3289],{},[754,3287,3288],{},"UUID primary keys"," for distributed systems compatibility",[1169,3291],{},[759,3293,3295],{"id":3294},"browser-ui-visualizing-your-exports","Browser UI: Visualizing Your Exports",[747,3297,3298,3299,3302],{},"The API includes a browser-based UI at ",[1383,3300,3301],{},"/browser"," that shows all your exports:",[747,3304,3305],{},[1162,3306],{"alt":3307,"src":3308},"Browser UI with timeline visualization of Ableton exports","/images/blog/musictechlab_blog_ableton-api-browser-ui.webp",[1295,3310,3312],{"id":3311},"features","Features",[1179,3314,3315,3325],{},[1182,3316,3317],{},[1185,3318,3319,3322],{},[1188,3320,3321],{},"Feature",[1188,3323,3324],{},"Description",[1195,3326,3327,3337,3347,3357,3367],{},[1185,3328,3329,3334],{},[1200,3330,3331],{},[754,3332,3333],{},"Timeline visualization",[1200,3335,3336],{},"Ableton-style arrangement view",[1185,3338,3339,3344],{},[1200,3340,3341],{},[754,3342,3343],{},"Filters",[1200,3345,3346],{},"By project, BPM range, section count",[1185,3348,3349,3354],{},[1200,3350,3351],{},[754,3352,3353],{},"Search",[1200,3355,3356],{},"Find exports by name",[1185,3358,3359,3364],{},[1200,3360,3361],{},[754,3362,3363],{},"Pagination",[1200,3365,3366],{},"Handle large export histories",[1185,3368,3369,3374],{},[1200,3370,3371],{},[754,3372,3373],{},"JSON inspection",[1200,3375,3376],{},"Click to see full export data",[1295,3378,3380],{"id":3379},"timeline-rendering","Timeline Rendering",[747,3382,3383],{},"Each export is visualized as a horizontal timeline with color-coded sections:",[764,3385,3387,3388],{"className":3386},[1079,1151],"\n  ",[1162,3389],{"src":3390,"alt":3391,"className":3392},"/images/blog/musictechlab_blog_ableton-api-timeline-row.webp","Timeline visualization with color-coded sections",[3393],"max-w-[70%]",[747,3395,3396],{},"The visualization is generated client-side using vanilla JavaScript and CSS Grid, making it lightweight and fast.",[1169,3398],{},[759,3400,3402],{"id":3401},"additional-api-endpoints","Additional API Endpoints",[1295,3404,3406],{"id":3405},"get-apiabletonexports","GET /api/ableton/exports",[747,3408,3409],{},"List all exports with pagination and filtering:",[1377,3411,3415],{"className":3412,"code":3413,"language":3414,"meta":943,"style":943},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl \"https://api.example.com/api/ableton/exports?project=my_track&page=1&limit=20\"\n","bash",[1383,3416,3417],{"__ignoreMap":943},[1386,3418,3419,3421,3423,3426],{"class":1388,"line":1389},[1386,3420,1930],{"class":1461},[1386,3422,1411],{"class":1392},[1386,3424,3425],{"class":1414},"https://api.example.com/api/ableton/exports?project=my_track&page=1&limit=20",[1386,3427,1681],{"class":1392},[1295,3429,3431],{"id":3430},"get-apiabletonexportsid","GET /api/ableton/exports/{id}",[747,3433,3434],{},"Get a specific export by ID:",[1377,3436,3438],{"className":3412,"code":3437,"language":3414,"meta":943,"style":943},"curl \"https://api.example.com/api/ableton/exports/550e8400-e29b-41d4-a716-446655440000\"\n",[1383,3439,3440],{"__ignoreMap":943},[1386,3441,3442,3444,3446,3449],{"class":1388,"line":1389},[1386,3443,1930],{"class":1461},[1386,3445,1411],{"class":1392},[1386,3447,3448],{"class":1414},"https://api.example.com/api/ableton/exports/550e8400-e29b-41d4-a716-446655440000",[1386,3450,1681],{"class":1392},[1295,3452,3454],{"id":3453},"get-apiabletonprojects","GET /api/ableton/projects",[747,3456,3457],{},"Get list of all unique project names:",[1377,3459,3461],{"className":3412,"code":3460,"language":3414,"meta":943,"style":943},"curl \"https://api.example.com/api/ableton/projects\"\n",[1383,3462,3463],{"__ignoreMap":943},[1386,3464,3465,3467,3469,3472],{"class":1388,"line":1389},[1386,3466,1930],{"class":1461},[1386,3468,1411],{"class":1392},[1386,3470,3471],{"class":1414},"https://api.example.com/api/ableton/projects",[1386,3473,1681],{"class":1392},[747,3475,1692],{},[1377,3477,3479],{"className":1379,"code":3478,"language":1381,"meta":943,"style":943},"{\n  \"projects\": [\"my_track\", \"remix_v2\", \"collab_final\"]\n}\n",[1383,3480,3481,3485,3525],{"__ignoreMap":943},[1386,3482,3483],{"class":1388,"line":1389},[1386,3484,1393],{"class":1392},[1386,3486,3487,3489,3492,3494,3496,3498,3500,3502,3504,3506,3508,3511,3513,3515,3517,3520,3522],{"class":1388,"line":944},[1386,3488,1398],{"class":1392},[1386,3490,3491],{"class":1401},"projects",[1386,3493,1405],{"class":1392},[1386,3495,1408],{"class":1392},[1386,3497,1818],{"class":1392},[1386,3499,1405],{"class":1392},[1386,3501,1415],{"class":1414},[1386,3503,1405],{"class":1392},[1386,3505,1549],{"class":1392},[1386,3507,1411],{"class":1392},[1386,3509,3510],{"class":1414},"remix_v2",[1386,3512,1405],{"class":1392},[1386,3514,1549],{"class":1392},[1386,3516,1411],{"class":1392},[1386,3518,3519],{"class":1414},"collab_final",[1386,3521,1405],{"class":1392},[1386,3523,3524],{"class":1392},"]\n",[1386,3526,3527],{"class":1388,"line":1423},[1386,3528,1687],{"class":1392},[1169,3530],{},[759,3532,3534],{"id":3533},"deployment","Deployment",[747,3536,3537,3538,3541,3542,1408],{},"The API runs on ",[754,3539,3540],{},"Google Cloud Run"," with ",[754,3543,3544],{},"Cloud SQL (PostgreSQL)",[1179,3546,3547,3557],{},[1182,3548,3549],{},[1185,3550,3551,3554],{},[1188,3552,3553],{},"Component",[1188,3555,3556],{},"Service",[1195,3558,3559,3567,3574],{},[1185,3560,3561,3564],{},[1200,3562,3563],{},"API",[1200,3565,3566],{},"Cloud Run (serverless containers)",[1185,3568,3569,3571],{},[1200,3570,1348],{},[1200,3572,3573],{},"Cloud SQL PostgreSQL",[1185,3575,3576,3579],{},[1200,3577,3578],{},"Region",[1200,3580,3581],{},"europe-west1",[747,3583,3584],{},"Local development uses Docker Compose with the same PostgreSQL setup, ensuring dev/prod parity.",[1169,3586],{},[759,3588,3590],{"id":3589},"testing-the-integration","Testing the Integration",[1295,3592,3594],{"id":3593},"from-ableton","From Ableton",[797,3596,3597,3600,3603,3609,3615],{},[800,3598,3599],{},"Open a project with arrangement locators",[800,3601,3602],{},"Add the Max for Live device to any MIDI track",[800,3604,3605,3606],{},"Click ",[754,3607,3608],{},"\"Export\"",[800,3610,3611,3612,1405],{},"Watch the status panel - should show \"Saved: ",[1386,3613,3614],{},"uuid",[800,3616,3617],{},"Open Browser UI - your export appears in the timeline",[1295,3619,3621],{"id":3620},"verify-with-curl","Verify with curl",[1377,3623,3625],{"className":3412,"code":3624,"language":3414,"meta":943,"style":943},"curl \"https://your-api.run.app/api/ableton/projects\"\n# Returns: { \"projects\": [\"your_project_name\", ...] }\n",[1383,3626,3627,3638],{"__ignoreMap":943},[1386,3628,3629,3631,3633,3636],{"class":1388,"line":1389},[1386,3630,1930],{"class":1461},[1386,3632,1411],{"class":1392},[1386,3634,3635],{"class":1414},"https://your-api.run.app/api/ableton/projects",[1386,3637,1681],{"class":1392},[1386,3639,3640],{"class":1388,"line":944},[1386,3641,3642],{"class":1950},"# Returns: { \"projects\": [\"your_project_name\", ...] }\n",[1169,3644],{},[759,3646,3648],{"id":3647},"security-considerations","Security Considerations",[747,3650,3651],{},"For a production deployment, consider:",[1179,3653,3654,3664],{},[1182,3655,3656],{},[1185,3657,3658,3661],{},[1188,3659,3660],{},"Concern",[1188,3662,3663],{},"Solution",[1195,3665,3666,3676,3686,3696,3706],{},[1185,3667,3668,3673],{},[1200,3669,3670],{},[754,3671,3672],{},"Authentication",[1200,3674,3675],{},"Add API keys or OAuth",[1185,3677,3678,3683],{},[1200,3679,3680],{},[754,3681,3682],{},"Rate limiting",[1200,3684,3685],{},"Prevent abuse",[1185,3687,3688,3693],{},[1200,3689,3690],{},[754,3691,3692],{},"CORS",[1200,3694,3695],{},"Restrict allowed origins",[1185,3697,3698,3703],{},[1200,3699,3700],{},[754,3701,3702],{},"Input validation",[1200,3704,3705],{},"Already handled by Pydantic",[1185,3707,3708,3713],{},[1200,3709,3710],{},[754,3711,3712],{},"HTTPS",[1200,3714,3715],{},"Enforced by Cloud Run",[1169,3717],{},[759,3719,3721],{"id":3720},"whats-next","What's Next?",[747,3723,3724],{},"This pipeline enables several advanced workflows:",[797,3726,3727,3733,3739,3745,3750],{},[800,3728,3729,3732],{},[754,3730,3731],{},"AI comparison"," - Compare manual annotations with AI-detected structures",[800,3734,3735,3738],{},[754,3736,3737],{},"Cross-DAW sync"," - Export from Ableton, import to REAPER/Logic",[800,3740,3741,3744],{},[754,3742,3743],{},"Version tracking"," - See how your arrangement evolved over time",[800,3746,3747,3749],{},[754,3748,1237],{}," - Share structure data with collaborators",[800,3751,3752,3755],{},[754,3753,3754],{},"Automated processing"," - Trigger downstream tasks on new exports",[1169,3757],{},[759,3759,3761],{"id":3760},"related-articles","Related Articles",[837,3763,3764,3770],{},[800,3765,3766,3769],{},[889,3767,3768],{"href":475},"Exporting Ableton Live Locators to JSON with Max for Live"," - Build the Max for Live device",[800,3771,3772,3775],{},[889,3773,3774],{"href":101},"Automatic Song Structure Analysis – How AI Detects Intro, Verse, and Chorus"," - AI-powered structure detection",[1169,3777],{},[759,3779,3781],{"id":3780},"conclusion","Conclusion",[747,3783,3784],{},"By connecting your Max for Live device to a cloud API, you transform Ableton from an isolated creative tool into a node in a larger data pipeline. Every arrangement decision, every locator you place, becomes structured data that can power visualizations, training datasets, and cross-platform workflows.",[747,3786,3787,3788,3791],{},"The key insight: ",[754,3789,3790],{},"your DAW is a data source",". Treating it that way opens up possibilities that weren't available when everything stayed local.",[3793,3794,3795],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":943,"searchDepth":944,"depth":944,"links":3797},[3798,3799,3800,3803,3807,3811,3812,3813,3814,3818,3823,3824,3828,3829,3830,3831],{"id":1132,"depth":944,"text":1133},{"id":1173,"depth":944,"text":1174},{"id":1245,"depth":944,"text":1246,"children":3801},[3802],{"id":1297,"depth":1423,"text":1298},{"id":1359,"depth":944,"text":1360,"children":3804},[3805,3806],{"id":1366,"depth":1423,"text":1367},{"id":1884,"depth":1423,"text":1885},{"id":1901,"depth":944,"text":1902,"children":3808},[3809,3810],{"id":1908,"depth":1423,"text":1909},{"id":1934,"depth":1423,"text":1935},{"id":2477,"depth":944,"text":2478},{"id":2513,"depth":944,"text":2514},{"id":2914,"depth":944,"text":2915},{"id":3294,"depth":944,"text":3295,"children":3815},[3816,3817],{"id":3311,"depth":1423,"text":3312},{"id":3379,"depth":1423,"text":3380},{"id":3401,"depth":944,"text":3402,"children":3819},[3820,3821,3822],{"id":3405,"depth":1423,"text":3406},{"id":3430,"depth":1423,"text":3431},{"id":3453,"depth":1423,"text":3454},{"id":3533,"depth":944,"text":3534},{"id":3589,"depth":944,"text":3590,"children":3825},[3826,3827],{"id":3593,"depth":1423,"text":3594},{"id":3620,"depth":1423,"text":3621},{"id":3647,"depth":944,"text":3648},{"id":3720,"depth":944,"text":3721},{"id":3760,"depth":944,"text":3761},{"id":3780,"depth":944,"text":3781},"2026-01-27T00:00:00.000Z","Send song structure data from Ableton Live to a cloud API. Build a complete DAW-to-database pipeline with real-time visualization.",{"src":3835},"/images/blog/musictechlab_blog_ableton-api-connection.webp",{"enabled":958,"items":3837},[3838,3841,3844,3847],{"text":3839,"icon":3840},"A cloud API turns local Ableton exports into a searchable, versioned database.","i-lucide-database",{"text":3842,"icon":3843},"FastAPI on Cloud Run receives, validates, and stores JSON from Max for Live.","i-lucide-rocket",{"text":3845,"icon":3846},"Every export gets a browser-based timeline visualization accessible from anywhere.","i-lucide-globe",{"text":3848,"icon":3849},"The pipeline: Max for Live extracts metadata, sends to API, stores in PostgreSQL.","i-lucide-layers",{},{"title":422,"description":3833},[973,3853],"development","ve9KJaSJswdmeyVXGi-ApoLF6XbRdIXt3m0EvEJIAIE",{"id":3856,"title":474,"authors":3857,"badge":3860,"body":3861,"category":951,"client":742,"date":7048,"description":7049,"extension":954,"faq":742,"featured":69,"featuredOrder":742,"hidden":69,"image":7050,"keyTakeaways":7052,"meta":7065,"navigation":958,"path":475,"seo":7066,"status":742,"stem":476,"tags":7067,"teaser":742,"__hash__":7068,"score":1423},"posts/blog/software-development/exporting-ableton-live-locators-to-json-with-max-for-live.md",[3858],{"name":738,"to":739,"avatar":3859},{"src":741},{"label":1126,"color":1127},{"type":744,"value":3862,"toc":7017},[3863,3867,3874,3877,3891,3894,3898,3901,4128,4131,4145,4149,4152,4196,4200,4203,4209,4229,4233,4251,4255,4258,4275,4279,4288,4328,4343,4347,4350,4378,4382,4385,5330,5334,5340,5346,5363,5371,5380,5384,5387,5399,5403,5407,5410,5415,5440,5444,5447,5452,5495,5499,5502,5510,5542,5546,5558,5561,5572,5577,5608,5612,5615,5815,5825,5836,5840,5844,5847,5853,5856,5870,5874,5886,5896,5900,5911,5915,5927,5958,5962,5969,5994,5996,5999,6062,6066,6069,6999,7001,7004,7011,7014],[3864,3865,3768],"h1",{"id":3866},"exporting-ableton-live-locators-to-json-with-max-for-live",[747,3868,3869,3870,3873],{},"When building music production tools and AI-powered analysis pipelines, one of the first challenges is getting structured data out of your DAW. Today, we'll walk through creating a ",[754,3871,3872],{},"Max for Live device"," that exports arrangement locators from Ableton Live to a clean JSON format.",[747,3875,3876],{},"This article documents a real proof-of-concept we built - a simple \"EXPORT JSON\" button that extracts:",[837,3878,3879,3885],{},[800,3880,3881,3884],{},[754,3882,3883],{},"BPM"," (tempo)",[800,3886,3887,3890],{},[754,3888,3889],{},"Locators/sections"," (INTRO, VERSE, CHORUS, etc.) with timestamps in seconds",[747,3892,3893],{},"The result is a portable JSON file that can feed into visualization tools, AI models, or cross-DAW workflows.",[759,3895,3897],{"id":3896},"the-goal","The Goal",[747,3899,3900],{},"We want a one-click solution inside Ableton Live that produces output like this:",[1377,3902,3904],{"className":1379,"code":3903,"language":1381,"meta":943,"style":943},"{\n  \"project\": \"my_track\",\n  \"bpm\": 103.34,\n  \"sections\": [\n    { \"label\": \"INTRO\", \"time_seconds\": 0 },\n    { \"label\": \"VERSE\", \"time_seconds\": 16 },\n    { \"label\": \"BRIDGE\", \"time_seconds\": 80 },\n    { \"label\": \"CHORUS\", \"time_seconds\": 112 },\n    { \"label\": \"OUTRO\", \"time_seconds\": 224 }\n  ]\n}\n",[1383,3905,3906,3910,3928,3942,3954,3986,4018,4052,4085,4119,4124],{"__ignoreMap":943},[1386,3907,3908],{"class":1388,"line":1389},[1386,3909,1393],{"class":1392},[1386,3911,3912,3914,3916,3918,3920,3922,3924,3926],{"class":1388,"line":944},[1386,3913,1398],{"class":1392},[1386,3915,1402],{"class":1401},[1386,3917,1405],{"class":1392},[1386,3919,1408],{"class":1392},[1386,3921,1411],{"class":1392},[1386,3923,1415],{"class":1414},[1386,3925,1405],{"class":1392},[1386,3927,1420],{"class":1392},[1386,3929,3930,3932,3934,3936,3938,3940],{"class":1388,"line":1423},[1386,3931,1398],{"class":1392},[1386,3933,1428],{"class":1401},[1386,3935,1405],{"class":1392},[1386,3937,1408],{"class":1392},[1386,3939,1436],{"class":1435},[1386,3941,1420],{"class":1392},[1386,3943,3944,3946,3948,3950,3952],{"class":1388,"line":1119},[1386,3945,1398],{"class":1392},[1386,3947,1517],{"class":1401},[1386,3949,1405],{"class":1392},[1386,3951,1408],{"class":1392},[1386,3953,1524],{"class":1392},[1386,3955,3956,3958,3960,3962,3964,3966,3968,3970,3972,3974,3976,3978,3980,3982,3984],{"class":1388,"line":1455},[1386,3957,1530],{"class":1392},[1386,3959,1411],{"class":1392},[1386,3961,1535],{"class":1461},[1386,3963,1405],{"class":1392},[1386,3965,1408],{"class":1392},[1386,3967,1411],{"class":1392},[1386,3969,1544],{"class":1414},[1386,3971,1405],{"class":1392},[1386,3973,1549],{"class":1392},[1386,3975,1411],{"class":1392},[1386,3977,1554],{"class":1461},[1386,3979,1405],{"class":1392},[1386,3981,1408],{"class":1392},[1386,3983,1507],{"class":1435},[1386,3985,1563],{"class":1392},[1386,3987,3988,3990,3992,3994,3996,3998,4000,4002,4004,4006,4008,4010,4012,4014,4016],{"class":1388,"line":1474},[1386,3989,1530],{"class":1392},[1386,3991,1411],{"class":1392},[1386,3993,1535],{"class":1461},[1386,3995,1405],{"class":1392},[1386,3997,1408],{"class":1392},[1386,3999,1411],{"class":1392},[1386,4001,1581],{"class":1414},[1386,4003,1405],{"class":1392},[1386,4005,1549],{"class":1392},[1386,4007,1411],{"class":1392},[1386,4009,1554],{"class":1461},[1386,4011,1405],{"class":1392},[1386,4013,1408],{"class":1392},[1386,4015,1596],{"class":1435},[1386,4017,1563],{"class":1392},[1386,4019,4020,4022,4024,4026,4028,4030,4032,4035,4037,4039,4041,4043,4045,4047,4050],{"class":1388,"line":1489},[1386,4021,1530],{"class":1392},[1386,4023,1411],{"class":1392},[1386,4025,1535],{"class":1461},[1386,4027,1405],{"class":1392},[1386,4029,1408],{"class":1392},[1386,4031,1411],{"class":1392},[1386,4033,4034],{"class":1414},"BRIDGE",[1386,4036,1405],{"class":1392},[1386,4038,1549],{"class":1392},[1386,4040,1411],{"class":1392},[1386,4042,1554],{"class":1461},[1386,4044,1405],{"class":1392},[1386,4046,1408],{"class":1392},[1386,4048,4049],{"class":1435}," 80",[1386,4051,1563],{"class":1392},[1386,4053,4054,4056,4058,4060,4062,4064,4066,4068,4070,4072,4074,4076,4078,4080,4083],{"class":1388,"line":1495},[1386,4055,1530],{"class":1392},[1386,4057,1411],{"class":1392},[1386,4059,1535],{"class":1461},[1386,4061,1405],{"class":1392},[1386,4063,1408],{"class":1392},[1386,4065,1411],{"class":1392},[1386,4067,1616],{"class":1414},[1386,4069,1405],{"class":1392},[1386,4071,1549],{"class":1392},[1386,4073,1411],{"class":1392},[1386,4075,1554],{"class":1461},[1386,4077,1405],{"class":1392},[1386,4079,1408],{"class":1392},[1386,4081,4082],{"class":1435}," 112",[1386,4084,1563],{"class":1392},[1386,4086,4087,4089,4091,4093,4095,4097,4099,4102,4104,4106,4108,4110,4112,4114,4117],{"class":1388,"line":1512},[1386,4088,1530],{"class":1392},[1386,4090,1411],{"class":1392},[1386,4092,1535],{"class":1461},[1386,4094,1405],{"class":1392},[1386,4096,1408],{"class":1392},[1386,4098,1411],{"class":1392},[1386,4100,4101],{"class":1414},"OUTRO",[1386,4103,1405],{"class":1392},[1386,4105,1549],{"class":1392},[1386,4107,1411],{"class":1392},[1386,4109,1554],{"class":1461},[1386,4111,1405],{"class":1392},[1386,4113,1408],{"class":1392},[1386,4115,4116],{"class":1435}," 224",[1386,4118,1634],{"class":1392},[1386,4120,4121],{"class":1388,"line":1527},[1386,4122,4123],{"class":1392},"  ]\n",[1386,4125,4126],{"class":1388,"line":1566},[1386,4127,1687],{"class":1392},[747,4129,4130],{},"This JSON can then be:",[837,4132,4133,4136,4139,4142],{},[800,4134,4135],{},"Imported into other DAWs (REAPER, Logic, etc.)",[800,4137,4138],{},"Used for automated video editing synced to song structure",[800,4140,4141],{},"Fed into machine learning models for training",[800,4143,4144],{},"Displayed in custom visualization tools",[759,4146,4148],{"id":4147},"prerequisites","Prerequisites",[747,4150,4151],{},"To follow along, you'll need:",[1179,4153,4154,4164],{},[1182,4155,4156],{},[1185,4157,4158,4161],{},[1188,4159,4160],{},"Requirement",[1188,4162,4163],{},"Notes",[1195,4165,4166,4176,4186],{},[1185,4167,4168,4173],{},[1200,4169,4170],{},[754,4171,4172],{},"Ableton Live 12 Suite",[1200,4174,4175],{},"Max for Live is included in Suite",[1185,4177,4178,4183],{},[1200,4179,4180],{},[754,4181,4182],{},"Basic Max/MSP knowledge",[1200,4184,4185],{},"We'll keep it simple",[1185,4187,4188,4193],{},[1200,4189,4190],{},[754,4191,4192],{},"Text editor",[1200,4194,4195],{},"For the JavaScript file",[759,4197,4199],{"id":4198},"architecture-overview","Architecture Overview",[747,4201,4202],{},"Our device consists of three components:",[1377,4204,4207],{"className":4205,"code":4206,"language":2500},[2498],"┌─────────────────┐     ┌──────────────────────┐     ┌────────────────┐\n│   textbutton    │────▶│  js marker_export.js │────▶│   textedit     │\n│  \"EXPORT JSON\"  │     │   (LiveAPI magic)    │     │  (JSON preview)│\n└─────────────────┘     └──────────────────────┘     └────────────────┘\n",[1383,4208,4206],{"__ignoreMap":943},[797,4210,4211,4217,4223],{},[800,4212,4213,4216],{},[754,4214,4215],{},"textbutton"," - The user clicks this to trigger export",[800,4218,4219,4222],{},[754,4220,4221],{},"js marker_export.js"," - JavaScript that queries Ableton's Live Object Model",[800,4224,4225,4228],{},[754,4226,4227],{},"textedit"," - Read-only display showing the exported JSON",[759,4230,4232],{"id":4231},"building-the-max-for-live-device","Building the Max for Live Device",[764,4234,3387,4236],{"style":4235},"display: flex; justify-content: center; margin: 2rem 0;",[4237,4238,4240,4241,4240,4246,3387],"figure",{"style":4239},"margin: 0; text-align: center;","\n    ",[1162,4242],{"src":4243,"alt":4244,"style":4245},"/images/blog/musictechlab_blog_ableton-locators-json-max-patcher.webp","Max for Live patcher with JavaScript code","max-width: 600px; width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block;",[4247,4248,4250],"figcaption",{"style":4249},"margin-top: 0.5rem; color: #666; font-size: 0.875rem;","Max for Live patcher with the JavaScript code editor open",[1295,4252,4254],{"id":4253},"step-1-create-the-patcher","Step 1: Create the Patcher",[747,4256,4257],{},"Open Max for Live in Ableton (create a new Max MIDI Effect), then add these objects:",[797,4259,4260,4265,4270],{},[800,4261,4262,4264],{},[754,4263,4215],{}," - Set the text to \"EXPORT JSON\"",[800,4266,4267,4269],{},[754,4268,4221],{}," - This will hold our JavaScript logic",[800,4271,4272,4274],{},[754,4273,4227],{}," - Enable \"Read Only\" in the Inspector",[1295,4276,4278],{"id":4277},"step-2-wire-the-connections","Step 2: Wire the Connections",[747,4280,4281,4282,4284,4285,1408],{},"This is where things get tricky. The ",[1383,4283,4215],{}," object has ",[754,4286,4287],{},"three outlets",[1179,4289,4290,4300],{},[1182,4291,4292],{},[1185,4293,4294,4297],{},[1188,4295,4296],{},"Outlet",[1188,4298,4299],{},"Output",[1195,4301,4302,4310,4318],{},[1185,4303,4304,4307],{},[1200,4305,4306],{},"1st (left)",[1200,4308,4309],{},"Button text",[1185,4311,4312,4315],{},[1200,4313,4314],{},"2nd (middle)",[1200,4316,4317],{},"Mouse events",[1185,4319,4320,4325],{},[1200,4321,4322],{},[754,4323,4324],{},"3rd (right)",[1200,4326,4327],{},"Integer (1 on click)",[747,4329,4330,4331,4334,4335,4337,4338,4340,4341,1931],{},"Connect the ",[754,4332,4333],{},"third outlet"," of ",[1383,4336,4215],{}," to the inlet of ",[1383,4339,4221],{},", then connect the outlet of the JS object to ",[1383,4342,4227],{},[1295,4344,4346],{"id":4345},"step-3-set-up-presentation-mode","Step 3: Set Up Presentation Mode",[747,4348,4349],{},"For the device to be usable in Live's UI:",[797,4351,4352,4359,4362,4368,4375],{},[800,4353,4354,4355,928,4357],{},"Select both ",[1383,4356,4215],{},[1383,4358,4227],{},[800,4360,4361],{},"Open the Inspector (right sidebar)",[800,4363,4364,4365],{},"Enable ",[754,4366,4367],{},"\"Include in Presentation\"",[800,4369,4370,4371,4374],{},"Switch to ",[754,4372,4373],{},"Presentation Mode"," (View → Presentation Mode)",[800,4376,4377],{},"Arrange the objects nicely",[759,4379,4381],{"id":4380},"the-javascript-marker_exportjs","The JavaScript: marker_export.js",[747,4383,4384],{},"Here's the complete script that powers our device:",[1377,4386,4388],{"className":1941,"code":4387,"language":1943,"meta":943,"style":943},"autowatch = 1;\noutlets = 1;\n\nfunction msg_int(v) {\n  if (v === 1) bang();\n}\n\nfunction bang() {\n  try {\n    var song = new LiveAPI(\"live_set\");\n\n    // --- PROJECT NAME ---\n    var name = song.get(\"name\");\n    name = Array.isArray(name) ? name[0] : name;\n    if (!name || name === \"\") name = \"untitled\";\n    name = name.replace(/[^a-z0-9_\\-]/gi, \"_\");\n\n    // --- BPM ---\n    var bpm = song.get(\"tempo\");\n    bpm = Array.isArray(bpm) ? bpm[0] : bpm;\n\n    // --- LOCATORS ---\n    var locatorIds = song.get(\"cue_points\");\n    var sections = [];\n\n    if (Array.isArray(locatorIds)) {\n      for (var i = 0; i \u003C locatorIds.length; i++) {\n        if (typeof locatorIds[i] !== \"number\") continue;\n\n        var l = new LiveAPI(\"id \" + locatorIds[i]);\n        var label = l.get(\"name\");\n        var time = l.get(\"time\");\n\n        sections.push({\n          label: Array.isArray(label) ? label[0] : label,\n          time_seconds: Array.isArray(time) ? time[0] : time\n        });\n      }\n    }\n\n    // --- BUILD JSON ---\n    var data = {\n      project: name,\n      bpm: bpm,\n      sections: sections\n    };\n\n    var json = JSON.stringify(data, null, 2);\n\n    // Send to UI (textedit)\n    outlet(0, \"set\", json);\n\n    // Log to Max Console\n    post(\"EXPORT SUCCESS\\\\n\");\n\n  } catch (e) {\n    post(\"EXPORT ERROR:\", e.toString(), \"\\\\n\");\n  }\n}\n",[1383,4389,4390,4402,4413,4417,4433,4455,4459,4463,4473,4480,4505,4509,4514,4540,4580,4616,4659,4663,4668,4694,4728,4732,4737,4764,4777,4781,4804,4847,4883,4887,4922,4949,4976,4980,4992,5027,5062,5072,5078,5084,5089,5095,5106,5118,5130,5141,5147,5152,5184,5189,5195,5222,5227,5233,5258,5263,5280,5320,5325],{"__ignoreMap":943},[1386,4391,4392,4395,4397,4400],{"class":1388,"line":1389},[1386,4393,4394],{"class":1821},"autowatch ",[1386,4396,2544],{"class":1392},[1386,4398,4399],{"class":1435}," 1",[1386,4401,2562],{"class":1392},[1386,4403,4404,4407,4409,4411],{"class":1388,"line":944},[1386,4405,4406],{"class":1821},"outlets ",[1386,4408,2544],{"class":1392},[1386,4410,4399],{"class":1435},[1386,4412,2562],{"class":1392},[1386,4414,4415],{"class":1388,"line":1423},[1386,4416,1956],{"emptyLinePlaceholder":958},[1386,4418,4419,4421,4424,4426,4429,4431],{"class":1388,"line":1119},[1386,4420,1961],{"class":1401},[1386,4422,4423],{"class":1964}," msg_int",[1386,4425,1993],{"class":1392},[1386,4427,4428],{"class":2614},"v",[1386,4430,2242],{"class":1392},[1386,4432,1452],{"class":1392},[1386,4434,4435,4437,4439,4441,4444,4446,4448,4451,4453],{"class":1388,"line":1455},[1386,4436,2796],{"class":2672},[1386,4438,2611],{"class":1992},[1386,4440,4428],{"class":1821},[1386,4442,4443],{"class":1392}," ===",[1386,4445,4399],{"class":1435},[1386,4447,2273],{"class":1992},[1386,4449,4450],{"class":1964},"bang",[1386,4452,1968],{"class":1992},[1386,4454,2562],{"class":1392},[1386,4456,4457],{"class":1388,"line":1474},[1386,4458,1687],{"class":1392},[1386,4460,4461],{"class":1388,"line":1489},[1386,4462,1956],{"emptyLinePlaceholder":958},[1386,4464,4465,4467,4469,4471],{"class":1388,"line":1495},[1386,4466,1961],{"class":1401},[1386,4468,1965],{"class":1964},[1386,4470,1968],{"class":1392},[1386,4472,1452],{"class":1392},[1386,4474,4475,4478],{"class":1388,"line":1512},[1386,4476,4477],{"class":2672},"  try",[1386,4479,1452],{"class":1392},[1386,4481,4482,4485,4487,4489,4491,4493,4495,4497,4499,4501,4503],{"class":1388,"line":1527},[1386,4483,4484],{"class":1401},"    var",[1386,4486,2017],{"class":1821},[1386,4488,1983],{"class":1392},[1386,4490,1986],{"class":1392},[1386,4492,1989],{"class":1964},[1386,4494,1993],{"class":1992},[1386,4496,1405],{"class":1392},[1386,4498,1998],{"class":1414},[1386,4500,1405],{"class":1392},[1386,4502,2242],{"class":1992},[1386,4504,2562],{"class":1392},[1386,4506,4507],{"class":1388,"line":1566},[1386,4508,1956],{"emptyLinePlaceholder":958},[1386,4510,4511],{"class":1388,"line":1601},[1386,4512,4513],{"class":1950},"    // --- PROJECT NAME ---\n",[1386,4515,4516,4518,4520,4522,4524,4526,4528,4530,4532,4534,4536,4538],{"class":1388,"line":1637},[1386,4517,4484],{"class":1401},[1386,4519,2316],{"class":1821},[1386,4521,1983],{"class":1392},[1386,4523,2017],{"class":1821},[1386,4525,1931],{"class":1392},[1386,4527,2022],{"class":1964},[1386,4529,1993],{"class":1992},[1386,4531,1405],{"class":1392},[1386,4533,2029],{"class":1414},[1386,4535,1405],{"class":1392},[1386,4537,2242],{"class":1992},[1386,4539,2562],{"class":1392},[1386,4541,4542,4545,4547,4550,4552,4555,4557,4559,4561,4564,4566,4569,4571,4574,4576,4578],{"class":1388,"line":1643},[1386,4543,4544],{"class":1821},"    name",[1386,4546,1983],{"class":1392},[1386,4548,4549],{"class":1821}," Array",[1386,4551,1931],{"class":1392},[1386,4553,4554],{"class":1964},"isArray",[1386,4556,1993],{"class":1992},[1386,4558,2029],{"class":1821},[1386,4560,2273],{"class":1992},[1386,4562,4563],{"class":1392},"?",[1386,4565,2316],{"class":1821},[1386,4567,4568],{"class":1992},"[",[1386,4570,2415],{"class":1435},[1386,4572,4573],{"class":1992},"] ",[1386,4575,1408],{"class":1392},[1386,4577,2316],{"class":1821},[1386,4579,2562],{"class":1392},[1386,4581,4582,4584,4586,4589,4591,4594,4596,4598,4601,4603,4605,4607,4609,4612,4614],{"class":1388,"line":1664},[1386,4583,3079],{"class":2672},[1386,4585,2611],{"class":1992},[1386,4587,4588],{"class":1392},"!",[1386,4590,2029],{"class":1821},[1386,4592,4593],{"class":1392}," ||",[1386,4595,2316],{"class":1821},[1386,4597,4443],{"class":1392},[1386,4599,4600],{"class":1392}," \"\"",[1386,4602,2273],{"class":1992},[1386,4604,2029],{"class":1821},[1386,4606,1983],{"class":1392},[1386,4608,1411],{"class":1392},[1386,4610,4611],{"class":1414},"untitled",[1386,4613,1405],{"class":1392},[1386,4615,2562],{"class":1392},[1386,4617,4618,4620,4622,4624,4626,4629,4631,4634,4637,4640,4643,4646,4648,4650,4653,4655,4657],{"class":1388,"line":1684},[1386,4619,4544],{"class":1821},[1386,4621,1983],{"class":1392},[1386,4623,2316],{"class":1821},[1386,4625,1931],{"class":1392},[1386,4627,4628],{"class":1964},"replace",[1386,4630,1993],{"class":1992},[1386,4632,4633],{"class":1392},"/[^",[1386,4635,4636],{"class":1414},"a-z0-9_",[1386,4638,4639],{"class":1821},"\\-",[1386,4641,4642],{"class":1392},"]/",[1386,4644,4645],{"class":1435},"gi",[1386,4647,1549],{"class":1392},[1386,4649,1411],{"class":1392},[1386,4651,4652],{"class":1414},"_",[1386,4654,1405],{"class":1392},[1386,4656,2242],{"class":1992},[1386,4658,2562],{"class":1392},[1386,4660,4661],{"class":1388,"line":2176},[1386,4662,1956],{"emptyLinePlaceholder":958},[1386,4664,4665],{"class":1388,"line":2204},[1386,4666,4667],{"class":1950},"    // --- BPM ---\n",[1386,4669,4670,4672,4674,4676,4678,4680,4682,4684,4686,4688,4690,4692],{"class":1388,"line":2219},[1386,4671,4484],{"class":1401},[1386,4673,2329],{"class":1821},[1386,4675,1983],{"class":1392},[1386,4677,2017],{"class":1821},[1386,4679,1931],{"class":1392},[1386,4681,2022],{"class":1964},[1386,4683,1993],{"class":1992},[1386,4685,1405],{"class":1392},[1386,4687,2057],{"class":1414},[1386,4689,1405],{"class":1392},[1386,4691,2242],{"class":1992},[1386,4693,2562],{"class":1392},[1386,4695,4696,4698,4700,4702,4704,4706,4708,4710,4712,4714,4716,4718,4720,4722,4724,4726],{"class":1388,"line":2250},[1386,4697,2324],{"class":1821},[1386,4699,1983],{"class":1392},[1386,4701,4549],{"class":1821},[1386,4703,1931],{"class":1392},[1386,4705,4554],{"class":1964},[1386,4707,1993],{"class":1992},[1386,4709,1428],{"class":1821},[1386,4711,2273],{"class":1992},[1386,4713,4563],{"class":1392},[1386,4715,2329],{"class":1821},[1386,4717,4568],{"class":1992},[1386,4719,2415],{"class":1435},[1386,4721,4573],{"class":1992},[1386,4723,1408],{"class":1392},[1386,4725,2329],{"class":1821},[1386,4727,2562],{"class":1392},[1386,4729,4730],{"class":1388,"line":2279},[1386,4731,1956],{"emptyLinePlaceholder":958},[1386,4733,4734],{"class":1388,"line":2287},[1386,4735,4736],{"class":1950},"    // --- LOCATORS ---\n",[1386,4738,4739,4741,4744,4746,4748,4750,4752,4754,4756,4758,4760,4762],{"class":1388,"line":2292},[1386,4740,4484],{"class":1401},[1386,4742,4743],{"class":1821}," locatorIds",[1386,4745,1983],{"class":1392},[1386,4747,2017],{"class":1821},[1386,4749,1931],{"class":1392},[1386,4751,2022],{"class":1964},[1386,4753,1993],{"class":1992},[1386,4755,1405],{"class":1392},[1386,4757,2141],{"class":1414},[1386,4759,1405],{"class":1392},[1386,4761,2242],{"class":1992},[1386,4763,2562],{"class":1392},[1386,4765,4766,4768,4770,4772,4775],{"class":1388,"line":2298},[1386,4767,4484],{"class":1401},[1386,4769,2371],{"class":1821},[1386,4771,1983],{"class":1392},[1386,4773,4774],{"class":1992}," []",[1386,4776,2562],{"class":1392},[1386,4778,4779],{"class":1388,"line":2308},[1386,4780,1956],{"emptyLinePlaceholder":958},[1386,4782,4783,4785,4787,4790,4792,4794,4796,4799,4802],{"class":1388,"line":2321},[1386,4784,3079],{"class":2672},[1386,4786,2611],{"class":1992},[1386,4788,4789],{"class":1821},"Array",[1386,4791,1931],{"class":1392},[1386,4793,4554],{"class":1964},[1386,4795,1993],{"class":1992},[1386,4797,4798],{"class":1821},"locatorIds",[1386,4800,4801],{"class":1992},")) ",[1386,4803,1393],{"class":1392},[1386,4805,4806,4809,4811,4814,4817,4819,4821,4824,4826,4829,4831,4833,4836,4838,4840,4843,4845],{"class":1388,"line":2334},[1386,4807,4808],{"class":2672},"      for",[1386,4810,2611],{"class":1992},[1386,4812,4813],{"class":1401},"var",[1386,4815,4816],{"class":1821}," i",[1386,4818,1983],{"class":1392},[1386,4820,1507],{"class":1435},[1386,4822,4823],{"class":1392},";",[1386,4825,4816],{"class":1821},[1386,4827,4828],{"class":1392}," \u003C",[1386,4830,4743],{"class":1821},[1386,4832,1931],{"class":1392},[1386,4834,4835],{"class":1821},"length",[1386,4837,4823],{"class":1392},[1386,4839,4816],{"class":1821},[1386,4841,4842],{"class":1392},"++",[1386,4844,2273],{"class":1992},[1386,4846,1393],{"class":1392},[1386,4848,4849,4852,4854,4857,4859,4861,4864,4866,4869,4871,4874,4876,4878,4881],{"class":1388,"line":2364},[1386,4850,4851],{"class":2672},"        if",[1386,4853,2611],{"class":1992},[1386,4855,4856],{"class":1392},"typeof",[1386,4858,4743],{"class":1821},[1386,4860,4568],{"class":1992},[1386,4862,4863],{"class":1821},"i",[1386,4865,4573],{"class":1992},[1386,4867,4868],{"class":1392},"!==",[1386,4870,1411],{"class":1392},[1386,4872,4873],{"class":1414},"number",[1386,4875,1405],{"class":1392},[1386,4877,2273],{"class":1992},[1386,4879,4880],{"class":2672},"continue",[1386,4882,2562],{"class":1392},[1386,4884,4885],{"class":1388,"line":2376},[1386,4886,1956],{"emptyLinePlaceholder":958},[1386,4888,4889,4892,4895,4897,4899,4901,4903,4905,4907,4909,4911,4913,4915,4917,4920],{"class":1388,"line":2390},[1386,4890,4891],{"class":1401},"        var",[1386,4893,4894],{"class":1821}," l",[1386,4896,1983],{"class":1392},[1386,4898,1986],{"class":1392},[1386,4900,1989],{"class":1964},[1386,4902,1993],{"class":1992},[1386,4904,1405],{"class":1392},[1386,4906,2192],{"class":1414},[1386,4908,1405],{"class":1392},[1386,4910,2197],{"class":1392},[1386,4912,4743],{"class":1821},[1386,4914,4568],{"class":1992},[1386,4916,4863],{"class":1821},[1386,4918,4919],{"class":1992},"])",[1386,4921,2562],{"class":1392},[1386,4923,4924,4926,4929,4931,4933,4935,4937,4939,4941,4943,4945,4947],{"class":1388,"line":2396},[1386,4925,4891],{"class":1401},[1386,4927,4928],{"class":1821}," label",[1386,4930,1983],{"class":1392},[1386,4932,4894],{"class":1821},[1386,4934,1931],{"class":1392},[1386,4936,2022],{"class":1964},[1386,4938,1993],{"class":1992},[1386,4940,1405],{"class":1392},[1386,4942,2029],{"class":1414},[1386,4944,1405],{"class":1392},[1386,4946,2242],{"class":1992},[1386,4948,2562],{"class":1392},[1386,4950,4951,4953,4956,4958,4960,4962,4964,4966,4968,4970,4972,4974],{"class":1388,"line":2401},[1386,4952,4891],{"class":1401},[1386,4954,4955],{"class":1821}," time",[1386,4957,1983],{"class":1392},[1386,4959,4894],{"class":1821},[1386,4961,1931],{"class":1392},[1386,4963,2022],{"class":1964},[1386,4965,1993],{"class":1992},[1386,4967,1405],{"class":1392},[1386,4969,2268],{"class":1414},[1386,4971,1405],{"class":1392},[1386,4973,2242],{"class":1992},[1386,4975,2562],{"class":1392},[1386,4977,4978],{"class":1388,"line":2407},[1386,4979,1956],{"emptyLinePlaceholder":958},[1386,4981,4982,4984,4986,4988,4990],{"class":1388,"line":2439},[1386,4983,3175],{"class":1821},[1386,4985,1931],{"class":1392},[1386,4987,2212],{"class":1964},[1386,4989,1993],{"class":1992},[1386,4991,1393],{"class":1392},[1386,4993,4994,4997,4999,5001,5003,5005,5007,5009,5011,5013,5015,5017,5019,5021,5023,5025],{"class":1388,"line":2460},[1386,4995,4996],{"class":1992},"          label",[1386,4998,1408],{"class":1392},[1386,5000,4549],{"class":1821},[1386,5002,1931],{"class":1392},[1386,5004,4554],{"class":1964},[1386,5006,1993],{"class":1992},[1386,5008,1535],{"class":1821},[1386,5010,2273],{"class":1992},[1386,5012,4563],{"class":1392},[1386,5014,4928],{"class":1821},[1386,5016,4568],{"class":1992},[1386,5018,2415],{"class":1435},[1386,5020,4573],{"class":1992},[1386,5022,1408],{"class":1392},[1386,5024,4928],{"class":1821},[1386,5026,1420],{"class":1392},[1386,5028,5030,5033,5035,5037,5039,5041,5043,5045,5047,5049,5051,5053,5055,5057,5059],{"class":1388,"line":5029},36,[1386,5031,5032],{"class":1992},"          time_seconds",[1386,5034,1408],{"class":1392},[1386,5036,4549],{"class":1821},[1386,5038,1931],{"class":1392},[1386,5040,4554],{"class":1964},[1386,5042,1993],{"class":1992},[1386,5044,2268],{"class":1821},[1386,5046,2273],{"class":1992},[1386,5048,4563],{"class":1392},[1386,5050,4955],{"class":1821},[1386,5052,4568],{"class":1992},[1386,5054,2415],{"class":1435},[1386,5056,4573],{"class":1992},[1386,5058,1408],{"class":1392},[1386,5060,5061],{"class":1821}," time\n",[1386,5063,5065,5068,5070],{"class":1388,"line":5064},37,[1386,5066,5067],{"class":1392},"        }",[1386,5069,2242],{"class":1992},[1386,5071,2562],{"class":1392},[1386,5073,5075],{"class":1388,"line":5074},38,[1386,5076,5077],{"class":1392},"      }\n",[1386,5079,5081],{"class":1388,"line":5080},39,[1386,5082,5083],{"class":1392},"    }\n",[1386,5085,5087],{"class":1388,"line":5086},40,[1386,5088,1956],{"emptyLinePlaceholder":958},[1386,5090,5092],{"class":1388,"line":5091},41,[1386,5093,5094],{"class":1950},"    // --- BUILD JSON ---\n",[1386,5096,5098,5100,5102,5104],{"class":1388,"line":5097},42,[1386,5099,4484],{"class":1401},[1386,5101,3040],{"class":1821},[1386,5103,1983],{"class":1392},[1386,5105,1452],{"class":1392},[1386,5107,5109,5112,5114,5116],{"class":1388,"line":5108},43,[1386,5110,5111],{"class":1992},"      project",[1386,5113,1408],{"class":1392},[1386,5115,2316],{"class":1821},[1386,5117,1420],{"class":1392},[1386,5119,5121,5124,5126,5128],{"class":1388,"line":5120},44,[1386,5122,5123],{"class":1992},"      bpm",[1386,5125,1408],{"class":1392},[1386,5127,2329],{"class":1821},[1386,5129,1420],{"class":1392},[1386,5131,5133,5136,5138],{"class":1388,"line":5132},45,[1386,5134,5135],{"class":1992},"      sections",[1386,5137,1408],{"class":1392},[1386,5139,5140],{"class":1821}," sections\n",[1386,5142,5144],{"class":1388,"line":5143},46,[1386,5145,5146],{"class":1392},"    };\n",[1386,5148,5150],{"class":1388,"line":5149},47,[1386,5151,1956],{"emptyLinePlaceholder":958},[1386,5153,5155,5157,5160,5162,5164,5166,5168,5170,5172,5174,5177,5180,5182],{"class":1388,"line":5154},48,[1386,5156,4484],{"class":1401},[1386,5158,5159],{"class":1821}," json",[1386,5161,1983],{"class":1392},[1386,5163,2420],{"class":1821},[1386,5165,1931],{"class":1392},[1386,5167,2425],{"class":1964},[1386,5169,1993],{"class":1992},[1386,5171,2974],{"class":1821},[1386,5173,1549],{"class":1392},[1386,5175,5176],{"class":1392}," null,",[1386,5178,5179],{"class":1435}," 2",[1386,5181,2242],{"class":1992},[1386,5183,2562],{"class":1392},[1386,5185,5187],{"class":1388,"line":5186},49,[1386,5188,1956],{"emptyLinePlaceholder":958},[1386,5190,5192],{"class":1388,"line":5191},50,[1386,5193,5194],{"class":1950},"    // Send to UI (textedit)\n",[1386,5196,5198,5201,5203,5205,5207,5209,5212,5214,5216,5218,5220],{"class":1388,"line":5197},51,[1386,5199,5200],{"class":1964},"    outlet",[1386,5202,1993],{"class":1992},[1386,5204,2415],{"class":1435},[1386,5206,1549],{"class":1392},[1386,5208,1411],{"class":1392},[1386,5210,5211],{"class":1414},"set",[1386,5213,1405],{"class":1392},[1386,5215,1549],{"class":1392},[1386,5217,5159],{"class":1821},[1386,5219,2242],{"class":1992},[1386,5221,2562],{"class":1392},[1386,5223,5225],{"class":1388,"line":5224},52,[1386,5226,1956],{"emptyLinePlaceholder":958},[1386,5228,5230],{"class":1388,"line":5229},53,[1386,5231,5232],{"class":1950},"    // Log to Max Console\n",[1386,5234,5236,5239,5241,5243,5246,5249,5252,5254,5256],{"class":1388,"line":5235},54,[1386,5237,5238],{"class":1964},"    post",[1386,5240,1993],{"class":1992},[1386,5242,1405],{"class":1392},[1386,5244,5245],{"class":1414},"EXPORT SUCCESS",[1386,5247,5248],{"class":1821},"\\\\",[1386,5250,5251],{"class":1414},"n",[1386,5253,1405],{"class":1392},[1386,5255,2242],{"class":1992},[1386,5257,2562],{"class":1392},[1386,5259,5261],{"class":1388,"line":5260},55,[1386,5262,1956],{"emptyLinePlaceholder":958},[1386,5264,5266,5268,5271,5273,5276,5278],{"class":1388,"line":5265},56,[1386,5267,2753],{"class":1392},[1386,5269,5270],{"class":2672}," catch",[1386,5272,2611],{"class":1992},[1386,5274,5275],{"class":1821},"e",[1386,5277,2273],{"class":1992},[1386,5279,1393],{"class":1392},[1386,5281,5283,5285,5287,5289,5292,5294,5296,5299,5301,5304,5306,5308,5310,5312,5314,5316,5318],{"class":1388,"line":5282},57,[1386,5284,5238],{"class":1964},[1386,5286,1993],{"class":1992},[1386,5288,1405],{"class":1392},[1386,5290,5291],{"class":1414},"EXPORT ERROR:",[1386,5293,1405],{"class":1392},[1386,5295,1549],{"class":1392},[1386,5297,5298],{"class":1821}," e",[1386,5300,1931],{"class":1392},[1386,5302,5303],{"class":1964},"toString",[1386,5305,1968],{"class":1992},[1386,5307,1549],{"class":1392},[1386,5309,1411],{"class":1392},[1386,5311,5248],{"class":1821},[1386,5313,5251],{"class":1414},[1386,5315,1405],{"class":1392},[1386,5317,2242],{"class":1992},[1386,5319,2562],{"class":1392},[1386,5321,5323],{"class":1388,"line":5322},58,[1386,5324,2393],{"class":1392},[1386,5326,5328],{"class":1388,"line":5327},59,[1386,5329,1687],{"class":1392},[1295,5331,5333],{"id":5332},"key-concepts-explained","Key Concepts Explained",[747,5335,5336,5339],{},[754,5337,5338],{},"autowatch = 1"," - Tells Max to reload the script automatically when the file changes. Essential during development.",[747,5341,5342,5345],{},[754,5343,5344],{},"LiveAPI"," - The bridge between JavaScript and Ableton's Live Object Model. We use it to access:",[837,5347,5348,5353,5358],{},[800,5349,5350,5352],{},[1383,5351,1998],{}," - The current project",[800,5354,5355,5357],{},[1383,5356,2057],{}," - Current BPM",[800,5359,5360,5362],{},[1383,5361,2141],{}," - Array of locator IDs",[747,5364,5365,5368,5369,1931],{},[754,5366,5367],{},"Array handling"," - LiveAPI often returns single values wrapped in arrays, so we consistently check with ",[1383,5370,2471],{},[747,5372,5373,5376,5377,5379],{},[754,5374,5375],{},"outlet(0, \"set\", json)"," - The \"set\" message tells ",[1383,5378,4227],{}," to display the text without triggering its output.",[1295,5381,5383],{"id":5382},"viewing-the-output","Viewing the Output",[747,5385,5386],{},"The JSON output appears in the Max Console window:",[764,5388,3387,5389],{"style":4235},[4237,5390,4240,5391,4240,5396,3387],{"style":4239},[1162,5392],{"src":5393,"alt":5394,"style":5395},"/images/blog/musictechlab_blog_ableton-locators-json-console.webp","Max Console showing JSON export output","max-width: 480px; width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block;",[4247,5397,5398],{"style":4249},"Max Console displaying the exported JSON with BPM and sections",[759,5400,5402],{"id":5401},"troubleshooting-common-issues","Troubleshooting Common Issues",[1295,5404,5406],{"id":5405},"js-cant-find-file-marker_exportjs","\"js: can't find file marker_export.js\"",[747,5408,5409],{},"Max can't locate your JavaScript file.",[747,5411,5412],{},[754,5413,5414],{},"Solution:",[797,5416,5417,5424,5427,5434],{},[800,5418,5419,5420,5423],{},"Right-click on the ",[1383,5421,5422],{},"js"," object in Max",[800,5425,5426],{},"Select \"Open marker_export.js\"",[800,5428,5429,5430,5433],{},"Save As... to the same folder as your ",[1383,5431,5432],{},".amxd"," file",[800,5435,5436,5437,5439],{},"Ensure the object text is just ",[1383,5438,4221],{}," (no paths)",[1295,5441,5443],{"id":5442},"js-no-function-msg_int","\"js: no function msg_int\"",[747,5445,5446],{},"The button sends an integer, but your script doesn't have a handler for it.",[747,5448,5449,5451],{},[754,5450,5414],{}," Add this function to your script:",[1377,5453,5455],{"className":1941,"code":5454,"language":1943,"meta":943,"style":943},"function msg_int(v) {\n  if (v === 1) bang();\n}\n",[1383,5456,5457,5471,5491],{"__ignoreMap":943},[1386,5458,5459,5461,5463,5465,5467,5469],{"class":1388,"line":1389},[1386,5460,1961],{"class":1401},[1386,5462,4423],{"class":1964},[1386,5464,1993],{"class":1392},[1386,5466,4428],{"class":2614},[1386,5468,2242],{"class":1392},[1386,5470,1452],{"class":1392},[1386,5472,5473,5475,5477,5479,5481,5483,5485,5487,5489],{"class":1388,"line":944},[1386,5474,2796],{"class":2672},[1386,5476,2611],{"class":1992},[1386,5478,4428],{"class":1821},[1386,5480,4443],{"class":1392},[1386,5482,4399],{"class":1435},[1386,5484,2273],{"class":1992},[1386,5486,4450],{"class":1964},[1386,5488,1968],{"class":1992},[1386,5490,2562],{"class":1392},[1386,5492,5493],{"class":1388,"line":1423},[1386,5494,1687],{"class":1392},[1295,5496,5498],{"id":5497},"song-object-has-no-attribute-locators","\"Song object has no attribute 'locators'\"",[747,5500,5501],{},"The LiveAPI path varies between Ableton versions.",[747,5503,5504,5506,5507,5509],{},[754,5505,5414],{}," Use ",[1383,5508,2141],{}," instead:",[1377,5511,5513],{"className":1941,"code":5512,"language":1943,"meta":943,"style":943},"var locatorIds = song.get(\"cue_points\");\n",[1383,5514,5515],{"__ignoreMap":943},[1386,5516,5517,5519,5522,5524,5526,5528,5530,5532,5534,5536,5538,5540],{"class":1388,"line":1389},[1386,5518,4813],{"class":1401},[1386,5520,5521],{"class":1821}," locatorIds ",[1386,5523,2544],{"class":1392},[1386,5525,2017],{"class":1821},[1386,5527,1931],{"class":1392},[1386,5529,2022],{"class":1964},[1386,5531,1993],{"class":1821},[1386,5533,1405],{"class":1392},[1386,5535,2141],{"class":1414},[1386,5537,1405],{"class":1392},[1386,5539,2242],{"class":1821},[1386,5541,2562],{"class":1392},[1295,5543,5545],{"id":5544},"sendmessage-error-2-bad-parameter-value","\"SendMessage error 2: Bad parameter value\"",[764,5547,3387,5548],{"style":4235},[4237,5549,4240,5550,4240,5555,3387],{"style":4239},[1162,5551],{"src":5552,"alt":5553,"style":5554},"/images/blog/musictechlab_blog_ableton-locators-json-error.webp","SendMessage error in Max Console","max-width: 400px; width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block;",[4247,5556,5557],{"style":4249},"Typical SendMessage errors when LiveAPI path is incorrect",[747,5559,5560],{},"Usually caused by:",[837,5562,5563,5566,5569],{},[800,5564,5565],{},"Invalid LiveAPI path",[800,5567,5568],{},"Querying a property that doesn't exist",[800,5570,5571],{},"Non-numeric values in the locator ID array",[747,5573,5574,5576],{},[754,5575,5414],{}," Filter IDs properly:",[1377,5578,5580],{"className":1941,"code":5579,"language":1943,"meta":943,"style":943},"if (typeof locatorIds[i] !== \"number\") continue;\n",[1383,5581,5582],{"__ignoreMap":943},[1386,5583,5584,5587,5589,5591,5594,5596,5598,5600,5602,5604,5606],{"class":1388,"line":1389},[1386,5585,5586],{"class":2672},"if",[1386,5588,2611],{"class":1821},[1386,5590,4856],{"class":1392},[1386,5592,5593],{"class":1821}," locatorIds[i] ",[1386,5595,4868],{"class":1392},[1386,5597,1411],{"class":1392},[1386,5599,4873],{"class":1414},[1386,5601,1405],{"class":1392},[1386,5603,2273],{"class":1821},[1386,5605,4880],{"class":2672},[1386,5607,2562],{"class":1392},[759,5609,5611],{"id":5610},"adding-file-export-optional","Adding File Export (Optional)",[747,5613,5614],{},"To save the JSON to disk, extend the script:",[1377,5616,5618],{"className":1941,"code":5617,"language":1943,"meta":943,"style":943},"// --- FILE SAVE ---\nvar folder = \"~/Documents/AbletonExports/\";\nvar f = new File(folder + name + \".json\", \"write\");\n\nif (f.isopen) {\n  f.writestring(json);\n  f.close();\n  post(\"Saved to:\", folder + name + \".json\", \"\\\\n\");\n} else {\n  post(\"EXPORT ERROR: cannot write file\\\\n\");\n}\n",[1383,5619,5620,5625,5643,5688,5692,5706,5724,5737,5782,5790,5811],{"__ignoreMap":943},[1386,5621,5622],{"class":1388,"line":1389},[1386,5623,5624],{"class":1950},"// --- FILE SAVE ---\n",[1386,5626,5627,5629,5632,5634,5636,5639,5641],{"class":1388,"line":944},[1386,5628,4813],{"class":1401},[1386,5630,5631],{"class":1821}," folder ",[1386,5633,2544],{"class":1392},[1386,5635,1411],{"class":1392},[1386,5637,5638],{"class":1414},"~/Documents/AbletonExports/",[1386,5640,1405],{"class":1392},[1386,5642,2562],{"class":1392},[1386,5644,5645,5647,5650,5652,5654,5657,5660,5663,5666,5668,5670,5673,5675,5677,5679,5682,5684,5686],{"class":1388,"line":1423},[1386,5646,4813],{"class":1401},[1386,5648,5649],{"class":1821}," f ",[1386,5651,2544],{"class":1392},[1386,5653,1986],{"class":1392},[1386,5655,5656],{"class":1964}," File",[1386,5658,5659],{"class":1821},"(folder ",[1386,5661,5662],{"class":1392},"+",[1386,5664,5665],{"class":1821}," name ",[1386,5667,5662],{"class":1392},[1386,5669,1411],{"class":1392},[1386,5671,5672],{"class":1414},".json",[1386,5674,1405],{"class":1392},[1386,5676,1549],{"class":1392},[1386,5678,1411],{"class":1392},[1386,5680,5681],{"class":1414},"write",[1386,5683,1405],{"class":1392},[1386,5685,2242],{"class":1821},[1386,5687,2562],{"class":1392},[1386,5689,5690],{"class":1388,"line":1119},[1386,5691,1956],{"emptyLinePlaceholder":958},[1386,5693,5694,5696,5699,5701,5704],{"class":1388,"line":1455},[1386,5695,5586],{"class":2672},[1386,5697,5698],{"class":1821}," (f",[1386,5700,1931],{"class":1392},[1386,5702,5703],{"class":1821},"isopen) ",[1386,5705,1393],{"class":1392},[1386,5707,5708,5711,5713,5716,5718,5720,5722],{"class":1388,"line":1474},[1386,5709,5710],{"class":1821},"  f",[1386,5712,1931],{"class":1392},[1386,5714,5715],{"class":1964},"writestring",[1386,5717,1993],{"class":1992},[1386,5719,1381],{"class":1821},[1386,5721,2242],{"class":1992},[1386,5723,2562],{"class":1392},[1386,5725,5726,5728,5730,5733,5735],{"class":1388,"line":1489},[1386,5727,5710],{"class":1821},[1386,5729,1931],{"class":1392},[1386,5731,5732],{"class":1964},"close",[1386,5734,1968],{"class":1992},[1386,5736,2562],{"class":1392},[1386,5738,5739,5742,5744,5746,5749,5751,5753,5756,5758,5760,5762,5764,5766,5768,5770,5772,5774,5776,5778,5780],{"class":1388,"line":1495},[1386,5740,5741],{"class":1964},"  post",[1386,5743,1993],{"class":1992},[1386,5745,1405],{"class":1392},[1386,5747,5748],{"class":1414},"Saved to:",[1386,5750,1405],{"class":1392},[1386,5752,1549],{"class":1392},[1386,5754,5755],{"class":1821}," folder",[1386,5757,2197],{"class":1392},[1386,5759,2316],{"class":1821},[1386,5761,2197],{"class":1392},[1386,5763,1411],{"class":1392},[1386,5765,5672],{"class":1414},[1386,5767,1405],{"class":1392},[1386,5769,1549],{"class":1392},[1386,5771,1411],{"class":1392},[1386,5773,5248],{"class":1821},[1386,5775,5251],{"class":1414},[1386,5777,1405],{"class":1392},[1386,5779,2242],{"class":1992},[1386,5781,2562],{"class":1392},[1386,5783,5784,5786,5788],{"class":1388,"line":1512},[1386,5785,2896],{"class":1392},[1386,5787,2848],{"class":2672},[1386,5789,1452],{"class":1392},[1386,5791,5792,5794,5796,5798,5801,5803,5805,5807,5809],{"class":1388,"line":1527},[1386,5793,5741],{"class":1964},[1386,5795,1993],{"class":1992},[1386,5797,1405],{"class":1392},[1386,5799,5800],{"class":1414},"EXPORT ERROR: cannot write file",[1386,5802,5248],{"class":1821},[1386,5804,5251],{"class":1414},[1386,5806,1405],{"class":1392},[1386,5808,2242],{"class":1992},[1386,5810,2562],{"class":1392},[1386,5812,5813],{"class":1388,"line":1566},[1386,5814,1687],{"class":1392},[747,5816,5817,5820,5821,5824],{},[754,5818,5819],{},"Note:"," The ",[1383,5822,5823],{},"~"," path expansion can be inconsistent in Max/JS. For reliability, either:",[837,5826,5827,5830,5833],{},[800,5828,5829],{},"Use absolute paths",[800,5831,5832],{},"Save to the project folder",[800,5834,5835],{},"Create the target directory manually first",[759,5837,5839],{"id":5838},"packaging-for-distribution","Packaging for Distribution",[1295,5841,5843],{"id":5842},"the-simple-way-recommended-for-mvp","The Simple Way (Recommended for MVP)",[747,5845,5846],{},"Create a folder with both files:",[1377,5848,5851],{"className":5849,"code":5850,"language":2500},[2498],"MTL_LocatorsToJSON/\n├── MTL_LocatorsToJSON.amxd\n├── marker_export.js\n└── README.txt\n",[1383,5852,5850],{"__ignoreMap":943},[747,5854,5855],{},"Compress to ZIP and share. Recipients should:",[797,5857,5858,5861,5867],{},[800,5859,5860],{},"Unzip the folder",[800,5862,5863,5864],{},"Copy to: ",[1383,5865,5866],{},"~/Music/Ableton/User Library/Presets/MIDI Effects/Max MIDI Effect/",[800,5868,5869],{},"Restart Ableton Live (or refresh the Browser)",[1295,5871,5873],{"id":5872},"why-not-alp-ableton-pack","Why Not .alp (Ableton Pack)?",[764,5875,3387,5876],{"style":4235},[4237,5877,4240,5878,4240,5883,3387],{"style":4239},[1162,5879],{"src":5880,"alt":5881,"style":5882},"/images/blog/musictechlab_blog_ableton-locators-json-pack-error.webp","Ableton Pack error - This is not a valid Pack","max-width: 500px; width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block;",[4247,5884,5885],{"style":4249},"\"This is not a valid Pack\" - why we use ZIP instead of .alp",[747,5887,2505,5888,5891,5892,5895],{},[1383,5889,5890],{},".alp"," format is ",[754,5893,5894],{},"not"," a simple ZIP with a different extension. Creating valid Packs requires Ableton's specific export workflow, which varies between Live versions. For quick distribution, a ZIP folder is more reliable.",[1295,5897,5899],{"id":5898},"project-folder-structure","Project Folder Structure",[764,5901,3387,5902],{"style":4235},[4237,5903,4240,5904,4240,5908,3387],{"style":4239},[1162,5905],{"src":5906,"alt":5907,"style":5554},"/images/blog/musictechlab_blog_ableton-locators-json-folder.webp","Finder showing the project folder structure",[4247,5909,5910],{"style":4249},"Project folder with the .amxd device and JS file",[759,5912,5914],{"id":5913},"usage-instructions","Usage Instructions",[764,5916,3387,5917],{"style":4235},[4237,5918,4240,5919,4240,5924,3387],{"style":4239},[1162,5920],{"src":5921,"alt":5922,"style":5923},"/images/blog/musictechlab_blog_ableton-locators-json-browser.webp","Device visible in Ableton Live browser","max-width: 360px; width: 100%; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block;",[4247,5925,5926],{"style":4249},"The device appears in Ableton's Browser under Max MIDI Effect",[797,5928,5929,5935,5941,5947,5952],{},[800,5930,5931,5934],{},[754,5932,5933],{},"Add the device"," to any MIDI track",[800,5936,5937,5940],{},[754,5938,5939],{},"Create locators"," in the Arrangement view (right-click → Add Locator, or Ctrl/Cmd+Shift+L)",[800,5942,5943,5946],{},[754,5944,5945],{},"Name your locators"," (INTRO, VERSE, CHORUS, etc.)",[800,5948,5949],{},[754,5950,5951],{},"Click EXPORT JSON",[800,5953,5954,5957],{},[754,5955,5956],{},"Copy the JSON"," from the text display or find it in your export folder",[759,5959,5961],{"id":5960},"integration-with-ai-workflows","Integration with AI Workflows",[747,5963,5964,5965,5968],{},"This JSON format is designed to be compatible with our ",[889,5966,5967],{"href":101},"song structure analysis pipeline",". You can:",[797,5970,5971,5976,5982,5988],{},[800,5972,5973,5975],{},[754,5974,3020],{}," manually-annotated structures from Ableton",[800,5977,5978,5981],{},[754,5979,5980],{},"Compare"," with AI-detected structures",[800,5983,5984,5987],{},[754,5985,5986],{},"Train"," custom models on your annotations",[800,5989,5990,5993],{},[754,5991,5992],{},"Import"," AI-generated structures back into your DAW",[759,5995,3721],{"id":3720},[747,5997,5998],{},"This MVP opens several possibilities:",[1179,6000,6001,6010],{},[1182,6002,6003],{},[1185,6004,6005,6008],{},[1188,6006,6007],{},"Enhancement",[1188,6009,3324],{},[1195,6011,6012,6022,6032,6042,6052],{},[1185,6013,6014,6019],{},[1200,6015,6016],{},[754,6017,6018],{},"Bidirectional sync",[1200,6020,6021],{},"Import JSON to create locators",[1185,6023,6024,6029],{},[1200,6025,6026],{},[754,6027,6028],{},"Audio Effect version",[1200,6030,6031],{},"Support audio tracks, not just MIDI",[1185,6033,6034,6039],{},[1200,6035,6036],{},[754,6037,6038],{},"Real-time export",[1200,6040,6041],{},"Auto-export on locator changes",[1185,6043,6044,6049],{},[1200,6045,6046],{},[754,6047,6048],{},"Cloud sync",[1200,6050,6051],{},"Push to API endpoint directly",[1185,6053,6054,6059],{},[1200,6055,6056],{},[754,6057,6058],{},"Time signature support",[1200,6060,6061],{},"Include meter changes",[759,6063,6065],{"id":6064},"complete-code-reference","Complete Code Reference",[747,6067,6068],{},"The final working script:",[1377,6070,6072],{"className":1941,"code":6071,"language":1943,"meta":943,"style":943},"autowatch = 1;\noutlets = 1;\n\nfunction msg_int(v) {\n  if (v === 1) bang();\n}\n\nfunction bang() {\n  try {\n    var song = new LiveAPI(\"live_set\");\n\n    // PROJECT NAME\n    var name = song.get(\"name\");\n    name = Array.isArray(name) ? name[0] : name;\n    if (!name || name === \"\") name = \"untitled\";\n    name = name.replace(/[^a-z0-9_\\-]/gi, \"_\");\n\n    // BPM\n    var bpm = song.get(\"tempo\");\n    bpm = Array.isArray(bpm) ? bpm[0] : bpm;\n\n    // LOCATORS\n    var locatorIds = song.get(\"cue_points\");\n    var sections = [];\n\n    if (Array.isArray(locatorIds)) {\n      for (var i = 0; i \u003C locatorIds.length; i++) {\n        if (typeof locatorIds[i] !== \"number\") continue;\n\n        var l = new LiveAPI(\"id \" + locatorIds[i]);\n        var label = l.get(\"name\");\n        var time = l.get(\"time\");\n\n        sections.push({\n          label: Array.isArray(label) ? label[0] : label,\n          time_seconds: Array.isArray(time) ? time[0] : time\n        });\n      }\n    }\n\n    // JSON OUTPUT\n    var data = {\n      project: name,\n      bpm: bpm,\n      sections: sections\n    };\n\n    var json = JSON.stringify(data, null, 2);\n    outlet(0, \"set\", json);\n\n    // OPTIONAL: File save\n    var folder = \"~/Documents/AbletonExports/\";\n    var f = new File(folder + name + \".json\", \"write\");\n    if (f.isopen) {\n      f.writestring(json);\n      f.close();\n    }\n\n  } catch (e) {\n    post(\"EXPORT ERROR:\", e.toString(), \"\\\\n\");\n  }\n}\n",[1383,6073,6074,6084,6094,6098,6112,6132,6136,6140,6150,6156,6180,6184,6189,6215,6249,6281,6317,6321,6326,6352,6386,6390,6395,6421,6433,6437,6457,6493,6523,6527,6559,6585,6611,6615,6627,6661,6693,6701,6705,6709,6713,6718,6728,6738,6748,6756,6760,6764,6792,6816,6820,6825,6841,6883,6901,6918,6930,6934,6938,6952,6989,6994],{"__ignoreMap":943},[1386,6075,6076,6078,6080,6082],{"class":1388,"line":1389},[1386,6077,4394],{"class":1821},[1386,6079,2544],{"class":1392},[1386,6081,4399],{"class":1435},[1386,6083,2562],{"class":1392},[1386,6085,6086,6088,6090,6092],{"class":1388,"line":944},[1386,6087,4406],{"class":1821},[1386,6089,2544],{"class":1392},[1386,6091,4399],{"class":1435},[1386,6093,2562],{"class":1392},[1386,6095,6096],{"class":1388,"line":1423},[1386,6097,1956],{"emptyLinePlaceholder":958},[1386,6099,6100,6102,6104,6106,6108,6110],{"class":1388,"line":1119},[1386,6101,1961],{"class":1401},[1386,6103,4423],{"class":1964},[1386,6105,1993],{"class":1392},[1386,6107,4428],{"class":2614},[1386,6109,2242],{"class":1392},[1386,6111,1452],{"class":1392},[1386,6113,6114,6116,6118,6120,6122,6124,6126,6128,6130],{"class":1388,"line":1455},[1386,6115,2796],{"class":2672},[1386,6117,2611],{"class":1992},[1386,6119,4428],{"class":1821},[1386,6121,4443],{"class":1392},[1386,6123,4399],{"class":1435},[1386,6125,2273],{"class":1992},[1386,6127,4450],{"class":1964},[1386,6129,1968],{"class":1992},[1386,6131,2562],{"class":1392},[1386,6133,6134],{"class":1388,"line":1474},[1386,6135,1687],{"class":1392},[1386,6137,6138],{"class":1388,"line":1489},[1386,6139,1956],{"emptyLinePlaceholder":958},[1386,6141,6142,6144,6146,6148],{"class":1388,"line":1495},[1386,6143,1961],{"class":1401},[1386,6145,1965],{"class":1964},[1386,6147,1968],{"class":1392},[1386,6149,1452],{"class":1392},[1386,6151,6152,6154],{"class":1388,"line":1512},[1386,6153,4477],{"class":2672},[1386,6155,1452],{"class":1392},[1386,6157,6158,6160,6162,6164,6166,6168,6170,6172,6174,6176,6178],{"class":1388,"line":1527},[1386,6159,4484],{"class":1401},[1386,6161,2017],{"class":1821},[1386,6163,1983],{"class":1392},[1386,6165,1986],{"class":1392},[1386,6167,1989],{"class":1964},[1386,6169,1993],{"class":1992},[1386,6171,1405],{"class":1392},[1386,6173,1998],{"class":1414},[1386,6175,1405],{"class":1392},[1386,6177,2242],{"class":1992},[1386,6179,2562],{"class":1392},[1386,6181,6182],{"class":1388,"line":1566},[1386,6183,1956],{"emptyLinePlaceholder":958},[1386,6185,6186],{"class":1388,"line":1601},[1386,6187,6188],{"class":1950},"    // PROJECT NAME\n",[1386,6190,6191,6193,6195,6197,6199,6201,6203,6205,6207,6209,6211,6213],{"class":1388,"line":1637},[1386,6192,4484],{"class":1401},[1386,6194,2316],{"class":1821},[1386,6196,1983],{"class":1392},[1386,6198,2017],{"class":1821},[1386,6200,1931],{"class":1392},[1386,6202,2022],{"class":1964},[1386,6204,1993],{"class":1992},[1386,6206,1405],{"class":1392},[1386,6208,2029],{"class":1414},[1386,6210,1405],{"class":1392},[1386,6212,2242],{"class":1992},[1386,6214,2562],{"class":1392},[1386,6216,6217,6219,6221,6223,6225,6227,6229,6231,6233,6235,6237,6239,6241,6243,6245,6247],{"class":1388,"line":1643},[1386,6218,4544],{"class":1821},[1386,6220,1983],{"class":1392},[1386,6222,4549],{"class":1821},[1386,6224,1931],{"class":1392},[1386,6226,4554],{"class":1964},[1386,6228,1993],{"class":1992},[1386,6230,2029],{"class":1821},[1386,6232,2273],{"class":1992},[1386,6234,4563],{"class":1392},[1386,6236,2316],{"class":1821},[1386,6238,4568],{"class":1992},[1386,6240,2415],{"class":1435},[1386,6242,4573],{"class":1992},[1386,6244,1408],{"class":1392},[1386,6246,2316],{"class":1821},[1386,6248,2562],{"class":1392},[1386,6250,6251,6253,6255,6257,6259,6261,6263,6265,6267,6269,6271,6273,6275,6277,6279],{"class":1388,"line":1664},[1386,6252,3079],{"class":2672},[1386,6254,2611],{"class":1992},[1386,6256,4588],{"class":1392},[1386,6258,2029],{"class":1821},[1386,6260,4593],{"class":1392},[1386,6262,2316],{"class":1821},[1386,6264,4443],{"class":1392},[1386,6266,4600],{"class":1392},[1386,6268,2273],{"class":1992},[1386,6270,2029],{"class":1821},[1386,6272,1983],{"class":1392},[1386,6274,1411],{"class":1392},[1386,6276,4611],{"class":1414},[1386,6278,1405],{"class":1392},[1386,6280,2562],{"class":1392},[1386,6282,6283,6285,6287,6289,6291,6293,6295,6297,6299,6301,6303,6305,6307,6309,6311,6313,6315],{"class":1388,"line":1684},[1386,6284,4544],{"class":1821},[1386,6286,1983],{"class":1392},[1386,6288,2316],{"class":1821},[1386,6290,1931],{"class":1392},[1386,6292,4628],{"class":1964},[1386,6294,1993],{"class":1992},[1386,6296,4633],{"class":1392},[1386,6298,4636],{"class":1414},[1386,6300,4639],{"class":1821},[1386,6302,4642],{"class":1392},[1386,6304,4645],{"class":1435},[1386,6306,1549],{"class":1392},[1386,6308,1411],{"class":1392},[1386,6310,4652],{"class":1414},[1386,6312,1405],{"class":1392},[1386,6314,2242],{"class":1992},[1386,6316,2562],{"class":1392},[1386,6318,6319],{"class":1388,"line":2176},[1386,6320,1956],{"emptyLinePlaceholder":958},[1386,6322,6323],{"class":1388,"line":2204},[1386,6324,6325],{"class":1950},"    // BPM\n",[1386,6327,6328,6330,6332,6334,6336,6338,6340,6342,6344,6346,6348,6350],{"class":1388,"line":2219},[1386,6329,4484],{"class":1401},[1386,6331,2329],{"class":1821},[1386,6333,1983],{"class":1392},[1386,6335,2017],{"class":1821},[1386,6337,1931],{"class":1392},[1386,6339,2022],{"class":1964},[1386,6341,1993],{"class":1992},[1386,6343,1405],{"class":1392},[1386,6345,2057],{"class":1414},[1386,6347,1405],{"class":1392},[1386,6349,2242],{"class":1992},[1386,6351,2562],{"class":1392},[1386,6353,6354,6356,6358,6360,6362,6364,6366,6368,6370,6372,6374,6376,6378,6380,6382,6384],{"class":1388,"line":2250},[1386,6355,2324],{"class":1821},[1386,6357,1983],{"class":1392},[1386,6359,4549],{"class":1821},[1386,6361,1931],{"class":1392},[1386,6363,4554],{"class":1964},[1386,6365,1993],{"class":1992},[1386,6367,1428],{"class":1821},[1386,6369,2273],{"class":1992},[1386,6371,4563],{"class":1392},[1386,6373,2329],{"class":1821},[1386,6375,4568],{"class":1992},[1386,6377,2415],{"class":1435},[1386,6379,4573],{"class":1992},[1386,6381,1408],{"class":1392},[1386,6383,2329],{"class":1821},[1386,6385,2562],{"class":1392},[1386,6387,6388],{"class":1388,"line":2279},[1386,6389,1956],{"emptyLinePlaceholder":958},[1386,6391,6392],{"class":1388,"line":2287},[1386,6393,6394],{"class":1950},"    // LOCATORS\n",[1386,6396,6397,6399,6401,6403,6405,6407,6409,6411,6413,6415,6417,6419],{"class":1388,"line":2292},[1386,6398,4484],{"class":1401},[1386,6400,4743],{"class":1821},[1386,6402,1983],{"class":1392},[1386,6404,2017],{"class":1821},[1386,6406,1931],{"class":1392},[1386,6408,2022],{"class":1964},[1386,6410,1993],{"class":1992},[1386,6412,1405],{"class":1392},[1386,6414,2141],{"class":1414},[1386,6416,1405],{"class":1392},[1386,6418,2242],{"class":1992},[1386,6420,2562],{"class":1392},[1386,6422,6423,6425,6427,6429,6431],{"class":1388,"line":2298},[1386,6424,4484],{"class":1401},[1386,6426,2371],{"class":1821},[1386,6428,1983],{"class":1392},[1386,6430,4774],{"class":1992},[1386,6432,2562],{"class":1392},[1386,6434,6435],{"class":1388,"line":2308},[1386,6436,1956],{"emptyLinePlaceholder":958},[1386,6438,6439,6441,6443,6445,6447,6449,6451,6453,6455],{"class":1388,"line":2321},[1386,6440,3079],{"class":2672},[1386,6442,2611],{"class":1992},[1386,6444,4789],{"class":1821},[1386,6446,1931],{"class":1392},[1386,6448,4554],{"class":1964},[1386,6450,1993],{"class":1992},[1386,6452,4798],{"class":1821},[1386,6454,4801],{"class":1992},[1386,6456,1393],{"class":1392},[1386,6458,6459,6461,6463,6465,6467,6469,6471,6473,6475,6477,6479,6481,6483,6485,6487,6489,6491],{"class":1388,"line":2334},[1386,6460,4808],{"class":2672},[1386,6462,2611],{"class":1992},[1386,6464,4813],{"class":1401},[1386,6466,4816],{"class":1821},[1386,6468,1983],{"class":1392},[1386,6470,1507],{"class":1435},[1386,6472,4823],{"class":1392},[1386,6474,4816],{"class":1821},[1386,6476,4828],{"class":1392},[1386,6478,4743],{"class":1821},[1386,6480,1931],{"class":1392},[1386,6482,4835],{"class":1821},[1386,6484,4823],{"class":1392},[1386,6486,4816],{"class":1821},[1386,6488,4842],{"class":1392},[1386,6490,2273],{"class":1992},[1386,6492,1393],{"class":1392},[1386,6494,6495,6497,6499,6501,6503,6505,6507,6509,6511,6513,6515,6517,6519,6521],{"class":1388,"line":2364},[1386,6496,4851],{"class":2672},[1386,6498,2611],{"class":1992},[1386,6500,4856],{"class":1392},[1386,6502,4743],{"class":1821},[1386,6504,4568],{"class":1992},[1386,6506,4863],{"class":1821},[1386,6508,4573],{"class":1992},[1386,6510,4868],{"class":1392},[1386,6512,1411],{"class":1392},[1386,6514,4873],{"class":1414},[1386,6516,1405],{"class":1392},[1386,6518,2273],{"class":1992},[1386,6520,4880],{"class":2672},[1386,6522,2562],{"class":1392},[1386,6524,6525],{"class":1388,"line":2376},[1386,6526,1956],{"emptyLinePlaceholder":958},[1386,6528,6529,6531,6533,6535,6537,6539,6541,6543,6545,6547,6549,6551,6553,6555,6557],{"class":1388,"line":2390},[1386,6530,4891],{"class":1401},[1386,6532,4894],{"class":1821},[1386,6534,1983],{"class":1392},[1386,6536,1986],{"class":1392},[1386,6538,1989],{"class":1964},[1386,6540,1993],{"class":1992},[1386,6542,1405],{"class":1392},[1386,6544,2192],{"class":1414},[1386,6546,1405],{"class":1392},[1386,6548,2197],{"class":1392},[1386,6550,4743],{"class":1821},[1386,6552,4568],{"class":1992},[1386,6554,4863],{"class":1821},[1386,6556,4919],{"class":1992},[1386,6558,2562],{"class":1392},[1386,6560,6561,6563,6565,6567,6569,6571,6573,6575,6577,6579,6581,6583],{"class":1388,"line":2396},[1386,6562,4891],{"class":1401},[1386,6564,4928],{"class":1821},[1386,6566,1983],{"class":1392},[1386,6568,4894],{"class":1821},[1386,6570,1931],{"class":1392},[1386,6572,2022],{"class":1964},[1386,6574,1993],{"class":1992},[1386,6576,1405],{"class":1392},[1386,6578,2029],{"class":1414},[1386,6580,1405],{"class":1392},[1386,6582,2242],{"class":1992},[1386,6584,2562],{"class":1392},[1386,6586,6587,6589,6591,6593,6595,6597,6599,6601,6603,6605,6607,6609],{"class":1388,"line":2401},[1386,6588,4891],{"class":1401},[1386,6590,4955],{"class":1821},[1386,6592,1983],{"class":1392},[1386,6594,4894],{"class":1821},[1386,6596,1931],{"class":1392},[1386,6598,2022],{"class":1964},[1386,6600,1993],{"class":1992},[1386,6602,1405],{"class":1392},[1386,6604,2268],{"class":1414},[1386,6606,1405],{"class":1392},[1386,6608,2242],{"class":1992},[1386,6610,2562],{"class":1392},[1386,6612,6613],{"class":1388,"line":2407},[1386,6614,1956],{"emptyLinePlaceholder":958},[1386,6616,6617,6619,6621,6623,6625],{"class":1388,"line":2439},[1386,6618,3175],{"class":1821},[1386,6620,1931],{"class":1392},[1386,6622,2212],{"class":1964},[1386,6624,1993],{"class":1992},[1386,6626,1393],{"class":1392},[1386,6628,6629,6631,6633,6635,6637,6639,6641,6643,6645,6647,6649,6651,6653,6655,6657,6659],{"class":1388,"line":2460},[1386,6630,4996],{"class":1992},[1386,6632,1408],{"class":1392},[1386,6634,4549],{"class":1821},[1386,6636,1931],{"class":1392},[1386,6638,4554],{"class":1964},[1386,6640,1993],{"class":1992},[1386,6642,1535],{"class":1821},[1386,6644,2273],{"class":1992},[1386,6646,4563],{"class":1392},[1386,6648,4928],{"class":1821},[1386,6650,4568],{"class":1992},[1386,6652,2415],{"class":1435},[1386,6654,4573],{"class":1992},[1386,6656,1408],{"class":1392},[1386,6658,4928],{"class":1821},[1386,6660,1420],{"class":1392},[1386,6662,6663,6665,6667,6669,6671,6673,6675,6677,6679,6681,6683,6685,6687,6689,6691],{"class":1388,"line":5029},[1386,6664,5032],{"class":1992},[1386,6666,1408],{"class":1392},[1386,6668,4549],{"class":1821},[1386,6670,1931],{"class":1392},[1386,6672,4554],{"class":1964},[1386,6674,1993],{"class":1992},[1386,6676,2268],{"class":1821},[1386,6678,2273],{"class":1992},[1386,6680,4563],{"class":1392},[1386,6682,4955],{"class":1821},[1386,6684,4568],{"class":1992},[1386,6686,2415],{"class":1435},[1386,6688,4573],{"class":1992},[1386,6690,1408],{"class":1392},[1386,6692,5061],{"class":1821},[1386,6694,6695,6697,6699],{"class":1388,"line":5064},[1386,6696,5067],{"class":1392},[1386,6698,2242],{"class":1992},[1386,6700,2562],{"class":1392},[1386,6702,6703],{"class":1388,"line":5074},[1386,6704,5077],{"class":1392},[1386,6706,6707],{"class":1388,"line":5080},[1386,6708,5083],{"class":1392},[1386,6710,6711],{"class":1388,"line":5086},[1386,6712,1956],{"emptyLinePlaceholder":958},[1386,6714,6715],{"class":1388,"line":5091},[1386,6716,6717],{"class":1950},"    // JSON OUTPUT\n",[1386,6719,6720,6722,6724,6726],{"class":1388,"line":5097},[1386,6721,4484],{"class":1401},[1386,6723,3040],{"class":1821},[1386,6725,1983],{"class":1392},[1386,6727,1452],{"class":1392},[1386,6729,6730,6732,6734,6736],{"class":1388,"line":5108},[1386,6731,5111],{"class":1992},[1386,6733,1408],{"class":1392},[1386,6735,2316],{"class":1821},[1386,6737,1420],{"class":1392},[1386,6739,6740,6742,6744,6746],{"class":1388,"line":5120},[1386,6741,5123],{"class":1992},[1386,6743,1408],{"class":1392},[1386,6745,2329],{"class":1821},[1386,6747,1420],{"class":1392},[1386,6749,6750,6752,6754],{"class":1388,"line":5132},[1386,6751,5135],{"class":1992},[1386,6753,1408],{"class":1392},[1386,6755,5140],{"class":1821},[1386,6757,6758],{"class":1388,"line":5143},[1386,6759,5146],{"class":1392},[1386,6761,6762],{"class":1388,"line":5149},[1386,6763,1956],{"emptyLinePlaceholder":958},[1386,6765,6766,6768,6770,6772,6774,6776,6778,6780,6782,6784,6786,6788,6790],{"class":1388,"line":5154},[1386,6767,4484],{"class":1401},[1386,6769,5159],{"class":1821},[1386,6771,1983],{"class":1392},[1386,6773,2420],{"class":1821},[1386,6775,1931],{"class":1392},[1386,6777,2425],{"class":1964},[1386,6779,1993],{"class":1992},[1386,6781,2974],{"class":1821},[1386,6783,1549],{"class":1392},[1386,6785,5176],{"class":1392},[1386,6787,5179],{"class":1435},[1386,6789,2242],{"class":1992},[1386,6791,2562],{"class":1392},[1386,6793,6794,6796,6798,6800,6802,6804,6806,6808,6810,6812,6814],{"class":1388,"line":5186},[1386,6795,5200],{"class":1964},[1386,6797,1993],{"class":1992},[1386,6799,2415],{"class":1435},[1386,6801,1549],{"class":1392},[1386,6803,1411],{"class":1392},[1386,6805,5211],{"class":1414},[1386,6807,1405],{"class":1392},[1386,6809,1549],{"class":1392},[1386,6811,5159],{"class":1821},[1386,6813,2242],{"class":1992},[1386,6815,2562],{"class":1392},[1386,6817,6818],{"class":1388,"line":5191},[1386,6819,1956],{"emptyLinePlaceholder":958},[1386,6821,6822],{"class":1388,"line":5197},[1386,6823,6824],{"class":1950},"    // OPTIONAL: File save\n",[1386,6826,6827,6829,6831,6833,6835,6837,6839],{"class":1388,"line":5224},[1386,6828,4484],{"class":1401},[1386,6830,5755],{"class":1821},[1386,6832,1983],{"class":1392},[1386,6834,1411],{"class":1392},[1386,6836,5638],{"class":1414},[1386,6838,1405],{"class":1392},[1386,6840,2562],{"class":1392},[1386,6842,6843,6845,6848,6850,6852,6854,6856,6859,6861,6863,6865,6867,6869,6871,6873,6875,6877,6879,6881],{"class":1388,"line":5229},[1386,6844,4484],{"class":1401},[1386,6846,6847],{"class":1821}," f",[1386,6849,1983],{"class":1392},[1386,6851,1986],{"class":1392},[1386,6853,5656],{"class":1964},[1386,6855,1993],{"class":1992},[1386,6857,6858],{"class":1821},"folder",[1386,6860,2197],{"class":1392},[1386,6862,2316],{"class":1821},[1386,6864,2197],{"class":1392},[1386,6866,1411],{"class":1392},[1386,6868,5672],{"class":1414},[1386,6870,1405],{"class":1392},[1386,6872,1549],{"class":1392},[1386,6874,1411],{"class":1392},[1386,6876,5681],{"class":1414},[1386,6878,1405],{"class":1392},[1386,6880,2242],{"class":1992},[1386,6882,2562],{"class":1392},[1386,6884,6885,6887,6889,6892,6894,6897,6899],{"class":1388,"line":5235},[1386,6886,3079],{"class":2672},[1386,6888,2611],{"class":1992},[1386,6890,6891],{"class":1821},"f",[1386,6893,1931],{"class":1392},[1386,6895,6896],{"class":1821},"isopen",[1386,6898,2273],{"class":1992},[1386,6900,1393],{"class":1392},[1386,6902,6903,6906,6908,6910,6912,6914,6916],{"class":1388,"line":5260},[1386,6904,6905],{"class":1821},"      f",[1386,6907,1931],{"class":1392},[1386,6909,5715],{"class":1964},[1386,6911,1993],{"class":1992},[1386,6913,1381],{"class":1821},[1386,6915,2242],{"class":1992},[1386,6917,2562],{"class":1392},[1386,6919,6920,6922,6924,6926,6928],{"class":1388,"line":5265},[1386,6921,6905],{"class":1821},[1386,6923,1931],{"class":1392},[1386,6925,5732],{"class":1964},[1386,6927,1968],{"class":1992},[1386,6929,2562],{"class":1392},[1386,6931,6932],{"class":1388,"line":5282},[1386,6933,5083],{"class":1392},[1386,6935,6936],{"class":1388,"line":5322},[1386,6937,1956],{"emptyLinePlaceholder":958},[1386,6939,6940,6942,6944,6946,6948,6950],{"class":1388,"line":5327},[1386,6941,2753],{"class":1392},[1386,6943,5270],{"class":2672},[1386,6945,2611],{"class":1992},[1386,6947,5275],{"class":1821},[1386,6949,2273],{"class":1992},[1386,6951,1393],{"class":1392},[1386,6953,6955,6957,6959,6961,6963,6965,6967,6969,6971,6973,6975,6977,6979,6981,6983,6985,6987],{"class":1388,"line":6954},60,[1386,6956,5238],{"class":1964},[1386,6958,1993],{"class":1992},[1386,6960,1405],{"class":1392},[1386,6962,5291],{"class":1414},[1386,6964,1405],{"class":1392},[1386,6966,1549],{"class":1392},[1386,6968,5298],{"class":1821},[1386,6970,1931],{"class":1392},[1386,6972,5303],{"class":1964},[1386,6974,1968],{"class":1992},[1386,6976,1549],{"class":1392},[1386,6978,1411],{"class":1392},[1386,6980,5248],{"class":1821},[1386,6982,5251],{"class":1414},[1386,6984,1405],{"class":1392},[1386,6986,2242],{"class":1992},[1386,6988,2562],{"class":1392},[1386,6990,6992],{"class":1388,"line":6991},61,[1386,6993,2393],{"class":1392},[1386,6995,6997],{"class":1388,"line":6996},62,[1386,6998,1687],{"class":1392},[759,7000,3781],{"id":3780},[747,7002,7003],{},"With about 50 lines of JavaScript and a simple Max for Live patcher, we've built a bridge between Ableton Live's arrangement markers and the wider world of data-driven music tools.",[747,7005,7006,7007,7010],{},"This approach demonstrates a key principle: ",[754,7008,7009],{},"start with the simplest thing that works",". A button, a script, and a text display. No complex UI, no elaborate state management. Just structured data flowing from your DAW to wherever it needs to go.",[747,7012,7013],{},"The JSON format we've chosen is intentionally minimal - project name, BPM, and an array of labeled timestamps. This makes it trivial to parse in any language and integrate with any system.",[3793,7015,7016],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":943,"searchDepth":944,"depth":944,"links":7018},[7019,7020,7021,7022,7027,7031,7037,7038,7043,7044,7045,7046,7047],{"id":3896,"depth":944,"text":3897},{"id":4147,"depth":944,"text":4148},{"id":4198,"depth":944,"text":4199},{"id":4231,"depth":944,"text":4232,"children":7023},[7024,7025,7026],{"id":4253,"depth":1423,"text":4254},{"id":4277,"depth":1423,"text":4278},{"id":4345,"depth":1423,"text":4346},{"id":4380,"depth":944,"text":4381,"children":7028},[7029,7030],{"id":5332,"depth":1423,"text":5333},{"id":5382,"depth":1423,"text":5383},{"id":5401,"depth":944,"text":5402,"children":7032},[7033,7034,7035,7036],{"id":5405,"depth":1423,"text":5406},{"id":5442,"depth":1423,"text":5443},{"id":5497,"depth":1423,"text":5498},{"id":5544,"depth":1423,"text":5545},{"id":5610,"depth":944,"text":5611},{"id":5838,"depth":944,"text":5839,"children":7039},[7040,7041,7042],{"id":5842,"depth":1423,"text":5843},{"id":5872,"depth":1423,"text":5873},{"id":5898,"depth":1423,"text":5899},{"id":5913,"depth":944,"text":5914},{"id":5960,"depth":944,"text":5961},{"id":3720,"depth":944,"text":3721},{"id":6064,"depth":944,"text":6065},{"id":3780,"depth":944,"text":3781},"2026-01-24T00:00:00.000Z","Build a Max for Live device that exports arrangement locators and BPM to JSON, ready for external tools and AI music analysis pipelines.",{"src":7051},"/images/blog/musictechlab_blog_ableton-locators-json-hero.webp",{"enabled":958,"items":7053},[7054,7056,7059,7062],{"text":7055,"icon":962},"A one-click Max for Live device exports arrangement locators and BPM to JSON.",{"text":7057,"icon":7058},"Output feeds into AI models, cross-DAW workflows, and video editing tools.","i-lucide-brain",{"text":7060,"icon":7061},"Built with three components: a button, JavaScript using LiveAPI, and a text display.","i-lucide-code",{"text":7063,"icon":7064},"Requires Ableton Live 12 Suite for Max for Live support.","i-lucide-headphones",{},{"title":474,"description":7049},[973,3853],"znDSVZTcrgfgHaCE3fnvM0ylRVU8K_vjHV1ACi7Y0WY",{"id":7070,"title":606,"authors":7071,"badge":742,"body":7074,"category":951,"client":742,"date":7892,"description":7893,"extension":954,"faq":742,"featured":69,"featuredOrder":742,"hidden":69,"image":7894,"keyTakeaways":7896,"meta":7906,"navigation":958,"path":607,"seo":7907,"status":742,"stem":608,"tags":7908,"teaser":742,"__hash__":7910,"score":1423},"posts/blog/software-development/musicxml-standard-for-music-notation-and-education.md",[7072],{"name":738,"to":739,"avatar":7073},{"src":741},{"type":744,"value":7075,"toc":7866},[7076,7080,7083,7086,7090,7093,7148,7151,7269,7273,7277,7280,7284,7287,7291,7294,7298,7301,7305,7309,7312,7326,7330,7333,7337,7340,7344,7347,7361,7365,7369,7372,7550,7554,7557,7663,7667,7670,7674,7758,7762,7765,7791,7795,7798,7812,7816,7819,7822,7826,7863],[759,7077,7079],{"id":7078},"what-is-musicxml","What is MusicXML?",[747,7081,7082],{},"MusicXML is an open standard for exchanging digital sheet music. It represents Western musical notation in XML format. Created by Recordare in 2004, it's now maintained by the W3C Music Notation Community Group and has become the universal language for score exchange.",[747,7084,7085],{},"Unlike proprietary Finale or Sibelius files, MusicXML is open and well-documented. Any software vendor can implement support, making cross-application data exchange straightforward.",[759,7087,7089],{"id":7088},"musicxml-file-structure","MusicXML File Structure",[747,7091,7092],{},"A MusicXML file consists of a hierarchical structure of XML elements describing all aspects of a musical score:",[837,7094,7095,7108,7116,7124,7132,7140],{},[800,7096,7097,1916,7102,7107],{},[754,7098,7099],{},[1383,7100,7101],{},"\u003Cscore-partwise>",[754,7103,7104],{},[1383,7105,7106],{},"\u003Cscore-timewise>"," - the root element determining how data is organized (by part or by measure)",[800,7109,7110,7115],{},[754,7111,7112],{},[1383,7113,7114],{},"\u003Cpart-list>"," - list of all instrumental parts in the piece",[800,7117,7118,7123],{},[754,7119,7120],{},[1383,7121,7122],{},"\u003Cpart>"," - a single instrumental part",[800,7125,7126,7131],{},[754,7127,7128],{},[1383,7129,7130],{},"\u003Cmeasure>"," - a musical measure containing notes and other elements",[800,7133,7134,7139],{},[754,7135,7136],{},[1383,7137,7138],{},"\u003Cnote>"," - a single note with attributes such as pitch, rhythmic value, and articulation",[800,7141,7142,7147],{},[754,7143,7144],{},[1383,7145,7146],{},"\u003Cattributes>"," - time signature, key signature, clef, and other musical attributes",[747,7149,7150],{},"Example structure of a simple note in MusicXML:",[1377,7152,7156],{"className":7153,"code":7154,"language":7155,"meta":943,"style":943},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cnote>\n  \u003Cpitch>\n    \u003Cstep>C\u003C/step>\n    \u003Coctave>4\u003C/octave>\n  \u003C/pitch>\n  \u003Cduration>1\u003C/duration>\n  \u003Ctype>quarter\u003C/type>\n\u003C/note>\n","xml",[1383,7157,7158,7168,7178,7199,7217,7226,7243,7261],{"__ignoreMap":943},[1386,7159,7160,7163,7165],{"class":1388,"line":1389},[1386,7161,7162],{"class":1392},"\u003C",[1386,7164,864],{"class":1992},[1386,7166,7167],{"class":1392},">\n",[1386,7169,7170,7173,7176],{"class":1388,"line":944},[1386,7171,7172],{"class":1392},"  \u003C",[1386,7174,7175],{"class":1992},"pitch",[1386,7177,7167],{"class":1392},[1386,7179,7180,7183,7186,7189,7192,7195,7197],{"class":1388,"line":1423},[1386,7181,7182],{"class":1392},"    \u003C",[1386,7184,7185],{"class":1992},"step",[1386,7187,7188],{"class":1392},">",[1386,7190,7191],{"class":1821},"C",[1386,7193,7194],{"class":1392},"\u003C/",[1386,7196,7185],{"class":1992},[1386,7198,7167],{"class":1392},[1386,7200,7201,7203,7206,7208,7211,7213,7215],{"class":1388,"line":1119},[1386,7202,7182],{"class":1392},[1386,7204,7205],{"class":1992},"octave",[1386,7207,7188],{"class":1392},[1386,7209,7210],{"class":1821},"4",[1386,7212,7194],{"class":1392},[1386,7214,7205],{"class":1992},[1386,7216,7167],{"class":1392},[1386,7218,7219,7222,7224],{"class":1388,"line":1455},[1386,7220,7221],{"class":1392},"  \u003C/",[1386,7223,7175],{"class":1992},[1386,7225,7167],{"class":1392},[1386,7227,7228,7230,7233,7235,7237,7239,7241],{"class":1388,"line":1474},[1386,7229,7172],{"class":1392},[1386,7231,7232],{"class":1992},"duration",[1386,7234,7188],{"class":1392},[1386,7236,2446],{"class":1821},[1386,7238,7194],{"class":1392},[1386,7240,7232],{"class":1992},[1386,7242,7167],{"class":1392},[1386,7244,7245,7247,7250,7252,7255,7257,7259],{"class":1388,"line":1489},[1386,7246,7172],{"class":1392},[1386,7248,7249],{"class":1992},"type",[1386,7251,7188],{"class":1392},[1386,7253,7254],{"class":1821},"quarter",[1386,7256,7194],{"class":1392},[1386,7258,7249],{"class":1992},[1386,7260,7167],{"class":1392},[1386,7262,7263,7265,7267],{"class":1388,"line":1495},[1386,7264,7194],{"class":1392},[1386,7266,864],{"class":1992},[1386,7268,7167],{"class":1392},[759,7270,7272],{"id":7271},"applications-in-the-music-industry","Applications in the Music Industry",[1295,7274,7276],{"id":7275},"score-exchange-between-applications","Score Exchange Between Applications",[747,7278,7279],{},"The primary use of MusicXML is transferring scores between different music notation applications. A musician working in Finale can export their composition to MusicXML and send it to a collaborator using Sibelius or MuseScore. This interoperability is crucial in professional music production, where different teams often use different tools.",[1295,7281,7283],{"id":7282},"archiving-and-digitization","Archiving and Digitization",[747,7285,7286],{},"Music libraries and archives increasingly use MusicXML for digitizing historical scores. This format allows storage of not only the visual representation of notes but also semantic information about the piece's structure, enabling advanced searching and analysis.",[1295,7288,7290],{"id":7289},"automatic-arrangement-and-transposition","Automatic Arrangement and Transposition",[747,7292,7293],{},"Programs using MusicXML can automatically transpose pieces to different keys or generate arrangements for various instrumental ensembles. The semantic structure of the format makes such operations much simpler than with graphic formats.",[1295,7295,7297],{"id":7296},"integration-with-daws-and-synthesizers","Integration with DAWs and Synthesizers",[747,7299,7300],{},"Some digital audio workstations (DAWs) support MusicXML import, allowing conversion of traditional notation to MIDI tracks. This is particularly useful for composers combining traditional notation with electronic production.",[759,7302,7304],{"id":7303},"musicxml-in-music-education","MusicXML in Music Education",[1295,7306,7308],{"id":7307},"interactive-educational-materials","Interactive Educational Materials",[747,7310,7311],{},"Music educators use MusicXML to create interactive exercises. Students can:",[837,7313,7314,7317,7320,7323],{},[800,7315,7316],{},"Play back scores at different tempos",[800,7318,7319],{},"Listen to selected parts separately",[800,7321,7322],{},"Follow the notation during playback",[800,7324,7325],{},"Modify and experiment with musical material",[1295,7327,7329],{"id":7328},"instrument-learning-applications","Instrument Learning Applications",[747,7331,7332],{},"Many educational applications import MusicXML files to present students with notation synchronized to audio backing. Applications like SmartMusic, Yousician, and Piano Marvel use this format to deliver interactive lessons.",[1295,7334,7336],{"id":7335},"accessibility-for-blind-musicians","Accessibility for Blind Musicians",[747,7338,7339],{},"MusicXML plays an important role in creating accessible musical materials. The format can be converted to music braille notation, enabling blind and visually impaired people to access musical scores. Projects like FreeDots and Music21 offer tools for such conversion.",[1295,7341,7343],{"id":7342},"music-analysis-and-theory","Music Analysis and Theory",[747,7345,7346],{},"Musicology students use MusicXML in combination with programming libraries (e.g., music21 in Python) for:",[837,7348,7349,7352,7355,7358],{},[800,7350,7351],{},"Harmonic analysis of compositions",[800,7353,7354],{},"Studying statistical patterns in compositions",[800,7356,7357],{},"Comparing different versions of the same piece",[800,7359,7360],{},"Visualizing musical structures",[759,7362,7364],{"id":7363},"programming-with-musicxml","Programming with MusicXML",[1295,7366,7368],{"id":7367},"python-and-the-music21-library","Python and the music21 Library",[747,7370,7371],{},"The most popular tool for working with MusicXML in Python is the music21 library developed by MIT. It enables:",[1377,7373,7375],{"className":2921,"code":7374,"language":2923,"meta":943,"style":943},"from music21 import converter, analysis\n\n# Load MusicXML file\nscore = converter.parse('composition.musicxml')\n\n# Key analysis\nkey = score.analyze('key')\nprint(f\"Key: {key}\")\n\n# Transpose up a minor third\ntransposed = score.transpose('m3')\ntransposed.write('musicxml', 'composition_transposed.musicxml')\n",[1383,7376,7377,7396,7400,7405,7429,7433,7438,7464,7487,7491,7496,7521],{"__ignoreMap":943},[1386,7378,7379,7382,7385,7388,7391,7393],{"class":1388,"line":1389},[1386,7380,7381],{"class":2672},"from",[1386,7383,7384],{"class":1821}," music21 ",[1386,7386,7387],{"class":2672},"import",[1386,7389,7390],{"class":1821}," converter",[1386,7392,1549],{"class":1392},[1386,7394,7395],{"class":1821}," analysis\n",[1386,7397,7398],{"class":1388,"line":944},[1386,7399,1956],{"emptyLinePlaceholder":958},[1386,7401,7402],{"class":1388,"line":1423},[1386,7403,7404],{"class":1950},"# Load MusicXML file\n",[1386,7406,7407,7410,7412,7414,7416,7418,7420,7422,7425,7427],{"class":1388,"line":1119},[1386,7408,7409],{"class":1821},"score ",[1386,7411,2544],{"class":1392},[1386,7413,7390],{"class":1821},[1386,7415,1931],{"class":1392},[1386,7417,2643],{"class":1964},[1386,7419,1993],{"class":1392},[1386,7421,2552],{"class":1392},[1386,7423,7424],{"class":1414},"composition.musicxml",[1386,7426,2552],{"class":1392},[1386,7428,2003],{"class":1392},[1386,7430,7431],{"class":1388,"line":1455},[1386,7432,1956],{"emptyLinePlaceholder":958},[1386,7434,7435],{"class":1388,"line":1474},[1386,7436,7437],{"class":1950},"# Key analysis\n",[1386,7439,7440,7443,7445,7448,7450,7453,7455,7457,7460,7462],{"class":1388,"line":1489},[1386,7441,7442],{"class":1821},"key ",[1386,7444,2544],{"class":1392},[1386,7446,7447],{"class":1821}," score",[1386,7449,1931],{"class":1392},[1386,7451,7452],{"class":1964},"analyze",[1386,7454,1993],{"class":1392},[1386,7456,2552],{"class":1392},[1386,7458,7459],{"class":1414},"key",[1386,7461,2552],{"class":1392},[1386,7463,2003],{"class":1392},[1386,7465,7466,7469,7471,7473,7476,7479,7481,7483,7485],{"class":1388,"line":1495},[1386,7467,7468],{"class":1964},"print",[1386,7470,1993],{"class":1392},[1386,7472,6891],{"class":1401},[1386,7474,7475],{"class":1414},"\"Key: ",[1386,7477,7478],{"class":1435},"{",[1386,7480,7459],{"class":1964},[1386,7482,2896],{"class":1435},[1386,7484,1405],{"class":1414},[1386,7486,2003],{"class":1392},[1386,7488,7489],{"class":1388,"line":1512},[1386,7490,1956],{"emptyLinePlaceholder":958},[1386,7492,7493],{"class":1388,"line":1527},[1386,7494,7495],{"class":1950},"# Transpose up a minor third\n",[1386,7497,7498,7501,7503,7505,7507,7510,7512,7514,7517,7519],{"class":1388,"line":1566},[1386,7499,7500],{"class":1821},"transposed ",[1386,7502,2544],{"class":1392},[1386,7504,7447],{"class":1821},[1386,7506,1931],{"class":1392},[1386,7508,7509],{"class":1964},"transpose",[1386,7511,1993],{"class":1392},[1386,7513,2552],{"class":1392},[1386,7515,7516],{"class":1414},"m3",[1386,7518,2552],{"class":1392},[1386,7520,2003],{"class":1392},[1386,7522,7523,7526,7528,7530,7532,7534,7537,7539,7541,7543,7546,7548],{"class":1388,"line":1601},[1386,7524,7525],{"class":1821},"transposed",[1386,7527,1931],{"class":1392},[1386,7529,5681],{"class":1964},[1386,7531,1993],{"class":1392},[1386,7533,2552],{"class":1392},[1386,7535,7536],{"class":1414},"musicxml",[1386,7538,2552],{"class":1392},[1386,7540,1549],{"class":1392},[1386,7542,2695],{"class":1392},[1386,7544,7545],{"class":1414},"composition_transposed.musicxml",[1386,7547,2552],{"class":1392},[1386,7549,2003],{"class":1392},[1295,7551,7553],{"id":7552},"javascript-and-the-opensheetmusicdisplay-library","JavaScript and the opensheetmusicdisplay Library",[747,7555,7556],{},"In the web environment, the opensheetmusicdisplay library is popular for rendering MusicXML files directly in the browser:",[1377,7558,7560],{"className":1941,"code":7559,"language":1943,"meta":943,"style":943},"import { OpenSheetMusicDisplay } from 'opensheetmusicdisplay';\n\nconst osmd = new OpenSheetMusicDisplay(\"container\");\nosmd.load(\"composition.musicxml\")\n  .then(() => osmd.render());\n",[1383,7561,7562,7586,7590,7616,7636],{"__ignoreMap":943},[1386,7563,7564,7566,7568,7571,7574,7577,7579,7582,7584],{"class":1388,"line":1389},[1386,7565,7387],{"class":2672},[1386,7567,1767],{"class":1392},[1386,7569,7570],{"class":1821}," OpenSheetMusicDisplay",[1386,7572,7573],{"class":1392}," }",[1386,7575,7576],{"class":2672}," from",[1386,7578,2695],{"class":1392},[1386,7580,7581],{"class":1414},"opensheetmusicdisplay",[1386,7583,2552],{"class":1392},[1386,7585,2562],{"class":1392},[1386,7587,7588],{"class":1388,"line":944},[1386,7589,1956],{"emptyLinePlaceholder":958},[1386,7591,7592,7594,7597,7599,7601,7603,7605,7607,7610,7612,7614],{"class":1388,"line":1423},[1386,7593,2538],{"class":1401},[1386,7595,7596],{"class":1821}," osmd ",[1386,7598,2544],{"class":1392},[1386,7600,1986],{"class":1392},[1386,7602,7570],{"class":1964},[1386,7604,1993],{"class":1821},[1386,7606,1405],{"class":1392},[1386,7608,7609],{"class":1414},"container",[1386,7611,1405],{"class":1392},[1386,7613,2242],{"class":1821},[1386,7615,2562],{"class":1392},[1386,7617,7618,7621,7623,7626,7628,7630,7632,7634],{"class":1388,"line":1119},[1386,7619,7620],{"class":1821},"osmd",[1386,7622,1931],{"class":1392},[1386,7624,7625],{"class":1964},"load",[1386,7627,1993],{"class":1821},[1386,7629,1405],{"class":1392},[1386,7631,7424],{"class":1414},[1386,7633,1405],{"class":1392},[1386,7635,2003],{"class":1821},[1386,7637,7638,7641,7644,7646,7648,7650,7653,7655,7658,7661],{"class":1388,"line":1455},[1386,7639,7640],{"class":1392},"  .",[1386,7642,7643],{"class":1964},"then",[1386,7645,1993],{"class":1821},[1386,7647,1968],{"class":1392},[1386,7649,2620],{"class":1401},[1386,7651,7652],{"class":1821}," osmd",[1386,7654,1931],{"class":1392},[1386,7656,7657],{"class":1964},"render",[1386,7659,7660],{"class":1821},"())",[1386,7662,2562],{"class":1392},[1295,7664,7666],{"id":7665},"xml-validation-and-parsing","XML Validation and Parsing",[747,7668,7669],{},"As an XML-based format, MusicXML can be processed by standard XML libraries in any programming language. Official XSD schemas allow validation of file correctness.",[759,7671,7673],{"id":7672},"comparison-with-other-formats","Comparison with Other Formats",[1179,7675,7676,7692],{},[1182,7677,7678],{},[1185,7679,7680,7683,7686,7689],{},[1188,7681,7682],{},"Format",[1188,7684,7685],{},"Type",[1188,7687,7688],{},"Openness",[1188,7690,7691],{},"Primary Use",[1195,7693,7694,7708,7720,7733,7746],{},[1185,7695,7696,7699,7702,7705],{},[1200,7697,7698],{},"MusicXML",[1200,7700,7701],{},"XML",[1200,7703,7704],{},"Open",[1200,7706,7707],{},"Score exchange",[1185,7709,7710,7713,7715,7717],{},[1200,7711,7712],{},"MEI",[1200,7714,7701],{},[1200,7716,7704],{},[1200,7718,7719],{},"Musicology, archiving",[1185,7721,7722,7725,7728,7730],{},[1200,7723,7724],{},"MIDI",[1200,7726,7727],{},"Binary",[1200,7729,7704],{},[1200,7731,7732],{},"Performance data",[1185,7734,7735,7738,7740,7743],{},[1200,7736,7737],{},"Finale (.musx)",[1200,7739,7727],{},[1200,7741,7742],{},"Closed",[1200,7744,7745],{},"Editing in Finale",[1185,7747,7748,7751,7753,7755],{},[1200,7749,7750],{},"Sibelius (.sib)",[1200,7752,7727],{},[1200,7754,7742],{},[1200,7756,7757],{},"Editing in Sibelius",[759,7759,7761],{"id":7760},"musicxml-limitations","MusicXML Limitations",[747,7763,7764],{},"Despite its many advantages, MusicXML has some limitations:",[837,7766,7767,7773,7779,7785],{},[800,7768,7769,7772],{},[754,7770,7771],{},"File size"," - XML files are significantly larger than binary formats",[800,7774,7775,7778],{},[754,7776,7777],{},"Complexity"," - the full specification is extensive and complicated",[800,7780,7781,7784],{},[754,7782,7783],{},"Formatting loss"," - specific visual elements may be lost when converting between programs",[800,7786,7787,7790],{},[754,7788,7789],{},"No sound standardization"," - the format describes notation, not sound (unlike MIDI)",[759,7792,7794],{"id":7793},"the-future-of-musicxml","The Future of MusicXML",[747,7796,7797],{},"The W3C Music Notation Community Group continues to develop the standard. Version 4.0 introduces, among other things:",[837,7799,7800,7803,7806,7809],{},[800,7801,7802],{},"Better support for contemporary and experimental notation",[800,7804,7805],{},"Extended capabilities for describing dynamics and articulation",[800,7807,7808],{},"Improvements in representing non-metric music",[800,7810,7811],{},"Integration with the SMuFL (Standard Music Font Layout) format",[759,7813,7815],{"id":7814},"summary","Summary",[747,7817,7818],{},"MusicXML forms the foundation of interoperability in digital music notation. For musicians, educators, and developers, it is an invaluable tool enabling the exchange, analysis, and processing of musical scores. As music education digitization grows and music applications develop, the importance of this standard will only increase.",[747,7820,7821],{},"For technical teams working on music projects, knowledge of MusicXML is a key competency for building solutions compatible with the broad ecosystem of music tools.",[759,7823,7825],{"id":7824},"useful-resources","Useful Resources",[837,7827,7828,7835,7842,7849,7856],{},[800,7829,7830],{},[889,7831,7834],{"href":7832,"rel":7833},"https://www.musicxml.com/",[893],"Official MusicXML Website",[800,7836,7837],{},[889,7838,7841],{"href":7839,"rel":7840},"https://www.w3.org/community/music-notation/",[893],"W3C Music Notation Community Group",[800,7843,7844],{},[889,7845,7848],{"href":7846,"rel":7847},"https://web.mit.edu/music21/",[893],"music21 Documentation",[800,7850,7851],{},[889,7852,7855],{"href":7853,"rel":7854},"https://opensheetmusicdisplay.org/",[893],"OpenSheetMusicDisplay",[800,7857,7858],{},[889,7859,7862],{"href":7860,"rel":7861},"https://www.w3.org/2021/06/musicxml40/",[893],"MusicXML 4.0 Specification",[3793,7864,7865],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":943,"searchDepth":944,"depth":944,"links":7867},[7868,7869,7870,7876,7882,7887,7888,7889,7890,7891],{"id":7078,"depth":944,"text":7079},{"id":7088,"depth":944,"text":7089},{"id":7271,"depth":944,"text":7272,"children":7871},[7872,7873,7874,7875],{"id":7275,"depth":1423,"text":7276},{"id":7282,"depth":1423,"text":7283},{"id":7289,"depth":1423,"text":7290},{"id":7296,"depth":1423,"text":7297},{"id":7303,"depth":944,"text":7304,"children":7877},[7878,7879,7880,7881],{"id":7307,"depth":1423,"text":7308},{"id":7328,"depth":1423,"text":7329},{"id":7335,"depth":1423,"text":7336},{"id":7342,"depth":1423,"text":7343},{"id":7363,"depth":944,"text":7364,"children":7883},[7884,7885,7886],{"id":7367,"depth":1423,"text":7368},{"id":7552,"depth":1423,"text":7553},{"id":7665,"depth":1423,"text":7666},{"id":7672,"depth":944,"text":7673},{"id":7760,"depth":944,"text":7761},{"id":7793,"depth":944,"text":7794},{"id":7814,"depth":944,"text":7815},{"id":7824,"depth":944,"text":7825},"2026-01-15T00:00:00.000Z","What is MusicXML, how does it work, and what are its applications in music and education? A guide to the open standard for sheet music exchange.",{"src":7895},"/images/blog/musictechlab_blog_musicxml-standard.webp",{"enabled":958,"items":7897},[7898,7900,7902,7904],{"text":7899,"icon":962},"MusicXML is the universal open standard for exchanging digital sheet music across applications.",{"text":7901,"icon":7061},"Python's music21 library enables key analysis, transposition, and statistical study of MusicXML files.",{"text":7903,"icon":1109},"MusicXML can be converted to music braille, making scores accessible to blind musicians.",{"text":7905,"icon":3849},"Version 4.0 adds better support for contemporary notation and SMuFL font integration.",{},{"title":606,"description":7893},[972,7909],"music-data","RMUBgJBMMiRalXu39PcOF_a2vQZmUD88k-VCZ_gaBUQ",1780305288209]