[{"data":1,"prerenderedAt":5265},["ShallowReactive",2],{"navigation":3,"/blog/music-data/ddex-office-hours-musictech-post":734,"/blog/music-data/ddex-office-hours-musictech-surround":953,"/blog/music-data/ddex-office-hours-musictech-related":958},[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":132,"authors":736,"badge":742,"body":745,"category":927,"client":928,"date":929,"description":930,"extension":931,"faq":928,"featured":69,"featuredOrder":928,"hidden":69,"image":932,"keyTakeaways":934,"meta":946,"navigation":935,"path":133,"seo":947,"status":928,"stem":134,"tags":948,"teaser":928,"__hash__":952},"posts/blog/music-data/ddex-office-hours-musictech.md",[737],{"name":738,"to":739,"avatar":740},"Maciej Dulski","https://www.linkedin.com/in/maciej-dulski/",{"src":741},"/images/cdn-migrated/maciej-dulski-400x400.webp",{"label":743,"color":744},"Featured","#E91E63",{"type":746,"value":747,"toc":919},"minimark",[748,757,770,777,782,808,811,815,818,837,843,847,854,868,871,875,891,900],[749,750,751,752,756],"p",{},"If you're building a MusicTech platform that needs to integrate with labels, distributors, or DSPs, DDEX compliance becomes unavoidable at some point. The challenge is knowing ",[753,754,755],"strong",{},"what to implement, when, and how much is actually required",".",[749,758,759,760,769],{},"MusicTech Lab is a ",[753,761,762],{},[763,764,768],"a",{"href":765,"rel":766},"https://ddex.net/membership/current-members/",[767],"nofollow","DDEX member",", and these office hours are run by our DDEX expert — based on hands-on experience with production systems used across the music industry.",[749,771,772,773,776],{},"We offer ",[753,774,775],{},"2 free DDEX office hour slots per month",", focused on practical guidance.",[778,779,781],"h2",{"id":780},"what-we-can-help-with","What We Can Help With",[783,784,791,796,800,804],"div",{"className":785},[786,787,788,789,790],"grid","grid-cols-1","md:grid-cols-2","gap-4","my-8",[792,793],"spotlight-card",{"description":794,"title":795},"Choosing the right DDEX standard for your use case — ERN, DSR, RIN, or MLC — and understanding the real-world differences between ERN versions.","Standards Selection",[792,797],{"description":798,"title":799},"Reviewing your internal data model for DDEX readiness. Mapping Releases, Resources, Deals, and Parties to your existing structures.","Data Model Preparation",[792,801],{"description":802,"title":803},"Designing ERN export APIs, including OpenAPI-based approaches. Handling identifiers for artists, contributors, and rights holders correctly.","API Design",[792,805],{"description":806,"title":807},"Common compliance pitfalls, validation strategies, and how to test your DDEX output before sending it to DSPs.","Validation & Compliance",[749,809,810],{},"You can bring a specific technical problem or ask us to review your overall approach.",[778,812,814],{"id":813},"common-questions-weve-answered","Common Questions We've Answered",[749,816,817],{},"Here are real examples of what teams bring to office hours:",[819,820,821,825,828,831,834],"ul",{},[822,823,824],"li",{},"\"We have track metadata in our database — how do we map it to ERN 3.8?\"",[822,826,827],{},"\"Our distributor is asking for DDEX-compliant delivery. Where do we start?\"",[822,829,830],{},"\"We're building an export pipeline. Should we generate XML directly or use an intermediary format?\"",[822,832,833],{},"\"How do we handle multi-territory deals and release windows?\"",[822,835,836],{},"\"What's the minimum viable ERN file that YouTube/Spotify will accept?\"",[838,839,840],"note",{},[749,841,842],{},"These aren't theoretical discussions. Every session is focused on your specific implementation — your data model, your tech stack, your timeline.",[778,844,846],{"id":845},"real-implementation-experience","Real Implementation Experience",[749,848,849,850,853],{},"We recently supported a music creation platform in preparing their internal data model for ",[753,851,852],{},"DDEX ERN-based metadata delivery",". The engagement included:",[819,855,856,859,862,865],{},[822,857,858],{},"Data model review and gap analysis for DDEX compliance",[822,860,861],{},"Mapping internal fields to ERN structures",[822,863,864],{},"Defining export specifications for ERN 3.8 with future upgrade paths",[822,866,867],{},"Documentation, examples, and validation recommendations",[749,869,870],{},"This gave the client a clear, compliant foundation to move toward distributor and DSP integrations.",[778,872,874],{"id":873},"how-it-works","How It Works",[783,876,879,883,887],{"className":877},[786,787,878,789,790],"md:grid-cols-3",[792,880],{"description":881,"title":882},"First come, first served. Each session is 30–45 minutes.","2 free slots per month",[792,884],{"description":885,"title":886},"Bring your code, data models, or architecture diagrams. We'll review and advise.","Technical consultation",[792,888],{"description":889,"title":890},"No sales pitch. Just practical help with real implementation choices.","Focused on decisions",[892,893,894],"warning",{},[749,895,896,897,756],{},"These office hours are provided by MusicTech Lab. MusicTech Lab is a DDEX member, but this service is ",[753,898,899],{},"not endorsed, operated, or provided by DDEX",[783,901,906,914],{"className":902},[903,904,905,790],"flex","flex-wrap","gap-3",[907,908],"u-button",{"color":909,"label":910,"target":911,"to":912,"variant":913},"primary","Book a Session","_blank","https://musictechlab.io/contact","subtle",[907,915],{"color":916,"label":917,"target":911,"to":918,"variant":913},"neutral","DDEX Integration Services","https://musictechlab.io/lp/ddex-integration",{"title":920,"searchDepth":921,"depth":921,"links":922},"",2,[923,924,925,926],{"id":780,"depth":921,"text":781},{"id":813,"depth":921,"text":814},{"id":845,"depth":921,"text":846},{"id":873,"depth":921,"text":874},"music-data",null,"2025-12-22T00:00:00.000Z","Free DDEX office hours for MusicTech teams. Get help with DDEX compliance, ERN implementation, data models, and integrations with DSPs.","md",{"src":933},"/images/blog/musictechlab_blog_musictech-lab-ddex-office-hours.webp",{"enabled":935,"items":936},true,[937,940,943],{"text":938,"icon":939},"MusicTech Lab offers 2 free DDEX office hour slots per month for hands-on technical guidance.","i-lucide-users",{"text":941,"icon":942},"Sessions cover standards selection, data model mapping, API design, and validation strategies.","i-lucide-file-code",{"text":944,"icon":945},"Every session is focused on your specific implementation, not theoretical discussions.","i-lucide-lightbulb",{},{"title":132,"description":930},[949,950,951],"DDEX","musictech","metadata","Ixad9_iid0eEMjDHYM-lp2qGTEmyHS6lFV2v0lZz3_c",[954,956],{"title":128,"path":129,"stem":130,"description":955,"children":-1},"The most useful data modeling design patterns in MongoDB are attributed, three, and extended reference patterns.",{"title":136,"path":137,"stem":138,"description":957,"children":-1},"Explore DDEX open-source projects that simplify music metadata management, enhance rights tracking, and streamline royalty distribution.",[959,1895,3879,4561],{"id":960,"title":136,"authors":961,"badge":967,"body":968,"category":927,"client":928,"date":1874,"description":957,"extension":931,"faq":928,"featured":69,"featuredOrder":928,"hidden":69,"image":1875,"keyTakeaways":1877,"meta":1890,"navigation":935,"path":137,"seo":1891,"status":928,"stem":138,"tags":1892,"teaser":928,"__hash__":1893,"score":1894},"posts/blog/music-data/ddex-open-source-projects-review.md",[962],{"name":963,"to":964,"avatar":965},"Mariusz Smenżyk","https://www.linkedin.com/in/mariusz-smenzyk/",{"src":966},"/images/people/mariusz-smenzyk2.webp",{"label":743,"color":744},{"type":746,"value":969,"toc":1860},[970,973,980,986,990,993,997,1005,1009,1012,1021,1047,1056,1078,1087,1109,1118,1139,1148,1168,1177,1197,1206,1227,1236,1256,1264,1283,1292,1313,1321,1341,1350,1370,1379,1400,1409,1429,1438,1457,1466,1487,1496,1517,1526,1547,1556,1576,1585,1605,1609,1628,1632,1647,1651,1669,1673,1696,1700,1715,1719,1757,1760,1764,1770,1789,1800,1828,1832,1843,1847],[749,971,972],{},"In the rapidly evolving digital music industry, managing the exchange of data across different platforms and services can be a daunting task. The complexity of licensing, distribution, and rights management makes seamless data exchange essential for all players involved - artists, record labels, distributors, and digital service providers (DSPs). To address this challenge, the Digital Data Exchange (DDEX) consortium was established to standardize data formats and processes across the industry. DDEX plays a critical role in ensuring that music rights, royalties, and metadata flow smoothly across the digital ecosystem. Among its most significant contributions are its open-source projects, which provide tools and resources that allow stakeholders to easily implement DDEX standards.",[749,974,975],{},[976,977],"img",{"alt":978,"src":979},"DDEX website screenshot","/images/cdn-migrated/ddex-website-screenshot.webp",[749,981,982],{},[983,984,985],"em",{},"CREDIT: DDEX website",[778,987,989],{"id":988},"what-is-ddex","What is DDEX?",[749,991,992],{},"DDEX, founded in 2006, is a consortium of leading media companies, digital music services, and music rights organizations. It creates and maintains standards for the communication of metadata between businesses in the digital music supply chain. These standards ensure that information such as licensing details, royalties, and usage data is accurately transferred between parties involved in the production, distribution, and consumption of digital media. The core of DDEX's mission is to enable a more efficient exchange of metadata, which is crucial for tracking music rights and ensuring that artists and rights holders receive fair compensation for their work.",[778,994,996],{"id":995},"open-source-in-ddex","Open Source in DDEX",[749,998,999,1000,1004],{},"DDEX's open-source projects allow developers and businesses to implement its standards without having to start from scratch. By making these projects available under open-source licenses, DDEX encourages collaboration, innovation, and faster adoption of standardized protocols. This approach lowers the barrier for small and large players alike, enabling the entire music industry to benefit from greater consistency and transparency in metadata management. Here is a list of Open Source tools provided by DDEX: ",[763,1001,1002],{"href":1002,"rel":1003},"https://kb.ddex.net/reference-material/open-source-software/",[767]," Let's delve inside them.",[778,1006,1008],{"id":1007},"open-source-software-from-ddex-website","Open Source Software (from DDEX website)",[749,1010,1011],{},"The DDEX website lists several open-source tools available on GitHub, developed by various companies and individuals. These tools can assist with parsing, validating, and converting DDEX-compliant metadata files in various programming languages, such as Python, Ruby, JavaScript, and PHP. Many of the tools focus on validating, parsing, and converting DDEX XML files related to music metadata, ensuring conformance to DDEX standards for digital sales reporting (DSR), Electronic Release Notification (ERN), and Metadata Choreography (MEAD).",[749,1013,1014],{},[763,1015,1018],{"href":1016,"rel":1017},"https://github.com/ddexnet/dsrf",[767],[753,1019,1020],{},"dsrf",[819,1022,1023,1029,1035,1041],{},[822,1024,1025,1028],{},[753,1026,1027],{},"Standard",": DSR (Digital Sales Report)",[822,1030,1031,1034],{},[753,1032,1033],{},"Description",": The DSRF Flat File Parser and Conformance Tool is an open-source library that allows parsing and testing of DDEX DSR Flat files, ensuring they comply with DDEX DSR Flat File Standard v3.0.",[822,1036,1037,1040],{},[753,1038,1039],{},"Language",": Python",[822,1042,1043,1046],{},[753,1044,1045],{},"Creator",": Google",[749,1048,1049],{},[763,1050,1053],{"href":1051,"rel":1052},"https://github.com/sshaw/ddex",[767],[753,1054,1055],{},"ddex ruby",[819,1057,1058,1063,1068,1073],{},[822,1059,1060,1062],{},[753,1061,1027],{},": ERN (Electronic Release Notification)",[822,1064,1065,1067],{},[753,1066,1033],{},": This library facilitates DDEX metadata serialization for Ruby. Comprehensive documentation is available for easy integration.",[822,1069,1070,1072],{},[753,1071,1039],{},": Ruby",[822,1074,1075,1077],{},[753,1076,1045],{},": Skye Shaw",[749,1079,1080],{},[763,1081,1084],{"href":1082,"rel":1083},"https://github.com/7digital/DDEX-Deserialiser",[767],[753,1085,1086],{},"DDEX Deserialiser",[819,1088,1089,1094,1099,1104],{},[822,1090,1091,1093],{},[753,1092,1027],{},": ERN",[822,1095,1096,1098],{},[753,1097,1033],{},": A tool developed by 7digital for batch deserialization of DDEX XML files, allowing seamless conversion of XML data to usable formats.",[822,1100,1101,1103],{},[753,1102,1039],{},": C#",[822,1105,1106,1108],{},[753,1107,1045],{},": 7digital",[749,1110,1111],{},[763,1112,1115],{"href":1113,"rel":1114},"https://github.com/eddleston/DDEX-Validator",[767],[753,1116,1117],{},"DDEX Validator",[819,1119,1120,1124,1129,1134],{},[822,1121,1122,1093],{},[753,1123,1027],{},[822,1125,1126,1128],{},[753,1127,1033],{},": A validation service designed to verify DDEX XML documents for compliance with the DDEX ERN standard.",[822,1130,1131,1133],{},[753,1132,1039],{},": NuGet/Microsoft Visual Studio",[822,1135,1136,1138],{},[753,1137,1045],{},": Paul Eddleston",[749,1140,1141],{},[763,1142,1145],{"href":1143,"rel":1144},"https://github.com/thornlaw/ddex-ern-lib",[767],[753,1146,1147],{},"ddex-ern-lib",[819,1149,1150,1154,1159,1163],{},[822,1151,1152,1093],{},[753,1153,1027],{},[822,1155,1156,1158],{},[753,1157,1033],{},": A DDEX ERN 3.7 XML Messaging Class Library, leveraging Linq to XSD and T4 Templates, for easy handling of ERN messages.",[822,1160,1161,1103],{},[753,1162,1039],{},[822,1164,1165,1167],{},[753,1166,1045],{},": Thornlaw Consultants",[749,1169,1170],{},[763,1171,1174],{"href":1172,"rel":1173},"https://github.com/willm/DDEXUI",[767],[753,1175,1176],{},"DDEXUI (1)",[819,1178,1179,1183,1188,1192],{},[822,1180,1181,1093],{},[753,1182,1027],{},[822,1184,1185,1187],{},[753,1186,1033],{},": A user interface designed to help create simplified DDEX metadata, making the metadata creation process easier for users.",[822,1189,1190,1040],{},[753,1191,1039],{},[822,1193,1194,1196],{},[753,1195,1045],{},": Will Munn",[749,1198,1199],{},[763,1200,1203],{"href":1201,"rel":1202},"https://github.com/agreen757/SoundCloudDDEX",[767],[753,1204,1205],{},"SoundCloud DDEX",[819,1207,1208,1212,1217,1222],{},[822,1209,1210,1093],{},[753,1211,1027],{},[822,1213,1214,1216],{},[753,1215,1033],{},": A tool for generating DDEX feeds for SoundCloud by converting data from CSV files into DDEX-compliant metadata.",[822,1218,1219,1221],{},[753,1220,1039],{},": JavaScript",[822,1223,1224,1226],{},[753,1225,1045],{},": Adrian Green",[749,1228,1229],{},[763,1230,1233],{"href":1231,"rel":1232},"https://github.com/Trax-air/ddexreader",[767],[753,1234,1235],{},"DDEXreader",[819,1237,1238,1242,1247,1251],{},[822,1239,1240,1093],{},[753,1241,1027],{},[822,1243,1244,1246],{},[753,1245,1033],{},": A Python project that allows reading of DDEX XML files and decoding them into Python data types using the PyXB library.",[822,1248,1249,1040],{},[753,1250,1039],{},[822,1252,1253,1255],{},[753,1254,1045],{},": Trax Air",[749,1257,1258],{},[763,1259,1261],{"href":1172,"rel":1260},[767],[753,1262,1263],{},"DDEXUI (2)",[819,1265,1266,1270,1275,1279],{},[822,1267,1268,1093],{},[753,1269,1027],{},[822,1271,1272,1274],{},[753,1273,1033],{},": Another version of DDEXUI, focusing on making DDEX metadata creation more accessible for small labels and independent artists by simplifying the process.",[822,1276,1277,1040],{},[753,1278,1039],{},[822,1280,1281,1196],{},[753,1282,1045],{},[749,1284,1285],{},[763,1286,1289],{"href":1287,"rel":1288},"https://github.com/moodleexpert/DDEXPHPParser",[767],[753,1290,1291],{},"DDEX PHP Parser",[819,1293,1294,1298,1303,1308],{},[822,1295,1296,1093],{},[753,1297,1027],{},[822,1299,1300,1302],{},[753,1301,1033],{},": A PHP parser specifically designed for handling DDEX XML files, enabling parsing and output in JSON format.",[822,1304,1305,1307],{},[753,1306,1039],{},": PHP",[822,1309,1310,1312],{},[753,1311,1045],{},": Nikhil Patil",[749,1314,1315],{},[763,1316,1319],{"href":1317,"rel":1318},"https://github.com/Alveum/DDEX",[767],[753,1320,949],{},[819,1322,1323,1327,1332,1336],{},[822,1324,1325,1093],{},[753,1326,1027],{},[822,1328,1329,1331],{},[753,1330,1033],{},": A library for retrieving DDEX party details, which helps in managing metadata related to parties in the music supply chain.",[822,1333,1334,1307],{},[753,1335,1039],{},[822,1337,1338,1340],{},[753,1339,1045],{},": Alveum",[749,1342,1343],{},[763,1344,1347],{"href":1345,"rel":1346},"https://github.com/bnathyuw/RubyDdexParserSpike",[767],[753,1348,1349],{},"RubyDDEXParserSpike",[819,1351,1352,1356,1361,1365],{},[822,1353,1354,1093],{},[753,1355,1027],{},[822,1357,1358,1360],{},[753,1359,1033],{},": A Ruby-based tool for reading DDEX deal information using XPath to extract data from the DDEX XML.",[822,1362,1363,1072],{},[753,1364,1039],{},[822,1366,1367,1369],{},[753,1368,1045],{},": Matthew Butt",[749,1371,1372],{},[763,1373,1376],{"href":1374,"rel":1375},"https://github.com/AidanTwomey/DdexToJson",[767],[753,1377,1378],{},"DDEX to JSON",[819,1380,1381,1385,1390,1395],{},[822,1382,1383,1093],{},[753,1384,1027],{},[822,1386,1387,1389],{},[753,1388,1033],{},": A Lambda function for converting DDEX XML files into JSON format for easier integration into web services and modern data workflows.",[822,1391,1392,1394],{},[753,1393,1039],{},": Lambda",[822,1396,1397,1399],{},[753,1398,1045],{},": Aidan Twomey",[749,1401,1402],{},[763,1403,1406],{"href":1404,"rel":1405},"https://github.com/ddexnet/ern-validator-client",[767],[753,1407,1408],{},"DDEX Validator (Client)",[819,1410,1411,1415,1420,1424],{},[822,1412,1413,1093],{},[753,1414,1027],{},[822,1416,1417,1419],{},[753,1418,1033],{},": A JavaScript client-side validator designed for verifying ERN messages for compliance with DDEX standards.",[822,1421,1422,1221],{},[753,1423,1039],{},[822,1425,1426,1428],{},[753,1427,1045],{},": Rob deWilder",[749,1430,1431],{},[763,1432,1435],{"href":1433,"rel":1434},"https://github.com/ddexnet/ern-validator-api",[767],[753,1436,1437],{},"Client Validator (API)",[819,1439,1440,1444,1449,1453],{},[822,1441,1442,1093],{},[753,1443,1027],{},[822,1445,1446,1448],{},[753,1447,1033],{},": A validator API for ensuring ERN XML files adhere to DDEX standards.",[822,1450,1451,1221],{},[753,1452,1039],{},[822,1454,1455,1428],{},[753,1456,1045],{},[749,1458,1459],{},[763,1460,1463],{"href":1461,"rel":1462},"https://github.com/elibeta22/ddex-mesage-validator-api",[767],[753,1464,1465],{},"DDEX XML Validator",[819,1467,1468,1472,1477,1482],{},[822,1469,1470,1093],{},[753,1471,1027],{},[822,1473,1474,1476],{},[753,1475,1033],{},": An API tool to validate XML documents against XSD and Schematron schemas for DDEX ERN messages.",[822,1478,1479,1481],{},[753,1480,1039],{},": XSLT",[822,1483,1484,1486],{},[753,1485,1045],{},": elibeta22",[749,1488,1489],{},[763,1490,1493],{"href":1491,"rel":1492},"https://github.com/googleinterns/ddex-mead-parser",[767],[753,1494,1495],{},"DDEX XML/XSD to Protocol Buffer",[819,1497,1498,1503,1508,1513],{},[822,1499,1500,1502],{},[753,1501,1027],{},": MEAD (Metadata Exchange)",[822,1504,1505,1507],{},[753,1506,1033],{},": Converts DDEX XML/XSD messages into Protocol Buffer format for easier usage in applications that rely on binary data protocols.",[822,1509,1510,1512],{},[753,1511,1039],{},": Java",[822,1514,1515,1046],{},[753,1516,1045],{},[749,1518,1519],{},[763,1520,1523],{"href":1521,"rel":1522},"https://github.com/monstercat/transport-ddex",[767],[753,1524,1525],{},"Transport DDEX",[819,1527,1528,1533,1538,1542],{},[822,1529,1530,1532],{},[753,1531,1027],{},": ERN Choreography",[822,1534,1535,1537],{},[753,1536,1033],{},": A Python tool for assisting in the secure transfer of DDEX files over SFTP, enabling reliable file exchanges.",[822,1539,1540,1040],{},[753,1541,1039],{},[822,1543,1544,1546],{},[753,1545,1045],{},": Monster Cat",[749,1548,1549],{},[763,1550,1553],{"href":1551,"rel":1552},"https://github.com/moodleexpert/DDEXPythonParser",[767],[753,1554,1555],{},"DDEX Python Parser",[819,1557,1558,1562,1567,1571],{},[822,1559,1560,1093],{},[753,1561,1027],{},[822,1563,1564,1566],{},[753,1565,1033],{},": Parses DDEX XML files and converts them to JSON format for easier handling in web services and other applications.",[822,1568,1569,1040],{},[753,1570,1039],{},[822,1572,1573,1575],{},[753,1574,1045],{},": Arjun Nikhil",[749,1577,1578],{},[763,1579,1582],{"href":1580,"rel":1581},"https://github.com/miqwit/dedex",[767],[753,1583,1584],{},"DeDEX",[819,1586,1587,1591,1596,1600],{},[822,1588,1589,1093],{},[753,1590,1027],{},[822,1592,1593,1595],{},[753,1594,1033],{},": A parser for DDEX XML files specifically supporting versions 3.8.2 and 4.1 of the ERN standard.",[822,1597,1598,1307],{},[753,1599,1039],{},[822,1601,1602,1604],{},[753,1603,1045],{},": miqwit",[778,1606,1608],{"id":1607},"code-quality","Code Quality",[749,1610,1611,1612,1615,1616,1619,1620,1615,1624,1627],{},"Most of the repositories, such as ",[763,1613,1020],{"href":1016,"rel":1614},[767]," and ",[763,1617,1117],{"href":1113,"rel":1618},[767],", show clean and modular code structures that follow standard practices in their respective languages. This ensures better readability and easier debugging or extension by other developers. Several projects, especially those from large contributors like ",[763,1621,1623],{"href":1491,"rel":1622},[767],"Google's DDEX XML/XSD to Protocol Buffer",[763,1625,1205],{"href":1201,"rel":1626},[767],", adopt coding best practices such as proper documentation within the code, and meaningful commit messages. These repositories are structured in a way that supports easy adoption and scalability.",[778,1629,1631],{"id":1630},"documentation","Documentation",[749,1633,1634,1635,1638,1639,1642,1643,1646],{},"The repositories generally provide adequate README files explaining usage, installation, and setup. For example, the ",[763,1636,1055],{"href":1051,"rel":1637},[767]," repository includes clear links to additional documentation and explains the Ruby serialization process. Similarly, ",[763,1640,1117],{"href":1113,"rel":1641},[767]," includes detailed instructions for integration with Microsoft Visual Studio. While most repositories have decent documentation, some could benefit from more extensive guides. For instance, repositories like ",[763,1644,1584],{"href":1580,"rel":1645},[767]," lack comprehensive usage examples or extended documentation, which might make it harder for newcomers to implement the tool.",[778,1648,1650],{"id":1649},"community-engagement","Community Engagement",[749,1652,1653,1654,1657,1658,1661,1662,1615,1665,1668],{},"Several of the repositories are personal or small-team projects, such as ",[763,1655,1291],{"href":1287,"rel":1656},[767],", which shows limited engagement from the wider community. However, repositories like ",[763,1659,1020],{"href":1016,"rel":1660},[767]," have contributions from large organizations (Google) and are more likely to see community engagement due to their relevance and backing. Repositories like ",[763,1663,1086],{"href":1082,"rel":1664},[767],[763,1666,1147],{"href":1143,"rel":1667},[767]," have open issues, showing active participation in maintaining and improving the code. Repositories without active issue management might face difficulties in sustaining quality as the technology evolves.",[778,1670,1672],{"id":1671},"activity-maintenance","Activity & Maintenance",[749,1674,1675,1676,1679,1680,1683,1684,1687,1688,1615,1691,1695],{},"Some repositories, such as ",[763,1677,1378],{"href":1374,"rel":1678},[767],", have not seen recent updates, which raises concerns about their long-term maintainability. In contrast, repositories like ",[763,1681,1020],{"href":1016,"rel":1682},[767]," or ",[763,1685,1117],{"href":1113,"rel":1686},[767]," show regular commits and improvements, signaling that they are actively maintained. Projects like ",[763,1689,1623],{"href":1491,"rel":1690},[767],[763,1692,1694],{"href":1172,"rel":1693},[767],"DDEXUI"," use proper versioning and commit practices, ensuring clear tracking of changes and fixes over time.",[778,1697,1699],{"id":1698},"testing-cicd","Testing & CI/CD",[749,1701,1702,1703,1706,1707,1710,1711,1714],{},"Repositories with automated tests and CI/CD integration are generally more reliable in production environments. Tools like ",[763,1704,1117],{"href":1113,"rel":1705},[767]," integrate well into Microsoft Visual Studio, implying a strong emphasis on testing and validation. However, repositories such as ",[763,1708,1291],{"href":1287,"rel":1709},[767]," might lack the same level of CI/CD infrastructure. Repositories like ",[763,1712,1147],{"href":1143,"rel":1713},[767]," show robust error handling mechanisms, which improve the reliability of these tools in production.",[778,1716,1718],{"id":1717},"overall-quality-assessment","Overall Quality Assessment",[819,1720,1721,1734,1747],{},[822,1722,1723,1726,1727,1615,1730,1733],{},[753,1724,1725],{},"High Quality",": Projects like ",[763,1728,1020],{"href":1016,"rel":1729},[767],[763,1731,1117],{"href":1113,"rel":1732},[767]," show high quality in terms of code structure, documentation, and community support.",[822,1735,1736,1739,1740,1615,1743,1746],{},[753,1737,1738],{},"Moderate Quality",": Projects such as ",[763,1741,1291],{"href":1287,"rel":1742},[767],[763,1744,1584],{"href":1580,"rel":1745},[767]," offer good functionality but may require additional documentation and updates to maintain relevance.",[822,1748,1749,1752,1753,1756],{},[753,1750,1751],{},"Low Activity or Maintenance Concerns",": Some repositories, like ",[763,1754,1378],{"href":1374,"rel":1755},[767],", show signs of being outdated or have low maintenance activity, which could make them less reliable in the long term.",[749,1758,1759],{},"By analyzing these repositories across various metrics, we can conclude that while most tools are functional and well-built, their long-term value largely depends on regular updates and community engagement.",[778,1761,1763],{"id":1762},"contributing-to-the-musictech-opensource","Contributing to the MusicTech OpenSource",[749,1765,1766],{},[976,1767],{"alt":1768,"src":1769},"DDEX Validator screenshot","/images/cdn-migrated/ddex-screenshot.webp",[749,1771,1772,1773,1780,1781,1784,1785,1788],{},"In addition to the tools offered by DDEX, the ",[763,1774,1777],{"href":1775,"rel":1776},"https://ddexvalidator.musictechlab.io/",[767],[753,1778,1779],{},"MTL DDEX Validator"," is a new open-source project developed to validate DDEX messages. Hosted by ",[753,1782,1783],{},"MusicTech Lab",", this tool is designed to help users ensure compliance with DDEX standards, specifically for validating ",[753,1786,1787],{},"Electronic Release Notification (ERN)"," messages.",[749,1790,1791,1792,1795,1796,1799],{},"The project can be accessed both as a ",[753,1793,1794],{},"web-based tool"," and through its ",[753,1797,1798],{},"GitHub repository",":",[819,1801,1802,1812,1824],{},[822,1803,1804,1807,1808,1811],{},[753,1805,1806],{},"Web Tool",": The ",[763,1809,1779],{"href":1775,"rel":1810},[767]," allows users to upload DDEX XML files and check their conformance with the official standards. This provides a quick and user-friendly way for developers and rights holders to verify their metadata.",[822,1813,1814,1817,1818,1823],{},[753,1815,1816],{},"GitHub",": ",[763,1819,1822],{"href":1820,"rel":1821},"https://github.com/musictechlab/ddex-validator",[767],"MTL DDEX Validator on GitHub"," offers the full codebase, allowing developers to contribute, clone, or modify the validator to suit their needs. This Python-based project focuses on ensuring accurate and up-to-date validations of XML files used for music metadata exchange, making it an invaluable tool for digital service providers and record labels.",[822,1825,1826,1040],{},[753,1827,1039],{},[778,1829,1831],{"id":1830},"additional-resource-musictech-open-source-catalog","Additional Resource: MusicTech Open-Source Catalog",[749,1833,1834,1835,1842],{},"The ",[763,1836,1839],{"href":1837,"rel":1838},"https://musictechlab.io/resources",[767],[753,1840,1841],{},"MusicTech Open-Source Catalog"," by MusicTech Lab is a dedicated resource for music technology tools, including DDEX-specific projects. It offers a variety of open-source tools designed to help developers in the music industry.",[778,1844,1846],{"id":1845},"in-need-of-ddex-standard-implementation","In need of DDEX standard implementation?",[749,1848,1849,1850,1852,1853,1859],{},"If you need expert support for integrating DDEX standards into your digital music platform, ",[753,1851,1783],{}," offers professional services to streamline implementation. Learn more and get started with DDEX integration by visiting the ",[763,1854,1856],{"href":918,"rel":1855},[767],[753,1857,1858],{},"MusicTech Lab DDEX Integration Services"," for personalized solutions tailored to your business needs.",{"title":920,"searchDepth":921,"depth":921,"links":1861},[1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873],{"id":988,"depth":921,"text":989},{"id":995,"depth":921,"text":996},{"id":1007,"depth":921,"text":1008},{"id":1607,"depth":921,"text":1608},{"id":1630,"depth":921,"text":1631},{"id":1649,"depth":921,"text":1650},{"id":1671,"depth":921,"text":1672},{"id":1698,"depth":921,"text":1699},{"id":1717,"depth":921,"text":1718},{"id":1762,"depth":921,"text":1763},{"id":1830,"depth":921,"text":1831},{"id":1845,"depth":921,"text":1846},"2024-09-12T00:00:00.000Z",{"src":1876},"/images/blog/musictechlab_blog_ddex-open-source-projects-review.webp",{"enabled":935,"items":1878},[1879,1882,1885,1888],{"text":1880,"icon":1881},"20+ open source DDEX tools exist across Python, Ruby, C#, PHP, JavaScript, and Java.","i-lucide-code",{"text":1883,"icon":1884},"Google's dsrf parser and the DDEX Validator are the highest-quality maintained projects.","i-lucide-star",{"text":1886,"icon":1887},"Many repositories lack recent updates, raising long-term maintainability concerns.","i-lucide-alert-triangle",{"text":1889,"icon":942},"MTL DDEX Validator is an open source web tool for validating ERN messages.",{},{"title":136,"description":957},[949,950,951],"1iGHR1ZyKl8mlFxEovkzHfYNK3VJPZ4Q8fDBbFxCZs8",5,{"id":1896,"title":120,"authors":1897,"badge":1900,"body":1903,"category":927,"client":928,"date":3842,"description":3843,"extension":931,"faq":3844,"featured":69,"featuredOrder":928,"hidden":69,"image":3854,"keyTakeaways":3856,"meta":3869,"navigation":935,"path":121,"seo":3870,"status":928,"stem":122,"tags":3873,"teaser":928,"__hash__":3878,"score":2850},"posts/blog/music-data/c2pa-and-ddex-authenticity-meets-rights-in-the-age-of-ai-music.md",[1898],{"name":963,"to":964,"avatar":1899},{"src":966},{"label":1901,"color":1902},"Distribution","#0ea5e9",{"type":746,"value":1904,"toc":3815},[1905,1908,1923,1927,1930,1934,1937,1955,1962,1973,1977,1980,2009,2011,2014,2018,2021,2095,2101,2105,2108,2140,2147,2151,2318,2322,2325,2372,2376,2383,2386,2397,2401,2404,2408,2411,2422,2426,2429,2440,2457,2461,2464,2582,2593,2597,2600,2745,2749,2752,2761,2766,2783,2800,2804,2808,2814,3376,3380,3395,3679,3690,3694,3761,3765,3775,3778,3781,3808,3811],[749,1906,1907],{},"A track lands on a streaming platform. It sounds like a well-known artist, but was it actually recorded by them -or generated by an AI model trained on their catalog? And regardless of origin, who should receive the royalties?",[749,1909,1910,1911,1615,1914,1917,1918,1615,1921,756],{},"These two questions -",[753,1912,1913],{},"\"is this real?\"",[753,1915,1916],{},"\"who gets paid?\""," -sit at the heart of the music industry's biggest challenges today. Two very different standards are stepping up to answer them: ",[753,1919,1920],{},"C2PA",[753,1922,949],{},[778,1924,1926],{"id":1925},"what-is-c2pa","What is C2PA?",[749,1928,1929],{},"C2PA (Coalition for Content Provenance and Authenticity) is an open standard for proving the origin and history of digital content. Think of it as a tamper-proof seal for media files: images, video, audio, and documents.",[1931,1932,1933],"h3",{"id":873},"How it works",[749,1935,1936],{},"The standard operates through three core mechanisms:",[783,1938,1940,1945,1950],{"className":1939},[786,787,878,789,790],[792,1941],{"description":1942,"icon":1943,"title":1944},"Cryptographically signed metadata embedded in files. They record who created or edited the content, what tools were used, and when the changes happened.","i-lucide-fingerprint","Content Credentials",[792,1946],{"description":1947,"icon":1948,"title":1949},"Structured metadata containers attached to content. Each manifest holds assertions (claims about the content) and a digital signature that can be verified against a certificate chain.","i-lucide-file-check","Manifests",[792,1951],{"description":1952,"icon":1953,"title":1954},"Cryptographic ties between the manifest and the actual content bytes. If someone tampers with the file, the binding breaks and verification fails.","i-lucide-link","Hard Bindings",[749,1956,1957,1958,1961],{},"Every time content is created or edited, a new manifest entry is added, forming a ",[753,1959,1960],{},"provenance chain",". A camera captures an image and signs it. An editor crops it and adds a new signed manifest. An AI model generates a track and labels it as AI-created. Each step is recorded and verifiable.",[838,1963,1964],{},[749,1965,1966,1967,1972],{},"C2PA was ",[763,1968,1971],{"href":1969,"rel":1970},"https://c2pa.org/about/",[767],"founded by Adobe, Arm, Intel, Microsoft, and Truepic"," as a Joint Development Foundation project. It unifies two earlier initiatives: the Adobe-led Content Authenticity Initiative (CAI) and Project Origin, a Microsoft- and BBC-led effort tackling disinformation in digital news. The coalition has since grown to include Sony, Nikon, Google, OpenAI, and many others.",[1931,1974,1976],{"id":1975},"c2pa-for-audio","C2PA for audio",[749,1978,1979],{},"While C2PA gained traction in the image and video space first, audio support is growing. The spec already supports audio file formats, and the implications for music are significant:",[819,1981,1982,1997,2003],{},[822,1983,1984,1987,1988,1992,1993,1996],{},[753,1985,1986],{},"AI transparency"," -a generative model like Suno or Udio could embed a C2PA manifest with a ",[1989,1990,1991],"code",{},"digitalSourceType"," (defined by IPTC) of ",[1989,1994,1995],{},"trainedAlgorithmicMedia",", the standard way to declare content as AI-generated. Additional assertions can capture model details and prompts",[822,1998,1999,2002],{},[753,2000,2001],{},"Recording provenance"," -a DAW or recording device could sign audio at the point of capture, creating a verifiable chain from microphone to master. We are just starting to see reference implementations where stems -with or without provenance -can be mixed into a final and saved with provenance that includes ingredients, but these are demos and PoCs. No DAW has committed to shipping C2PA support yet",[822,2004,2005,2008],{},[753,2006,2007],{},"Remix and sample tracking"," -each derivative work adds a manifest, linking back to source material",[778,2010,989],{"id":988},[749,2012,2013],{},"DDEX (Digital Data Exchange) is a group of music industry players that builds standards for sharing data about music. While C2PA asks \"is this content real?\", DDEX asks \"who owns this, and how should they be paid?\"",[1931,2015,2017],{"id":2016},"the-ddex-standard-family","The DDEX standard family",[749,2019,2020],{},"DDEX isn't a single standard -it's a family of XML and JSON-based messaging formats:",[2022,2023,2024,2036],"table",{},[2025,2026,2027],"thead",{},[2028,2029,2030,2033],"tr",{},[2031,2032,1027],"th",{},[2031,2034,2035],{},"Purpose",[2037,2038,2039,2051,2062,2073,2084],"tbody",{},[2028,2040,2041,2048],{},[2042,2043,2044,2047],"td",{},[753,2045,2046],{},"ERN"," (Electronic Release Notification)",[2042,2049,2050],{},"Delivering releases from labels to DSPs",[2028,2052,2053,2059],{},[2042,2054,2055,2058],{},[753,2056,2057],{},"MWN"," (Musical Works Notification)",[2042,2060,2061],{},"Communicating musical works data between publishers and societies",[2028,2063,2064,2070],{},[2042,2065,2066,2069],{},[753,2067,2068],{},"MEAD"," (Media Enrichment and Description)",[2042,2071,2072],{},"Enriching metadata for discovery and curation",[2028,2074,2075,2081],{},[2042,2076,2077,2080],{},[753,2078,2079],{},"DSR"," (Digital Sales Reporting)",[2042,2082,2083],{},"Reporting sales and streams back to rights holders",[2028,2085,2086,2092],{},[2042,2087,2088,2091],{},[753,2089,2090],{},"RDR"," (Recording Data and Rights)",[2042,2093,2094],{},"Linking sound recordings to musical works and their rights holders",[2096,2097,2098],"tip",{},[749,2099,2100],{},"If you distribute music to Spotify, Apple Music, Amazon, or any major DSP, your distributor is almost certainly using DDEX ERN messages under the hood.",[1931,2102,2104],{"id":2103},"what-ddex-carries","What DDEX carries",[749,2106,2107],{},"A DDEX message typically contains:",[819,2109,2110,2116,2122,2128,2134],{},[822,2111,2112,2115],{},[753,2113,2114],{},"Release metadata"," -title, artist, label, UPC/EAN, genre, release date",[822,2117,2118,2121],{},[753,2119,2120],{},"Track-level data"," -ISRC codes, duration, contributors, territories",[822,2123,2124,2127],{},[753,2125,2126],{},"Rights and licensing"," -who owns what, in which territories, under which terms",[822,2129,2130,2133],{},[753,2131,2132],{},"Commercial terms"," -pricing, availability windows, pre-order dates",[822,2135,2136,2139],{},[753,2137,2138],{},"Royalty reporting"," -stream counts, revenue splits, payment details",[749,2141,2142,2143,2146],{},"In practice, this metadata arrives from every distributor in different formats and naming conventions. Even something as simple as a retailer name can appear ",[763,2144,2145],{"href":81},"830 different ways across sources",", which is why normalisation is a critical step before any of this data becomes useful.",[778,2148,2150],{"id":2149},"who-are-these-standards-designed-for","Who are these standards designed for?",[783,2152,2154,2237],{"className":2153},[786,787,788,789,790],[792,2155,2159],{"description":2156,"icon":2157,"title":2158},"Anyone who creates, distributes, or consumes digital content.","i-lucide-building-2","C2PA -Who benefits",[2022,2160,2161,2171],{},[2025,2162,2163],{},[2028,2164,2165,2168],{},[2031,2166,2167],{},"Stakeholder",[2031,2169,2170],{},"How they use C2PA",[2037,2172,2173,2184,2195,2206,2216,2226],{},[2028,2174,2175,2181],{},[2042,2176,2177,2180],{},[753,2178,2179],{},"DAW vendors"," (Ableton, Logic, Pro Tools)",[2042,2182,2183],{},"Sign audio at export to prove origin",[2028,2185,2186,2192],{},[2042,2187,2188,2191],{},[753,2189,2190],{},"AI music platforms"," (Suno, Udio)",[2042,2193,2194],{},"Label outputs as AI-generated with model details",[2028,2196,2197,2203],{},[2042,2198,2199,2202],{},[753,2200,2201],{},"Streaming platforms"," (Spotify, Apple Music)",[2042,2204,2205],{},"Verify content authenticity at ingest",[2028,2207,2208,2213],{},[2042,2209,2210],{},[753,2211,2212],{},"News organizations",[2042,2214,2215],{},"Confirm audio/video hasn't been manipulated",[2028,2217,2218,2223],{},[2042,2219,2220],{},[753,2221,2222],{},"Creators and artists",[2042,2224,2225],{},"Prove their work is original and human-made",[2028,2227,2228,2234],{},[2042,2229,2230,2233],{},[753,2231,2232],{},"Hardware manufacturers"," (Nikon, Sony)",[2042,2235,2236],{},"Embed provenance at point of capture",[792,2238,2242],{"description":2239,"icon":2240,"title":2241},"Music industry players who need to exchange rights and commercial data.","i-lucide-music","DDEX -Who benefits",[2022,2243,2244,2253],{},[2025,2245,2246],{},[2028,2247,2248,2250],{},[2031,2249,2167],{},[2031,2251,2252],{},"How they use DDEX",[2037,2254,2255,2265,2276,2287,2297,2308],{},[2028,2256,2257,2262],{},[2042,2258,2259],{},[753,2260,2261],{},"Record labels",[2042,2263,2264],{},"Deliver releases and metadata to DSPs",[2028,2266,2267,2273],{},[2042,2268,2269,2272],{},[753,2270,2271],{},"Distributors"," (DistroKid, TuneCore)",[2042,2274,2275],{},"Automate release delivery via ERN messages",[2028,2277,2278,2284],{},[2042,2279,2280,2283],{},[753,2281,2282],{},"DSPs"," (Spotify, Apple Music, Amazon)",[2042,2285,2286],{},"Ingest releases with structured rights data",[2028,2288,2289,2294],{},[2042,2290,2291],{},[753,2292,2293],{},"Publishers",[2042,2295,2296],{},"Communicate musical works ownership via MWN",[2028,2298,2299,2305],{},[2042,2300,2301,2304],{},[753,2302,2303],{},"Collecting societies"," (ASCAP, PRS, ZAIKS)",[2042,2306,2307],{},"Process royalty claims and distributions",[2028,2309,2310,2315],{},[2042,2311,2312],{},[753,2313,2314],{},"Independent artists",[2042,2316,2317],{},"Get paid correctly through standardized reporting",[778,2319,2321],{"id":2320},"the-fundamental-difference","The fundamental difference",[749,2323,2324],{},"Here's the core distinction:",[783,2326,2328,2350],{"className":2327},[786,787,788,789,790],[792,2329,2333],{"description":2330,"icon":2331,"title":2332},"Was this content tampered with? Who created it? Was AI involved?","i-lucide-shield-check","C2PA -Trust Layer",[819,2334,2335,2338,2341,2344,2347],{},[822,2336,2337],{},"Cryptographic proof of origin",[822,2339,2340],{},"Tamper-evident edit history",[822,2342,2343],{},"AI disclosure and labeling",[822,2345,2346],{},"Works on any digital media",[822,2348,2349],{},"PKI-based trust model (see below)",[792,2351,2355],{"description":2352,"icon":2353,"title":2354},"Who owns the rights? How should royalties be split? Where can this be distributed?","i-lucide-receipt","DDEX -Commerce Layer",[819,2356,2357,2360,2363,2366,2369],{},[822,2358,2359],{},"Rights ownership and splits",[822,2361,2362],{},"Commercial metadata exchange",[822,2364,2365],{},"Royalty reporting and payment",[822,2367,2368],{},"Music industry specific",[822,2370,2371],{},"B2B contractual trust model",[1931,2373,2375],{"id":2374},"how-c2pa-trust-works-pki-in-plain-terms","How C2PA trust works: PKI in plain terms",[749,2377,2378,2379,2382],{},"C2PA relies on ",[753,2380,2381],{},"Public Key Infrastructure (PKI)",", the same trust system that secures HTTPS websites. Every app or device that creates content holds a private key and a certificate from a trusted authority. When a C2PA manifest is signed, anyone can check that signature against the certificate chain, up to a root Certificate Authority (CA). If it checks out, you know the manifest is untouched and you know who produced it. Change even a single byte of the file, and the signature breaks.",[749,2384,2385],{},"In practice, this means a DAW vendor like Ableton could obtain a C2PA certificate, sign every exported master, and any platform receiving that file can verify it came from Ableton's software, untouched.",[749,2387,2388,2389,2392,2393,2396],{},"They operate at different layers of the content lifecycle. C2PA is about the ",[753,2390,2391],{},"integrity of the content itself"," -its provenance and authenticity. DDEX is about the ",[753,2394,2395],{},"business logic surrounding the content"," -ownership, distribution, and compensation.",[778,2398,2400],{"id":2399},"why-ai-music-needs-both","Why AI music needs both",[749,2402,2403],{},"The rise of AI-generated music is exactly why both standards matter now.",[1931,2405,2407],{"id":2406},"the-authenticity-problem","The authenticity problem",[749,2409,2410],{},"When an AI model can generate a track that sounds identical to a human recording, platforms, listeners, and rights holders all need to know the origin. Without C2PA-style provenance:",[819,2412,2413,2416,2419],{},[822,2414,2415],{},"A generated track could be uploaded as an \"original recording\" and claim royalties under false pretenses",[822,2417,2418],{},"Training data attribution becomes impossible to verify",[822,2420,2421],{},"Deepfake audio of real artists erodes trust across the entire ecosystem",[1931,2423,2425],{"id":2424},"the-rights-problem","The rights problem",[749,2427,2428],{},"Even when AI origin is disclosed, the rights questions are hard:",[819,2430,2431,2434,2437],{},[822,2432,2433],{},"Who owns an AI-generated track -the prompter, the model operator, or the training data contributors?",[822,2435,2436],{},"If a model was trained on copyrighted recordings, how should those rights holders be compensated?",[822,2438,2439],{},"How do existing DDEX workflows handle a \"performer\" that is a language model?",[892,2441,2442],{},[749,2443,2444,2445,2448,2449,2452,2453,2456],{},"Current DDEX schemas weren't built for AI-generated content. Fields like ",[1989,2446,2447],{},"Artist",", ",[1989,2450,2451],{},"Performer",", and ",[1989,2454,2455],{},"Contributor"," assume human creators. The industry will need to extend these standards, or build new ones, to handle AI provenance and attribution.",[1931,2458,2460],{"id":2459},"the-combined-solution","The combined solution",[749,2462,2463],{},"Imagine a future where a single music file carries both layers:",[783,2465,2467,2526],{"className":2466},[786,787,788,789,790],[792,2468,2471],{"description":2469,"icon":2331,"title":2470},"Authenticity and provenance layer embedded in the file.","C2PA Manifest",[2022,2472,2473,2483],{},[2025,2474,2475],{},[2028,2476,2477,2480],{},[2031,2478,2479],{},"Field",[2031,2481,2482],{},"Value",[2037,2484,2485,2493,2502,2510,2518],{},[2028,2486,2487,2490],{},[2042,2488,2489],{},"Created by",[2042,2491,2492],{},"SunoAI v4.0",[2028,2494,2495,2497],{},[2042,2496,1991],{},[2042,2498,2499,2501],{},[1989,2500,1995],{}," (IPTC)",[2028,2503,2504,2507],{},[2042,2505,2506],{},"Prompt",[2042,2508,2509],{},"\"upbeat jazz fusion, 120 BPM\"",[2028,2511,2512,2515],{},[2042,2513,2514],{},"Training data",[2042,2516,2517],{},"Licensed Dataset X",[2028,2519,2520,2523],{},[2042,2521,2522],{},"Signature",[2042,2524,2525],{},"Valid (SunoAI cert)",[792,2527,2530],{"description":2528,"icon":2353,"title":2529},"Commercial and rights layer for distribution and payment.","DDEX Metadata",[2022,2531,2532,2540],{},[2025,2533,2534],{},[2028,2535,2536,2538],{},[2031,2537,2479],{},[2031,2539,2482],{},[2037,2541,2542,2550,2558,2566,2574],{},[2028,2543,2544,2547],{},[2042,2545,2546],{},"ISRC",[2042,2548,2549],{},"USXX42312345",[2028,2551,2552,2555],{},[2042,2553,2554],{},"Rights holder",[2042,2556,2557],{},"Acme Music LLC",[2028,2559,2560,2563],{},[2042,2561,2562],{},"Royalty split",[2042,2564,2565],{},"70% publisher / 30% AI",[2028,2567,2568,2571],{},[2042,2569,2570],{},"Territory",[2042,2572,2573],{},"Worldwide",[2028,2575,2576,2579],{},[2042,2577,2578],{},"Distributor",[2042,2580,2581],{},"DistroKid",[749,2583,2584,2585,2588,2589,2592],{},"The C2PA layer provides ",[753,2586,2587],{},"verifiable proof"," of how the content was created. The DDEX layer provides ",[753,2590,2591],{},"the commercial framework"," for distributing it and paying the right parties.",[778,2594,2596],{"id":2595},"technical-integration-points","Technical integration points",[749,2598,2599],{},"For developers and music tech teams thinking about implementation, here are the key integration points:",[783,2601,2603,2646,2703],{"className":2602},[786,787,878,789,790],[792,2604,2608],{"description":2605,"icon":2606,"title":2607},"When a track arrives at a DSP or distributor, run these checks in sequence.","i-lucide-scan-search","Ingest Pipeline",[2022,2609,2610,2620],{},[2025,2611,2612],{},[2028,2613,2614,2617],{},[2031,2615,2616],{},"Step",[2031,2618,2619],{},"Action",[2037,2621,2622,2630,2638],{},[2028,2623,2624,2627],{},[2042,2625,2626],{},"Validate C2PA",[2042,2628,2629],{},"Check signature chain, verify content integrity, extract provenance",[2028,2631,2632,2635],{},[2042,2633,2634],{},"Parse DDEX",[2042,2636,2637],{},"Extract rights, contributors, and commercial terms",[2028,2639,2640,2643],{},[2042,2641,2642],{},"Cross-reference",[2042,2644,2645],{},"Flag mismatches (e.g. C2PA says \"AI-generated\" but DDEX lists a human performer)",[792,2647,2651],{"description":2648,"icon":2649,"title":2650},"C2PA provenance data can automatically populate DDEX fields.","i-lucide-merge","Metadata Enrichment",[2022,2652,2653,2663],{},[2025,2654,2655],{},[2028,2656,2657,2660],{},[2031,2658,2659],{},"C2PA Source",[2031,2661,2662],{},"DDEX Target",[2037,2664,2665,2680,2689],{},[2028,2666,2667,2672],{},[2042,2668,2669],{},[1989,2670,2671],{},"creator",[2042,2673,2674,2677,2678],{},[1989,2675,2676],{},"DisplayArtist"," / ",[1989,2679,2455],{},[2028,2681,2682,2686],{},[2042,2683,2684],{},[1989,2685,1991],{},[2042,2687,2688],{},"Extension field for AI disclosure",[2028,2690,2691,2697],{},[2042,2692,2693,2696],{},[1989,2694,2695],{},"source material"," refs",[2042,2698,2699,2702],{},[1989,2700,2701],{},"RelatedRelease"," links",[792,2704,2708],{"description":2705,"icon":2706,"title":2707},"Before distributing a track, a platform should verify both layers.","i-lucide-check-circle","Rights Verification",[2022,2709,2710,2719],{},[2025,2711,2712],{},[2028,2713,2714,2717],{},[2031,2715,2716],{},"Check",[2031,2718,2035],{},[2037,2720,2721,2729,2737],{},[2028,2722,2723,2726],{},[2042,2724,2725],{},"C2PA chain",[2042,2727,2728],{},"Confirm submitter has legitimate access to the content",[2028,2730,2731,2734],{},[2042,2732,2733],{},"DDEX rights",[2042,2735,2736],{},"Confirm distribution is authorized for the target territory",[2028,2738,2739,2742],{},[2042,2740,2741],{},"Training data refs",[2042,2743,2744],{},"Verify licensing compliance for AI-generated content",[778,2746,2748],{"id":2747},"whats-happening-now","What's happening now",[749,2750,2751],{},"Both standards are actively evolving:",[749,2753,2754,2756,2757,2760],{},[753,2755,1920],{}," released version 2.3 of the specification and the ecosystem is growing rapidly. The ",[1989,2758,2759],{},"c2patool"," CLI and libraries in Rust, JavaScript, and Python make it possible to read and write C2PA manifests programmatically, though writing manifests correctly is non-trivial in practice.",[749,2762,2763,2765],{},[753,2764,949],{}," continues to refine its standards. ERN 4.3 is the latest release notification format, and there are ongoing discussions within the consortium about how to handle AI-generated content within existing schemas.",[838,2767,2768],{},[749,2769,2770,2771,2773,2774,2779,2780,2782],{},"The C2PA spec requires every asset to include a ",[1989,2772,1991],{}," as defined by ",[763,2775,2778],{"href":2776,"rel":2777},"https://iptc.org/",[767],"IPTC",". For AI-generated content, the value is ",[1989,2781,1995],{},". There are additional assertions available for AI content, but in practice consumption and verification tooling is still catching up -much of this remains theoretical for now.",[2096,2784,2785],{},[749,2786,2787,2788,2793,2794,2799],{},"If you're building music tech infrastructure, start experimenting with C2PA now. The ",[763,2789,2792],{"href":2790,"rel":2791},"https://github.com/contentauth/c2pa-rs",[767],"c2pa-rs"," Rust crate and ",[763,2795,2798],{"href":2796,"rel":2797},"https://github.com/contentauth/c2pa-node",[767],"c2pa-node"," JavaScript library are production-ready and well-documented. You can get quite far using the development certificate for testing.",[778,2801,2803],{"id":2802},"code-examples","Code examples",[1931,2805,2807],{"id":2806},"reading-a-c2pa-manifest-with-python","Reading a C2PA manifest with Python",[749,2809,1834,2810,2813],{},[1989,2811,2812],{},"c2pa-python"," library lets you read and validate Content Credentials from any supported file:",[2815,2816,2821],"pre",{"className":2817,"code":2818,"filename":2819,"language":2820,"meta":920,"style":920},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import c2pa\n\n# Read the C2PA manifest from an audio file\nreader = c2pa.Reader.from_file(\"track.wav\")\n\n# Get the active manifest (most recent signer)\nmanifest = reader.get_active_manifest()\n\nprint(f\"Title: {manifest['title']}\")\nprint(f\"Format: {manifest['format']}\")\n\n# Check assertions -was this AI-generated?\nfor assertion in manifest.get(\"assertions\", []):\n    if assertion[\"label\"] == \"c2pa.actions\":\n        for action in assertion[\"data\"][\"actions\"]:\n            print(f\"Action: {action['action']}\")\n            if \"softwareAgent\" in action:\n                print(f\"Software: {action['softwareAgent']}\")\n            # digitalSourceType is required by the spec (IPTC vocabulary)\n            # trainedAlgorithmicMedia = AI-generated content\n            if \"digitalSourceType\" in action:\n                print(f\"Source type: {action['digitalSourceType']}\")\n\n# Validate the signature chain\nvalidation = reader.validation_status\nif not validation:\n    print(\"Signature: VALID\")\nelse:\n    for status in validation:\n        print(f\"Issue: {status['code']}\")\n","read_c2pa.py","python",[1989,2822,2823,2836,2841,2848,2888,2892,2898,2917,2922,2965,2998,3003,3009,3044,3078,3113,3147,3168,3201,3207,3213,3230,3262,3267,3273,3288,3302,3319,3327,3342],{"__ignoreMap":920},[2824,2825,2828,2832],"span",{"class":2826,"line":2827},"line",1,[2824,2829,2831],{"class":2830},"s7zQu","import",[2824,2833,2835],{"class":2834},"sTEyZ"," c2pa\n",[2824,2837,2838],{"class":2826,"line":921},[2824,2839,2840],{"emptyLinePlaceholder":935},"\n",[2824,2842,2844],{"class":2826,"line":2843},3,[2824,2845,2847],{"class":2846},"sHwdD","# Read the C2PA manifest from an audio file\n",[2824,2849,2851,2854,2858,2861,2863,2867,2869,2873,2876,2879,2883,2885],{"class":2826,"line":2850},4,[2824,2852,2853],{"class":2834},"reader ",[2824,2855,2857],{"class":2856},"sMK4o","=",[2824,2859,2860],{"class":2834}," c2pa",[2824,2862,756],{"class":2856},[2824,2864,2866],{"class":2865},"swJcz","Reader",[2824,2868,756],{"class":2856},[2824,2870,2872],{"class":2871},"s2Zo4","from_file",[2824,2874,2875],{"class":2856},"(",[2824,2877,2878],{"class":2856},"\"",[2824,2880,2882],{"class":2881},"sfazB","track.wav",[2824,2884,2878],{"class":2856},[2824,2886,2887],{"class":2856},")\n",[2824,2889,2890],{"class":2826,"line":1894},[2824,2891,2840],{"emptyLinePlaceholder":935},[2824,2893,2895],{"class":2826,"line":2894},6,[2824,2896,2897],{"class":2846},"# Get the active manifest (most recent signer)\n",[2824,2899,2901,2904,2906,2909,2911,2914],{"class":2826,"line":2900},7,[2824,2902,2903],{"class":2834},"manifest ",[2824,2905,2857],{"class":2856},[2824,2907,2908],{"class":2834}," reader",[2824,2910,756],{"class":2856},[2824,2912,2913],{"class":2871},"get_active_manifest",[2824,2915,2916],{"class":2856},"()\n",[2824,2918,2920],{"class":2826,"line":2919},8,[2824,2921,2840],{"emptyLinePlaceholder":935},[2824,2923,2925,2928,2930,2934,2937,2941,2944,2947,2950,2953,2955,2958,2961,2963],{"class":2826,"line":2924},9,[2824,2926,2927],{"class":2871},"print",[2824,2929,2875],{"class":2856},[2824,2931,2933],{"class":2932},"spNyl","f",[2824,2935,2936],{"class":2881},"\"Title: ",[2824,2938,2940],{"class":2939},"sbssI","{",[2824,2942,2943],{"class":2871},"manifest",[2824,2945,2946],{"class":2856},"[",[2824,2948,2949],{"class":2856},"'",[2824,2951,2952],{"class":2881},"title",[2824,2954,2949],{"class":2856},[2824,2956,2957],{"class":2856},"]",[2824,2959,2960],{"class":2939},"}",[2824,2962,2878],{"class":2881},[2824,2964,2887],{"class":2856},[2824,2966,2968,2970,2972,2974,2977,2979,2981,2983,2985,2988,2990,2992,2994,2996],{"class":2826,"line":2967},10,[2824,2969,2927],{"class":2871},[2824,2971,2875],{"class":2856},[2824,2973,2933],{"class":2932},[2824,2975,2976],{"class":2881},"\"Format: ",[2824,2978,2940],{"class":2939},[2824,2980,2943],{"class":2871},[2824,2982,2946],{"class":2856},[2824,2984,2949],{"class":2856},[2824,2986,2987],{"class":2881},"format",[2824,2989,2949],{"class":2856},[2824,2991,2957],{"class":2856},[2824,2993,2960],{"class":2939},[2824,2995,2878],{"class":2881},[2824,2997,2887],{"class":2856},[2824,2999,3001],{"class":2826,"line":3000},11,[2824,3002,2840],{"emptyLinePlaceholder":935},[2824,3004,3006],{"class":2826,"line":3005},12,[2824,3007,3008],{"class":2846},"# Check assertions -was this AI-generated?\n",[2824,3010,3012,3015,3018,3021,3024,3026,3029,3031,3033,3036,3038,3041],{"class":2826,"line":3011},13,[2824,3013,3014],{"class":2830},"for",[2824,3016,3017],{"class":2834}," assertion ",[2824,3019,3020],{"class":2830},"in",[2824,3022,3023],{"class":2834}," manifest",[2824,3025,756],{"class":2856},[2824,3027,3028],{"class":2871},"get",[2824,3030,2875],{"class":2856},[2824,3032,2878],{"class":2856},[2824,3034,3035],{"class":2881},"assertions",[2824,3037,2878],{"class":2856},[2824,3039,3040],{"class":2856},",",[2824,3042,3043],{"class":2856}," []):\n",[2824,3045,3047,3050,3053,3055,3057,3060,3062,3064,3067,3070,3073,3075],{"class":2826,"line":3046},14,[2824,3048,3049],{"class":2830},"    if",[2824,3051,3052],{"class":2834}," assertion",[2824,3054,2946],{"class":2856},[2824,3056,2878],{"class":2856},[2824,3058,3059],{"class":2881},"label",[2824,3061,2878],{"class":2856},[2824,3063,2957],{"class":2856},[2824,3065,3066],{"class":2856}," ==",[2824,3068,3069],{"class":2856}," \"",[2824,3071,3072],{"class":2881},"c2pa.actions",[2824,3074,2878],{"class":2856},[2824,3076,3077],{"class":2856},":\n",[2824,3079,3081,3084,3087,3089,3091,3093,3095,3098,3100,3103,3105,3108,3110],{"class":2826,"line":3080},15,[2824,3082,3083],{"class":2830},"        for",[2824,3085,3086],{"class":2834}," action ",[2824,3088,3020],{"class":2830},[2824,3090,3052],{"class":2834},[2824,3092,2946],{"class":2856},[2824,3094,2878],{"class":2856},[2824,3096,3097],{"class":2881},"data",[2824,3099,2878],{"class":2856},[2824,3101,3102],{"class":2856},"][",[2824,3104,2878],{"class":2856},[2824,3106,3107],{"class":2881},"actions",[2824,3109,2878],{"class":2856},[2824,3111,3112],{"class":2856},"]:\n",[2824,3114,3116,3119,3121,3123,3126,3128,3131,3133,3135,3137,3139,3141,3143,3145],{"class":2826,"line":3115},16,[2824,3117,3118],{"class":2871},"            print",[2824,3120,2875],{"class":2856},[2824,3122,2933],{"class":2932},[2824,3124,3125],{"class":2881},"\"Action: ",[2824,3127,2940],{"class":2939},[2824,3129,3130],{"class":2871},"action",[2824,3132,2946],{"class":2856},[2824,3134,2949],{"class":2856},[2824,3136,3130],{"class":2881},[2824,3138,2949],{"class":2856},[2824,3140,2957],{"class":2856},[2824,3142,2960],{"class":2939},[2824,3144,2878],{"class":2881},[2824,3146,2887],{"class":2856},[2824,3148,3150,3153,3155,3158,3160,3163,3166],{"class":2826,"line":3149},17,[2824,3151,3152],{"class":2830},"            if",[2824,3154,3069],{"class":2856},[2824,3156,3157],{"class":2881},"softwareAgent",[2824,3159,2878],{"class":2856},[2824,3161,3162],{"class":2856}," in",[2824,3164,3165],{"class":2834}," action",[2824,3167,3077],{"class":2856},[2824,3169,3171,3174,3176,3178,3181,3183,3185,3187,3189,3191,3193,3195,3197,3199],{"class":2826,"line":3170},18,[2824,3172,3173],{"class":2871},"                print",[2824,3175,2875],{"class":2856},[2824,3177,2933],{"class":2932},[2824,3179,3180],{"class":2881},"\"Software: ",[2824,3182,2940],{"class":2939},[2824,3184,3130],{"class":2871},[2824,3186,2946],{"class":2856},[2824,3188,2949],{"class":2856},[2824,3190,3157],{"class":2881},[2824,3192,2949],{"class":2856},[2824,3194,2957],{"class":2856},[2824,3196,2960],{"class":2939},[2824,3198,2878],{"class":2881},[2824,3200,2887],{"class":2856},[2824,3202,3204],{"class":2826,"line":3203},19,[2824,3205,3206],{"class":2846},"            # digitalSourceType is required by the spec (IPTC vocabulary)\n",[2824,3208,3210],{"class":2826,"line":3209},20,[2824,3211,3212],{"class":2846},"            # trainedAlgorithmicMedia = AI-generated content\n",[2824,3214,3216,3218,3220,3222,3224,3226,3228],{"class":2826,"line":3215},21,[2824,3217,3152],{"class":2830},[2824,3219,3069],{"class":2856},[2824,3221,1991],{"class":2881},[2824,3223,2878],{"class":2856},[2824,3225,3162],{"class":2856},[2824,3227,3165],{"class":2834},[2824,3229,3077],{"class":2856},[2824,3231,3233,3235,3237,3239,3242,3244,3246,3248,3250,3252,3254,3256,3258,3260],{"class":2826,"line":3232},22,[2824,3234,3173],{"class":2871},[2824,3236,2875],{"class":2856},[2824,3238,2933],{"class":2932},[2824,3240,3241],{"class":2881},"\"Source type: ",[2824,3243,2940],{"class":2939},[2824,3245,3130],{"class":2871},[2824,3247,2946],{"class":2856},[2824,3249,2949],{"class":2856},[2824,3251,1991],{"class":2881},[2824,3253,2949],{"class":2856},[2824,3255,2957],{"class":2856},[2824,3257,2960],{"class":2939},[2824,3259,2878],{"class":2881},[2824,3261,2887],{"class":2856},[2824,3263,3265],{"class":2826,"line":3264},23,[2824,3266,2840],{"emptyLinePlaceholder":935},[2824,3268,3270],{"class":2826,"line":3269},24,[2824,3271,3272],{"class":2846},"# Validate the signature chain\n",[2824,3274,3276,3279,3281,3283,3285],{"class":2826,"line":3275},25,[2824,3277,3278],{"class":2834},"validation ",[2824,3280,2857],{"class":2856},[2824,3282,2908],{"class":2834},[2824,3284,756],{"class":2856},[2824,3286,3287],{"class":2865},"validation_status\n",[2824,3289,3291,3294,3297,3300],{"class":2826,"line":3290},26,[2824,3292,3293],{"class":2830},"if",[2824,3295,3296],{"class":2856}," not",[2824,3298,3299],{"class":2834}," validation",[2824,3301,3077],{"class":2856},[2824,3303,3305,3308,3310,3312,3315,3317],{"class":2826,"line":3304},27,[2824,3306,3307],{"class":2871},"    print",[2824,3309,2875],{"class":2856},[2824,3311,2878],{"class":2856},[2824,3313,3314],{"class":2881},"Signature: VALID",[2824,3316,2878],{"class":2856},[2824,3318,2887],{"class":2856},[2824,3320,3322,3325],{"class":2826,"line":3321},28,[2824,3323,3324],{"class":2830},"else",[2824,3326,3077],{"class":2856},[2824,3328,3330,3333,3336,3338,3340],{"class":2826,"line":3329},29,[2824,3331,3332],{"class":2830},"    for",[2824,3334,3335],{"class":2834}," status ",[2824,3337,3020],{"class":2830},[2824,3339,3299],{"class":2834},[2824,3341,3077],{"class":2856},[2824,3343,3345,3348,3350,3352,3355,3357,3360,3362,3364,3366,3368,3370,3372,3374],{"class":2826,"line":3344},30,[2824,3346,3347],{"class":2871},"        print",[2824,3349,2875],{"class":2856},[2824,3351,2933],{"class":2932},[2824,3353,3354],{"class":2881},"\"Issue: ",[2824,3356,2940],{"class":2939},[2824,3358,3359],{"class":2871},"status",[2824,3361,2946],{"class":2856},[2824,3363,2949],{"class":2856},[2824,3365,1989],{"class":2881},[2824,3367,2949],{"class":2856},[2824,3369,2957],{"class":2856},[2824,3371,2960],{"class":2939},[2824,3373,2878],{"class":2881},[2824,3375,2887],{"class":2856},[1931,3377,3379],{"id":3378},"ddex-ern-message-simplified","DDEX ERN message (simplified)",[749,3381,3382,3383,3386,3387,3390,3391,3394],{},"The core of a DDEX Electronic Release Notification boils down to three blocks: ",[753,3384,3385],{},"what"," is being released, ",[753,3388,3389],{},"who"," performs it, and ",[753,3392,3393],{},"where/how"," it can be streamed:",[2815,3396,3401],{"className":3397,"code":3398,"filename":3399,"language":3400,"meta":920,"style":920},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003CNewReleaseMessage>\n  \u003C!-- WHAT: the release -->\n  \u003CRelease>\n    \u003CICPN>0123456789012\u003C/ICPN>\n    \u003CTitle>Upbeat Jazz Fusion\u003C/Title>\n    \u003CArtist>Acme Music AI\u003C/Artist>\n    \u003CTerritory>Worldwide\u003C/Territory>\n  \u003C/Release>\n\n  \u003C!-- WHO: the sound recording -->\n  \u003CSoundRecording>\n    \u003CISRC>USXX42312345\u003C/ISRC>\n    \u003CDuration>PT3M24S\u003C/Duration>\n    \u003CArtistRole>MainArtist\u003C/ArtistRole>  \u003C!-- No \"AI\" option here -->\n  \u003C/SoundRecording>\n\n  \u003C!-- HOW: the deal terms -->\n  \u003CDeal>\n    \u003CModel>SubscriptionModel\u003C/Model>\n    \u003CUseType>OnDemandStream\u003C/UseType>\n    \u003CStartDate>2026-03-13\u003C/StartDate>\n  \u003C/Deal>\n\u003C/NewReleaseMessage>\n","ern_release.xml","xml",[1989,3402,3403,3414,3419,3429,3450,3468,3485,3501,3510,3514,3519,3528,3544,3562,3583,3591,3595,3600,3609,3627,3645,3663,3671],{"__ignoreMap":920},[2824,3404,3405,3408,3411],{"class":2826,"line":2827},[2824,3406,3407],{"class":2856},"\u003C",[2824,3409,3410],{"class":2865},"NewReleaseMessage",[2824,3412,3413],{"class":2856},">\n",[2824,3415,3416],{"class":2826,"line":921},[2824,3417,3418],{"class":2846},"  \u003C!-- WHAT: the release -->\n",[2824,3420,3421,3424,3427],{"class":2826,"line":2843},[2824,3422,3423],{"class":2856},"  \u003C",[2824,3425,3426],{"class":2865},"Release",[2824,3428,3413],{"class":2856},[2824,3430,3431,3434,3437,3440,3443,3446,3448],{"class":2826,"line":2850},[2824,3432,3433],{"class":2856},"    \u003C",[2824,3435,3436],{"class":2865},"ICPN",[2824,3438,3439],{"class":2856},">",[2824,3441,3442],{"class":2834},"0123456789012",[2824,3444,3445],{"class":2856},"\u003C/",[2824,3447,3436],{"class":2865},[2824,3449,3413],{"class":2856},[2824,3451,3452,3454,3457,3459,3462,3464,3466],{"class":2826,"line":1894},[2824,3453,3433],{"class":2856},[2824,3455,3456],{"class":2865},"Title",[2824,3458,3439],{"class":2856},[2824,3460,3461],{"class":2834},"Upbeat Jazz Fusion",[2824,3463,3445],{"class":2856},[2824,3465,3456],{"class":2865},[2824,3467,3413],{"class":2856},[2824,3469,3470,3472,3474,3476,3479,3481,3483],{"class":2826,"line":2894},[2824,3471,3433],{"class":2856},[2824,3473,2447],{"class":2865},[2824,3475,3439],{"class":2856},[2824,3477,3478],{"class":2834},"Acme Music AI",[2824,3480,3445],{"class":2856},[2824,3482,2447],{"class":2865},[2824,3484,3413],{"class":2856},[2824,3486,3487,3489,3491,3493,3495,3497,3499],{"class":2826,"line":2900},[2824,3488,3433],{"class":2856},[2824,3490,2570],{"class":2865},[2824,3492,3439],{"class":2856},[2824,3494,2573],{"class":2834},[2824,3496,3445],{"class":2856},[2824,3498,2570],{"class":2865},[2824,3500,3413],{"class":2856},[2824,3502,3503,3506,3508],{"class":2826,"line":2919},[2824,3504,3505],{"class":2856},"  \u003C/",[2824,3507,3426],{"class":2865},[2824,3509,3413],{"class":2856},[2824,3511,3512],{"class":2826,"line":2924},[2824,3513,2840],{"emptyLinePlaceholder":935},[2824,3515,3516],{"class":2826,"line":2967},[2824,3517,3518],{"class":2846},"  \u003C!-- WHO: the sound recording -->\n",[2824,3520,3521,3523,3526],{"class":2826,"line":3000},[2824,3522,3423],{"class":2856},[2824,3524,3525],{"class":2865},"SoundRecording",[2824,3527,3413],{"class":2856},[2824,3529,3530,3532,3534,3536,3538,3540,3542],{"class":2826,"line":3005},[2824,3531,3433],{"class":2856},[2824,3533,2546],{"class":2865},[2824,3535,3439],{"class":2856},[2824,3537,2549],{"class":2834},[2824,3539,3445],{"class":2856},[2824,3541,2546],{"class":2865},[2824,3543,3413],{"class":2856},[2824,3545,3546,3548,3551,3553,3556,3558,3560],{"class":2826,"line":3011},[2824,3547,3433],{"class":2856},[2824,3549,3550],{"class":2865},"Duration",[2824,3552,3439],{"class":2856},[2824,3554,3555],{"class":2834},"PT3M24S",[2824,3557,3445],{"class":2856},[2824,3559,3550],{"class":2865},[2824,3561,3413],{"class":2856},[2824,3563,3564,3566,3569,3571,3574,3576,3578,3580],{"class":2826,"line":3046},[2824,3565,3433],{"class":2856},[2824,3567,3568],{"class":2865},"ArtistRole",[2824,3570,3439],{"class":2856},[2824,3572,3573],{"class":2834},"MainArtist",[2824,3575,3445],{"class":2856},[2824,3577,3568],{"class":2865},[2824,3579,3439],{"class":2856},[2824,3581,3582],{"class":2846},"  \u003C!-- No \"AI\" option here -->\n",[2824,3584,3585,3587,3589],{"class":2826,"line":3080},[2824,3586,3505],{"class":2856},[2824,3588,3525],{"class":2865},[2824,3590,3413],{"class":2856},[2824,3592,3593],{"class":2826,"line":3115},[2824,3594,2840],{"emptyLinePlaceholder":935},[2824,3596,3597],{"class":2826,"line":3149},[2824,3598,3599],{"class":2846},"  \u003C!-- HOW: the deal terms -->\n",[2824,3601,3602,3604,3607],{"class":2826,"line":3170},[2824,3603,3423],{"class":2856},[2824,3605,3606],{"class":2865},"Deal",[2824,3608,3413],{"class":2856},[2824,3610,3611,3613,3616,3618,3621,3623,3625],{"class":2826,"line":3203},[2824,3612,3433],{"class":2856},[2824,3614,3615],{"class":2865},"Model",[2824,3617,3439],{"class":2856},[2824,3619,3620],{"class":2834},"SubscriptionModel",[2824,3622,3445],{"class":2856},[2824,3624,3615],{"class":2865},[2824,3626,3413],{"class":2856},[2824,3628,3629,3631,3634,3636,3639,3641,3643],{"class":2826,"line":3209},[2824,3630,3433],{"class":2856},[2824,3632,3633],{"class":2865},"UseType",[2824,3635,3439],{"class":2856},[2824,3637,3638],{"class":2834},"OnDemandStream",[2824,3640,3445],{"class":2856},[2824,3642,3633],{"class":2865},[2824,3644,3413],{"class":2856},[2824,3646,3647,3649,3652,3654,3657,3659,3661],{"class":2826,"line":3215},[2824,3648,3433],{"class":2856},[2824,3650,3651],{"class":2865},"StartDate",[2824,3653,3439],{"class":2856},[2824,3655,3656],{"class":2834},"2026-03-13",[2824,3658,3445],{"class":2856},[2824,3660,3651],{"class":2865},[2824,3662,3413],{"class":2856},[2824,3664,3665,3667,3669],{"class":2826,"line":3232},[2824,3666,3505],{"class":2856},[2824,3668,3606],{"class":2865},[2824,3670,3413],{"class":2856},[2824,3672,3673,3675,3677],{"class":2826,"line":3264},[2824,3674,3445],{"class":2856},[2824,3676,3410],{"class":2865},[2824,3678,3413],{"class":2856},[838,3680,3681],{},[749,3682,3683,3684,3686,3687,3689],{},"Notice how the DDEX schema has no concept of \"AI-generated.\" The ",[1989,3685,3568],{}," is ",[1989,3688,3573],{},", which traditionally means a human performer. This is exactly the gap that combining C2PA provenance with DDEX metadata would fill.",[1931,3691,3693],{"id":3692},"real-world-use-cases","Real-world use cases",[783,3695,3697,3713,3729,3745],{"className":3696},[786,787,788,789,790],[792,3698,3702],{"description":3699,"icon":3700,"title":3701},"A service like ElevenLabs or Kits.AI generates a vocal track using a licensed artist voice model.","i-lucide-mic","AI vocal cloning",[819,3703,3704,3707,3710],{},[822,3705,3706],{},"C2PA manifest declares the output as AI-generated, referencing the voice model license",[822,3708,3709],{},"DDEX metadata routes royalties to both the platform and the original voice owner",[822,3711,3712],{},"DSPs can surface an \"AI-generated vocal\" label to listeners",[792,3714,3718],{"description":3715,"icon":3716,"title":3717},"A music supervisor finds a track on a sync platform and needs to clear rights quickly.","i-lucide-radio","Sync licensing for film/TV",[819,3719,3720,3723,3726],{},[822,3721,3722],{},"C2PA chain confirms the track is an unaltered original from a known studio",[822,3724,3725],{},"DDEX rights data shows territory clearance, splits, and one-stop licensing",[822,3727,3728],{},"The supervisor can verify authenticity and clear rights in a single workflow",[792,3730,3734],{"description":3731,"icon":3732,"title":3733},"A producer builds a track using stems from Splice or Tracklib.","i-lucide-disc-3","Sample-based production",[819,3735,3736,3739,3742],{},[822,3737,3738],{},"Each stem carries a C2PA manifest linking to its original recording session",[822,3740,3741],{},"The DAW adds a new manifest referencing all source stems on export",[822,3743,3744],{},"DDEX metadata captures royalty splits between the producer and sample owners",[792,3746,3750],{"description":3747,"icon":3748,"title":3749},"A streaming platform receives a submission that sounds like a major artist from an unknown account.","i-lucide-shield-alert","Deepfake detection at DSPs",[819,3751,3752,3755,3758],{},[822,3753,3754],{},"No C2PA manifest present, or the manifest shows AI generation with no artist license",[822,3756,3757],{},"DDEX metadata claims the submitter as the performer, contradicting the audio fingerprint",[822,3759,3760],{},"Automated pipeline flags the submission for human review before it goes live",[778,3762,3764],{"id":3763},"looking-ahead","Looking ahead",[749,3766,3767,3768,1615,3771,3774],{},"The music industry is approaching a tipping point. As AI-generated content floods platforms, the demand for both ",[753,3769,3770],{},"authenticity verification",[753,3772,3773],{},"rights management"," will only grow.",[749,3776,3777],{},"The platforms that win will be the ones that treat provenance and rights as two sides of the same coin. C2PA and DDEX aren't competitors. Together, they could form the trust layer the music industry needs.",[749,3779,3780],{},"For music tech builders, the action items are clear:",[3782,3783,3784,3790,3796,3802],"ol",{},[822,3785,3786,3789],{},[753,3787,3788],{},"Embed C2PA manifests"," at the point of content creation -whether that's a DAW, an AI model, or a recording device",[822,3791,3792,3795],{},[753,3793,3794],{},"Extend DDEX workflows"," to consume and reference C2PA provenance data",[822,3797,3798,3801],{},[753,3799,3800],{},"Build cross-validation"," into ingest pipelines to catch mismatches between authenticity claims and rights declarations",[822,3803,3804,3807],{},[753,3805,3806],{},"Engage with both consortiums"," -the standards are still evolving, and the music industry's voice matters in shaping them",[749,3809,3810],{},"The question isn't whether these standards will converge -it's how quickly the industry can make it happen.",[3812,3813,3814],"style",{},"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 .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 .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 .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}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);}",{"title":920,"searchDepth":921,"depth":921,"links":3816},[3817,3821,3825,3826,3829,3834,3835,3836,3841],{"id":1925,"depth":921,"text":1926,"children":3818},[3819,3820],{"id":873,"depth":2843,"text":1933},{"id":1975,"depth":2843,"text":1976},{"id":988,"depth":921,"text":989,"children":3822},[3823,3824],{"id":2016,"depth":2843,"text":2017},{"id":2103,"depth":2843,"text":2104},{"id":2149,"depth":921,"text":2150},{"id":2320,"depth":921,"text":2321,"children":3827},[3828],{"id":2374,"depth":2843,"text":2375},{"id":2399,"depth":921,"text":2400,"children":3830},[3831,3832,3833],{"id":2406,"depth":2843,"text":2407},{"id":2424,"depth":2843,"text":2425},{"id":2459,"depth":2843,"text":2460},{"id":2595,"depth":921,"text":2596},{"id":2747,"depth":921,"text":2748},{"id":2802,"depth":921,"text":2803,"children":3837},[3838,3839,3840],{"id":2806,"depth":2843,"text":2807},{"id":3378,"depth":2843,"text":3379},{"id":3692,"depth":2843,"text":3693},{"id":3763,"depth":921,"text":3764},"2026-03-13T00:00:00.000Z","C2PA proves content is real. DDEX ensures the right people get paid. Together, could they reshape how the music industry handles trust and rights in the AI era?",[3845,3848,3851],{"question":3846,"answer":3847},"What is the difference between C2PA and DDEX?","C2PA is a content authenticity standard that cryptographically proves who created digital content and whether it was modified. DDEX is a music industry standard for exchanging commercial metadata like rights ownership, royalty splits, and release information. C2PA answers 'is this real?' while DDEX answers 'who gets paid?'",{"question":3849,"answer":3850},"Can C2PA and DDEX work together?","Yes. A music file could carry both a C2PA manifest proving its origin and creation history, and DDEX metadata ensuring correct royalty distribution. Together they provide end-to-end trust -from authenticity to payment.",{"question":3852,"answer":3853},"Why do these standards matter for AI-generated music?","AI-generated tracks blur the line between human and machine creation. C2PA can transparently label AI-generated content, while DDEX can handle the complex rights questions around who owns and profits from AI-created music.",{"src":3855},"/images/blog/musictechlab_blog_c2pa-vs-ddex.webp",{"enabled":935,"items":3857},[3858,3861,3864,3867],{"text":3859,"icon":3860},"C2PA proves content origin with cryptographic signatures; DDEX handles rights and royalty splits.","i-lucide-shield",{"text":3862,"icon":3863},"Current DDEX schemas have no concept of AI-generated content or non-human performers.","i-lucide-brain",{"text":3865,"icon":3866},"Combining both standards creates end-to-end trust from authenticity verification to payment.","i-lucide-handshake",{"text":3868,"icon":1881},"C2PA tools in Rust, JavaScript, and Python are production-ready for experimentation today.",{},{"title":3871,"description":3872},"C2PA & DDEX: Authenticity & Rights in AI Music","Compare C2PA and DDEX standards -how content provenance and rights metadata work together to solve trust and payment in the AI music era.",[1920,949,3874,3875,3876,951,3877],"AI music","content authenticity","music rights","music distribution","gAC7wVP0DrbqIReV_k8NunYO6AEVCudMp3VZZ9-1zfY",{"id":3880,"title":80,"authors":3881,"badge":3884,"body":3886,"category":927,"client":928,"date":4527,"description":4528,"extension":931,"faq":4529,"featured":935,"featuredOrder":921,"hidden":69,"image":4539,"keyTakeaways":4541,"meta":4554,"navigation":935,"path":81,"seo":4555,"status":928,"stem":82,"tags":4558,"teaser":928,"__hash__":4560,"score":2850},"posts/blog/music-data/830-ways-to-say-spotify-normalizing-music-streaming-data.md",[3882],{"name":963,"to":964,"avatar":3883},{"src":966},{"label":5,"color":3885},"#f59e0b",{"type":746,"value":3887,"toc":4516},[3888,3895,3898,3902,3905,3994,4001,4005,4012,4120,4123,4129,4140,4155,4158,4162,4165,4168,4173,4179,4183,4186,4190,4193,4277,4280,4284,4287,4353,4356,4360,4363,4493,4496,4500,4503,4510,4513],[749,3889,3890,3891,3894],{},"In our ",[763,3892,3893],{"href":77},"previous article",", we showed what a real label's download folder looks like - 18 distributors, 5 file formats, 500+ files per year. But solving the file format problem is only step one.",[749,3896,3897],{},"Open those files. The data inside is just as messy.",[778,3899,3901],{"id":3900},"the-name-problem","The name problem",[749,3903,3904],{},"Ask 18 distributors what \"Spotify\" is called. You'll get more answers than you expect:",[2022,3906,3907,3916],{},[2025,3908,3909],{},[2028,3910,3911,3913],{},[2031,3912,2578],{},[2031,3914,3915],{},"How they label Spotify",[2037,3917,3918,3928,3938,3948,3958,3966,3975,3984],{},[2028,3919,3920,3923],{},[2042,3921,3922],{},"FUGA",[2042,3924,3925],{},[1989,3926,3927],{},"Spotify",[2028,3929,3930,3933],{},[2042,3931,3932],{},"ADA",[2042,3934,3935],{},[1989,3936,3937],{},"SPOTIFY",[2028,3939,3940,3943],{},[2042,3941,3942],{},"Ingrooves",[2042,3944,3945],{},[1989,3946,3947],{},"spotify",[2028,3949,3950,3953],{},[2042,3951,3952],{},"The Orchard",[2042,3954,3955],{},[1989,3956,3957],{},"Spotify Premium",[2028,3959,3960,3963],{},[2042,3961,3962],{},"Bandcamp",[2042,3964,3965],{},"N/A",[2028,3967,3968,3971],{},[2042,3969,3970],{},"MVD",[2042,3972,3973],{},[1989,3974,3927],{},[2028,3976,3977,3980],{},[2042,3978,3979],{},"Emerald",[2042,3981,3982],{},[1989,3983,3937],{},[2028,3985,3986,3989],{},[2042,3987,3988],{},"SFM",[2042,3990,3991],{},[1989,3992,3993],{},"Spotify AB",[749,3995,3996,3997,4000],{},"That's just one platform. Now multiply across ",[753,3998,3999],{},"every retailer, every label name, and every service type"," in the dataset. The same entity appears under different names, different capitalizations, and different abbreviations depending on which distributor sent the file.",[778,4002,4004],{"id":4003},"_830-values-19-names","830 values, 19 names",[749,4006,4007,4008,4011],{},"The solution is what we call ",[753,4009,4010],{},"unions"," - normalization groups that map many raw values to one canonical name.",[783,4013,4016],{"className":4014},[903,4015,790],"justify-center",[2815,4017,4021],{"className":4018,"code":4019,"language":4020,"meta":920,"style":920},"language-mermaid shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","flowchart LR\n    subgraph raw[\"Raw Values\"]\n        A[\"Spotify\"]\n        B[\"SPOTIFY\"]\n        C[\"spotify\"]\n        D[\"Spotify Premium\"]\n        E[\"Spotify AB\"]\n        F[\"Spotify Ltd\"]\n    end\n\n    subgraph union[\"Union\"]\n        G([\"SPOTIFY\"])\n    end\n\n    A --> G\n    B --> G\n    C --> G\n    D --> G\n    E --> G\n    F --> G\n","mermaid",[1989,4022,4023,4028,4033,4038,4043,4048,4053,4058,4063,4068,4072,4077,4082,4086,4090,4095,4100,4105,4110,4115],{"__ignoreMap":920},[2824,4024,4025],{"class":2826,"line":2827},[2824,4026,4027],{"class":2834},"flowchart LR\n",[2824,4029,4030],{"class":2826,"line":921},[2824,4031,4032],{"class":2834},"    subgraph raw[\"Raw Values\"]\n",[2824,4034,4035],{"class":2826,"line":2843},[2824,4036,4037],{"class":2834},"        A[\"Spotify\"]\n",[2824,4039,4040],{"class":2826,"line":2850},[2824,4041,4042],{"class":2834},"        B[\"SPOTIFY\"]\n",[2824,4044,4045],{"class":2826,"line":1894},[2824,4046,4047],{"class":2834},"        C[\"spotify\"]\n",[2824,4049,4050],{"class":2826,"line":2894},[2824,4051,4052],{"class":2834},"        D[\"Spotify Premium\"]\n",[2824,4054,4055],{"class":2826,"line":2900},[2824,4056,4057],{"class":2834},"        E[\"Spotify AB\"]\n",[2824,4059,4060],{"class":2826,"line":2919},[2824,4061,4062],{"class":2834},"        F[\"Spotify Ltd\"]\n",[2824,4064,4065],{"class":2826,"line":2924},[2824,4066,4067],{"class":2834},"    end\n",[2824,4069,4070],{"class":2826,"line":2967},[2824,4071,2840],{"emptyLinePlaceholder":935},[2824,4073,4074],{"class":2826,"line":3000},[2824,4075,4076],{"class":2834},"    subgraph union[\"Union\"]\n",[2824,4078,4079],{"class":2826,"line":3005},[2824,4080,4081],{"class":2834},"        G([\"SPOTIFY\"])\n",[2824,4083,4084],{"class":2826,"line":3011},[2824,4085,4067],{"class":2834},[2824,4087,4088],{"class":2826,"line":3046},[2824,4089,2840],{"emptyLinePlaceholder":935},[2824,4091,4092],{"class":2826,"line":3080},[2824,4093,4094],{"class":2834},"    A --> G\n",[2824,4096,4097],{"class":2826,"line":3115},[2824,4098,4099],{"class":2834},"    B --> G\n",[2824,4101,4102],{"class":2826,"line":3149},[2824,4103,4104],{"class":2834},"    C --> G\n",[2824,4106,4107],{"class":2826,"line":3170},[2824,4108,4109],{"class":2834},"    D --> G\n",[2824,4111,4112],{"class":2826,"line":3203},[2824,4113,4114],{"class":2834},"    E --> G\n",[2824,4116,4117],{"class":2826,"line":3209},[2824,4118,4119],{"class":2834},"    F --> G\n",[749,4121,4122],{},"Here's what the union management interface looks like in practice - TIDAL alone has 10 variations, SoundCloud over 30:",[749,4124,4125],{},[976,4126],{"alt":4127,"src":4128},"Union management interface showing raw value mappings","/images/blog/musictechlab_blog_unions-admin-interface.webp",[749,4130,4131,4132,4135,4136,4139],{},"In production, this system maps ",[753,4133,4134],{},"830 raw tag values"," to just ",[753,4137,4138],{},"19 unions"," across three dimensions:",[783,4141,4143,4147,4151],{"className":4142},[786,787,878,789,790],[792,4144],{"description":4145,"title":4146},"Spotify, Amazon, YouTube, Pandora, Facebook, and more. Each with dozens of naming variations across sources.","Retailer unions",[792,4148],{"description":4149,"title":4150},"The label itself can appear under different names, abbreviations, or legal entity variations across distributors.","Label unions",[792,4152],{"description":4153,"title":4154},"Streaming, downloads, physical, sync - each distributor categorizes their services differently.","Service unions",[749,4156,4157],{},"When a file is imported, every raw value is checked against the union mappings. If it matches, the canonical name is stored alongside the original. If it doesn't, the raw value is preserved - and flagged for review.",[778,4159,4161],{"id":4160},"why-not-just-find-and-replace","Why not just find-and-replace?",[749,4163,4164],{},"Because new values appear constantly. A distributor adds a sub-brand. Another changes their internal naming. A third introduces a typo that persists for six months before anyone notices. Static find-and-replace breaks every time the data evolves.",[749,4166,4167],{},"Unions are dynamic. A non-technical user can add a new mapping through an admin interface - no code changes, no redeployment. The next import picks it up automatically.",[838,4169,4170],{},[749,4171,4172],{},"One real example: a distributor renamed their Spotify column from \"Spotify\" to \"Spotify AB\" mid-year. Without union mapping, this would have created a second \"Spotify\" in every report, splitting the data and making quarterly comparisons unreliable.",[749,4174,4175],{},[976,4176],{"alt":4177,"src":4178},"Currency exchange and data normalization","/images/blog/musictechlab_blog_currency-exchange-data.webp",[778,4180,4182],{"id":4181},"the-cherry-on-top-currencies-and-territories","The cherry on top: currencies and territories",[749,4184,4185],{},"Even after normalizing names, two more problems remain.",[1931,4187,4189],{"id":4188},"currencies","Currencies",[749,4191,4192],{},"Every distributor reports income in their own currency. And they don't even agree on what to call the currency column:",[2022,4194,4195,4207],{},[2025,4196,4197],{},[2028,4198,4199,4201,4204],{},[2031,4200,2578],{},[2031,4202,4203],{},"Column name",[2031,4205,4206],{},"Default currency",[2037,4208,4209,4221,4231,4242,4254,4266],{},[2028,4210,4211,4213,4218],{},[2042,4212,3922],{},[2042,4214,4215],{},[1989,4216,4217],{},"Original currency",[2042,4219,4220],{},"varies",[2028,4222,4223,4225,4228],{},[2042,4224,3932],{},[2042,4226,4227],{},"(file-level)",[2042,4229,4230],{},"GBP",[2028,4232,4233,4235,4240],{},[2042,4234,3942],{},[2042,4236,4237],{},[1989,4238,4239],{},"CURRENCY_CODE",[2042,4241,4230],{},[2028,4243,4244,4246,4251],{},[2042,4245,3952],{},[2042,4247,4248],{},[1989,4249,4250],{},"Preferred Currency",[2042,4252,4253],{},"USD",[2028,4255,4256,4259,4264],{},[2042,4257,4258],{},"Merlin",[2042,4260,4261],{},[1989,4262,4263],{},"Payable currency",[2042,4265,4220],{},[2028,4267,4268,4270,4275],{},[2042,4269,3970],{},[2042,4271,4272],{},[1989,4273,4274],{},"currency-code",[2042,4276,4220],{},[749,4278,4279],{},"To compare income across sources, every value needs to be converted to a single target currency using exchange rates tied to specific dates. A $1,000 Orchard payment and a £800 ADA payment aren't comparable until you normalize them.",[1931,4281,4283],{"id":4282},"territories","Territories",[749,4285,4286],{},"Countries seem straightforward - until you see how distributors label them:",[2022,4288,4289,4299],{},[2025,4290,4291],{},[2028,4292,4293,4296],{},[2031,4294,4295],{},"The same country",[2031,4297,4298],{},"Variations across sources",[2037,4300,4301,4319,4337],{},[2028,4302,4303,4306],{},[2042,4304,4305],{},"United States",[2042,4307,4308,2448,4311,2448,4314,2448,4317],{},[1989,4309,4310],{},"US",[1989,4312,4313],{},"USA",[1989,4315,4316],{},"UNITED STATES",[1989,4318,4305],{},[2028,4320,4321,4324],{},[2042,4322,4323],{},"United Kingdom",[2042,4325,4326,2448,4329,2448,4332,2448,4335],{},[1989,4327,4328],{},"UK",[1989,4330,4331],{},"GB",[1989,4333,4334],{},"UNITED KINGDOM (GB)",[1989,4336,4323],{},[2028,4338,4339,4342],{},[2042,4340,4341],{},"Czech Republic",[2042,4343,4344,2448,4347,2448,4350],{},[1989,4345,4346],{},"CZ",[1989,4348,4349],{},"CZECH REPUBLIC",[1989,4351,4352],{},"Czechia",[749,4354,4355],{},"Each variation needs to map to a standard two-letter code. Without this, \"show me all US streams\" misses half the data.",[778,4357,4359],{"id":4358},"three-layers-of-normalization","Three layers of normalization",[749,4361,4362],{},"Here's the full picture - what it actually takes to turn raw distributor data into something usable:",[783,4364,4366],{"className":4365},[903,4015,790],[2815,4367,4369],{"className":4018,"code":4368,"language":4020,"meta":920,"style":920},"flowchart TD\n    subgraph layer1[\"Layer 1: File Formats\"]\n        A[\"18 adapters\"]\n        B[\"5 formats\"]\n        C[\"500+ files/year\"]\n    end\n\n    subgraph layer2[\"Layer 2: Name Normalization\"]\n        D[\"830 raw values\"]\n        E[\"19 unions\"]\n        F[\"3 dimensions\"]\n    end\n\n    subgraph layer3[\"Layer 3: Currency & Territory\"]\n        G[\"Multiple currencies\"]\n        H[\"Exchange rates\"]\n        I[\"Country code mapping\"]\n    end\n\n    subgraph result[\"Result\"]\n        J[(\"One clean dataset\")]\n    end\n\n    layer1 --> layer2\n    layer2 --> layer3\n    layer3 --> result\n",[1989,4370,4371,4376,4381,4386,4391,4396,4400,4404,4409,4414,4419,4424,4428,4432,4437,4442,4447,4452,4456,4460,4465,4470,4474,4478,4483,4488],{"__ignoreMap":920},[2824,4372,4373],{"class":2826,"line":2827},[2824,4374,4375],{"class":2834},"flowchart TD\n",[2824,4377,4378],{"class":2826,"line":921},[2824,4379,4380],{"class":2834},"    subgraph layer1[\"Layer 1: File Formats\"]\n",[2824,4382,4383],{"class":2826,"line":2843},[2824,4384,4385],{"class":2834},"        A[\"18 adapters\"]\n",[2824,4387,4388],{"class":2826,"line":2850},[2824,4389,4390],{"class":2834},"        B[\"5 formats\"]\n",[2824,4392,4393],{"class":2826,"line":1894},[2824,4394,4395],{"class":2834},"        C[\"500+ files/year\"]\n",[2824,4397,4398],{"class":2826,"line":2894},[2824,4399,4067],{"class":2834},[2824,4401,4402],{"class":2826,"line":2900},[2824,4403,2840],{"emptyLinePlaceholder":935},[2824,4405,4406],{"class":2826,"line":2919},[2824,4407,4408],{"class":2834},"    subgraph layer2[\"Layer 2: Name Normalization\"]\n",[2824,4410,4411],{"class":2826,"line":2924},[2824,4412,4413],{"class":2834},"        D[\"830 raw values\"]\n",[2824,4415,4416],{"class":2826,"line":2967},[2824,4417,4418],{"class":2834},"        E[\"19 unions\"]\n",[2824,4420,4421],{"class":2826,"line":3000},[2824,4422,4423],{"class":2834},"        F[\"3 dimensions\"]\n",[2824,4425,4426],{"class":2826,"line":3005},[2824,4427,4067],{"class":2834},[2824,4429,4430],{"class":2826,"line":3011},[2824,4431,2840],{"emptyLinePlaceholder":935},[2824,4433,4434],{"class":2826,"line":3046},[2824,4435,4436],{"class":2834},"    subgraph layer3[\"Layer 3: Currency & Territory\"]\n",[2824,4438,4439],{"class":2826,"line":3080},[2824,4440,4441],{"class":2834},"        G[\"Multiple currencies\"]\n",[2824,4443,4444],{"class":2826,"line":3115},[2824,4445,4446],{"class":2834},"        H[\"Exchange rates\"]\n",[2824,4448,4449],{"class":2826,"line":3149},[2824,4450,4451],{"class":2834},"        I[\"Country code mapping\"]\n",[2824,4453,4454],{"class":2826,"line":3170},[2824,4455,4067],{"class":2834},[2824,4457,4458],{"class":2826,"line":3203},[2824,4459,2840],{"emptyLinePlaceholder":935},[2824,4461,4462],{"class":2826,"line":3209},[2824,4463,4464],{"class":2834},"    subgraph result[\"Result\"]\n",[2824,4466,4467],{"class":2826,"line":3215},[2824,4468,4469],{"class":2834},"        J[(\"One clean dataset\")]\n",[2824,4471,4472],{"class":2826,"line":3232},[2824,4473,4067],{"class":2834},[2824,4475,4476],{"class":2826,"line":3264},[2824,4477,2840],{"emptyLinePlaceholder":935},[2824,4479,4480],{"class":2826,"line":3269},[2824,4481,4482],{"class":2834},"    layer1 --> layer2\n",[2824,4484,4485],{"class":2826,"line":3275},[2824,4486,4487],{"class":2834},"    layer2 --> layer3\n",[2824,4489,4490],{"class":2826,"line":3290},[2824,4491,4492],{"class":2834},"    layer3 --> result\n",[749,4494,4495],{},"Most teams get stuck at Layer 1 and never even reach the name and currency problems. But without all three layers, you can't answer basic questions like \"What were our total Spotify streams in Q3, in GBP?\"",[778,4497,4499],{"id":4498},"the-payoff","The payoff",[749,4501,4502],{},"After all three normalization layers, that question becomes trivial. Filter by retailer union, filter by date range, and every value is already in GBP. One query. One answer. No spreadsheet wrangling.",[749,4504,4505,4506,4509],{},"And once the data is clean, even non-technical users can get answers. We built an ",[763,4507,4508],{"href":85},"AI-powered analytics dashboard"," that lets anyone type a question in plain English and get a chart back in seconds, no SQL required.",[749,4511,4512],{},"That's the difference between a collection of files and a data platform. We build the latter.",[3812,4514,4515],{},"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);}",{"title":920,"searchDepth":921,"depth":921,"links":4517},[4518,4519,4520,4521,4525,4526],{"id":3900,"depth":921,"text":3901},{"id":4003,"depth":921,"text":4004},{"id":4160,"depth":921,"text":4161},{"id":4181,"depth":921,"text":4182,"children":4522},[4523,4524],{"id":4188,"depth":2843,"text":4189},{"id":4282,"depth":2843,"text":4283},{"id":4358,"depth":921,"text":4359},{"id":4498,"depth":921,"text":4499},"2026-03-03T00:00:00.000Z","After solving the file format problem, the data inside is just as messy. Different names for the same platforms, labels, currencies, and territories. Here's how we normalize it.",[4530,4533,4536],{"question":4531,"answer":4532},"Why is music streaming data so inconsistent?","Every distributor uses their own naming conventions for retailers, labels, services, territories, and currencies. There is no shared standard, so the same platform can appear under dozens of different names across data sources.",{"question":4534,"answer":4535},"What is a data union in the context of music royalties?","A union is a normalization group that maps multiple raw values to one canonical name. For example, all variations of 'Spotify' across 18 distributors get mapped to a single SPOTIFY union, making cross-source analysis possible.",{"question":4537,"answer":4538},"How do currency differences affect music royalty reporting?","Distributors report income in different currencies (USD, GBP, EUR) and even label the currency column differently. To compare or aggregate income across sources, every value must be converted to a single target currency using exchange rates.",{"src":4540},"/images/blog/musictechlab_blog_830-ways-to-say-spotify.webp",{"enabled":935,"items":4542},[4543,4546,4549,4552],{"text":4544,"icon":4545},"830 raw data values map to just 19 canonical names across retailers, labels, and services.","i-lucide-database",{"text":4547,"icon":4548},"Three normalization layers are needed: file formats, name unions, and currency/territory mapping.","i-lucide-layers",{"text":4550,"icon":4551},"Unions are dynamic and admin-editable, so new naming variations need no code changes.","i-lucide-settings",{"text":4553,"icon":1887},"Without all three layers, even basic queries like total Spotify streams in Q3 are impossible.",{},{"title":4556,"description":4557},"Normalizing Music Streaming Data: 830 Values, 19 Unions | MusicTech Lab","How we normalize 830 raw data values into 19 canonical names across retailers, labels, and services. Real-world music data normalization.",[927,950,4559,951],"streaming","nkhKea-amz1NLgquVd-h3Qvo8Tq2jJzXtEx0Fmt3TeE",{"id":4562,"title":76,"authors":4563,"badge":4566,"body":4567,"category":927,"client":928,"date":5232,"description":5233,"extension":931,"faq":5234,"featured":935,"featuredOrder":2827,"hidden":69,"image":5244,"keyTakeaways":5246,"meta":5258,"navigation":935,"path":77,"seo":5259,"status":928,"stem":78,"tags":5262,"teaser":928,"__hash__":5264,"score":2850},"posts/blog/music-data/13-distributors-5-file-formats-zero-standards-the-reality-of-music-royalty-data.md",[4564],{"name":963,"to":964,"avatar":4565},{"src":966},{"label":1901,"color":1902},{"type":746,"value":4568,"toc":5224},[4569,4572,4575,4579,4582,4863,4870,4874,4877,4896,4899,4903,4906,4909,4920,4925,4931,4935,4938,5038,5041,5045,5048,5194,5197,5208,5215,5219,5222],[749,4570,4571],{},"Every month, an independent label receives royalty reports from over a dozen distributors. Not a single one looks the same.",[749,4573,4574],{},"This isn't a hypothetical. This is what a real download folder looks like when you work with music royalty data at scale.",[778,4576,4578],{"id":4577},"the-wall-of-files","The wall of files",[749,4580,4581],{},"Here's a small sample of actual filenames from a single label's monthly data intake -anonymised, but otherwise untouched:",[2022,4583,4584,4599],{},[2025,4585,4586],{},[2028,4587,4588,4590,4593,4596],{},[2031,4589,2578],{},[2031,4591,4592],{},"Example Filename",[2031,4594,4595],{},"Format",[2031,4597,4598],{},"File Size",[2037,4600,4601,4616,4631,4646,4661,4675,4689,4702,4716,4731,4747,4762,4777,4792,4806,4820,4834,4849],{},[2028,4602,4603,4605,4610,4613],{},[2042,4604,3922],{},[2042,4606,4607],{},[1989,4608,4609],{},"FUGA_Statement_June_2024.xlsx",[2042,4611,4612],{},".xlsx",[2042,4614,4615],{},"~1 MB",[2028,4617,4618,4620,4625,4628],{},[2042,4619,3932],{},[2042,4621,4622],{},[1989,4623,4624],{},"SR1_Distribution_Aug_24_-_00054061_-_2024-8.xlsb",[2042,4626,4627],{},".xlsb",[2042,4629,4630],{},"~70 KB",[2028,4632,4633,4635,4640,4643],{},[2042,4634,3942],{},[2042,4636,4637],{},[1989,4638,4639],{},"20240801-1496-DS-GBP_Digital_Sales.csv",[2042,4641,4642],{},".csv",[2042,4644,4645],{},"up to 226 MB",[2028,4647,4648,4650,4655,4658],{},[2042,4649,3952],{},[2042,4651,4652],{},[1989,4653,4654],{},"The_Orchard20240821_Jun2024_fullreport_catalogue_US.xls",[2042,4656,4657],{},".xls",[2042,4659,4660],{},"up to 700 MB",[2028,4662,4663,4665,4670,4672],{},[2042,4664,3962],{},[2042,4666,4667],{},[1989,4668,4669],{},"bandcamp_rev_report_20240801-20240831.csv",[2042,4671,4642],{},[2042,4673,4674],{},"~6 KB",[2028,4676,4677,4679,4684,4686],{},[2042,4678,3970],{},[2042,4680,4681],{},[1989,4682,4683],{},"MVD_Statement_DigitalSales_2024-07.xls",[2042,4685,4657],{},[2042,4687,4688],{},"~12 KB",[2028,4690,4691,4693,4698,4700],{},[2042,4692,3970],{},[2042,4694,4695],{},[1989,4696,4697],{},"MVD_Statement_DigitalSales_2024-07.xlsx",[2042,4699,4612],{},[2042,4701,4688],{},[2028,4703,4704,4706,4711,4713],{},[2042,4705,3979],{},[2042,4707,4708],{},[1989,4709,4710],{},"Emerald_202408_DSR.csv",[2042,4712,4642],{},[2042,4714,4715],{},"~46 MB",[2028,4717,4718,4721,4726,4728],{},[2042,4719,4720],{},"Safari Records",[2042,4722,4723],{},[1989,4724,4725],{},"Safari_Records_202408_DSR.xlsx",[2042,4727,4612],{},[2042,4729,4730],{},"~2 MB",[2028,4732,4733,4736,4741,4744],{},[2042,4734,4735],{},"ADA (legacy)",[2042,4737,4738],{},[1989,4739,4740],{},"ADAOCT1.XLS",[2042,4742,4743],{},".XLS",[2042,4745,4746],{},"up to 150 MB",[2028,4748,4749,4752,4757,4759],{},[2042,4750,4751],{},"MAC",[2042,4753,4754],{},[1989,4755,4756],{},"MAC_Developments_iTunes_August_2024.xlsx",[2042,4758,4612],{},[2042,4760,4761],{},"~49 KB",[2028,4763,4764,4767,4772,4775],{},[2042,4765,4766],{},"Absolute",[2042,4768,4769],{},[1989,4770,4771],{},"Absolute_2024021.CSV",[2042,4773,4774],{},".CSV",[2042,4776,4645],{},[2028,4778,4779,4782,4787,4789],{},[2042,4780,4781],{},"Qello",[2042,4783,4784],{},[1989,4785,4786],{},"DetailedSheet_Records_Ltd_20240801_20240831.xlsx",[2042,4788,4612],{},[2042,4790,4791],{},"~10 KB",[2028,4793,4794,4796,4801,4803],{},[2042,4795,3988],{},[2042,4797,4798],{},[1989,4799,4800],{},"sfmaug2024.xlsx",[2042,4802,4612],{},[2042,4804,4805],{},"~2.5 MB",[2028,4807,4808,4811,4816,4818],{},[2042,4809,4810],{},"BOFM",[2042,4812,4813],{},[1989,4814,4815],{},"BOFM_Aug2024.xlsx",[2042,4817,4612],{},[2042,4819,4805],{},[2028,4821,4822,4825,4830,4832],{},[2042,4823,4824],{},"Dome Records",[2042,4826,4827],{},[1989,4828,4829],{},"Dome_Records_202408_DSR.csv",[2042,4831,4642],{},[2042,4833,4615],{},[2028,4835,4836,4839,4844,4846],{},[2042,4837,4838],{},"MDR",[2042,4840,4841],{},[1989,4842,4843],{},"MDR_May-2024_65634.92_Records.xlsx",[2042,4845,4612],{},[2042,4847,4848],{},"~500 KB",[2028,4850,4851,4853,4858,4860],{},[2042,4852,4258],{},[2042,4854,4855],{},[1989,4856,4857],{},"Merlin_Nov24_eg.for.jack.xlsx",[2042,4859,4612],{},[2042,4861,4862],{},"~703 KB",[749,4864,4865,4866,4869],{},"That's ",[753,4867,4868],{},"18 adapters across 500+ files per year"," -each with its own naming convention, file format, and internal structure. From a 6 KB Bandcamp CSV to a single Orchard report that can reach 700 MB.",[778,4871,4873],{"id":4872},"spot-the-pattern","Spot the pattern",[749,4875,4876],{},"Go ahead, try. You won't find one.",[783,4878,4880,4884,4888,4892],{"className":4879},[786,787,788,789,790],[792,4881],{"description":4882,"title":4883},"`.xlsx` · `.xlsb` · `.xls` · `.XLS` · `.csv` · `.CSV`","5 file formats",[792,4885],{"description":4886,"title":4887},"`2024-07` · `202408` · `Aug_24` · `August_2024` · `20240801-20240831` · `2024021`","6 date conventions in filenames",[792,4889],{"description":4890,"title":4891},"Some distributors send both `.xls` and `.xlsx` versions of the exact same data.","Same report, multiple formats",[792,4893],{"description":4894,"title":4895},"camelCase, ALLCAPS, underscores, hyphens, internal reference numbers, random hash suffixes.","No naming standard",[749,4897,4898],{},"And that's just the filenames. Open these files and you'll find different column names for the same data, different date formats inside the cells, different encodings, and multi-sheet workbooks where each sheet follows its own rules.",[778,4900,4902],{"id":4901},"why-this-matters","Why this matters",[749,4904,4905],{},"Someone has to make sense of all this. Every month.",[749,4907,4908],{},"For most independent labels, that means hours of manual work -copying data between spreadsheets, reformatting dates, matching column names, fixing encoding issues that turn artist names into garbled text.",[749,4910,4911,4912,4915,4916,4919],{},"The cost isn't just time. It's ",[753,4913,4914],{},"delayed royalty payments"," to artists. It's ",[753,4917,4918],{},"reporting errors"," that erode trust. It's the finance team spending their week on data cleanup instead of analysis.",[838,4921,4922],{},[749,4923,4924],{},"One distributor changed their report format mid-year without notice. The same filename pattern, but completely different column structure inside. Manual processes break silently when this happens.",[749,4926,4927],{},[976,4928],{"alt":4929,"src":4930},"Someone working on a laptop with spreadsheet data","/images/blog/musictechlab_blog_royalty-data-spreadsheet-laptop.webp",[778,4932,4934],{"id":4933},"how-teams-try-to-solve-this","How teams try to solve this",[749,4936,4937],{},"There's more than one way to tackle this problem. Here's how the most common approaches compare:",[2022,4939,4940,4959],{},[2025,4941,4942],{},[2028,4943,4944,4947,4950,4953,4956],{},[2031,4945,4946],{},"Approach",[2031,4948,4949],{},"Setup effort",[2031,4951,4952],{},"Maintenance",[2031,4954,4955],{},"Handles format changes",[2031,4957,4958],{},"Scales with new sources",[2037,4960,4961,4980,5000,5019],{},[2028,4962,4963,4968,4971,4974,4977],{},[2042,4964,4965],{},[753,4966,4967],{},"Manual spreadsheets",[2042,4969,4970],{},"None",[2042,4972,4973],{},"Hours every month",[2042,4975,4976],{},"Breaks silently",[2042,4978,4979],{},"Every new source = more hours",[2028,4981,4982,4988,4991,4994,4997],{},[2042,4983,4984,4987],{},[753,4985,4986],{},"Generic ETL tools"," (Fivetran, Airbyte)",[2042,4989,4990],{},"Medium",[2042,4992,4993],{},"Low",[2042,4995,4996],{},"Limited - connectors are generic",[2042,4998,4999],{},"Only if a connector exists",[2028,5001,5002,5007,5010,5013,5016],{},[2042,5003,5004],{},[753,5005,5006],{},"Custom Python scripts",[2042,5008,5009],{},"High",[2042,5011,5012],{},"High - fragile, hard to maintain",[2042,5014,5015],{},"Depends on the developer",[2042,5017,5018],{},"Every new source = new script",[2028,5020,5021,5026,5029,5032,5035],{},[2042,5022,5023],{},[753,5024,5025],{},"Adapter-based pipeline",[2042,5027,5028],{},"High upfront",[2042,5030,5031],{},"Low - each adapter is isolated",[2042,5033,5034],{},"Adapter update, no side effects",[2042,5036,5037],{},"Add an adapter, done",[749,5039,5040],{},"Generic ETL tools work well for standardised APIs and databases. But music royalty data doesn't come from APIs - it comes from email attachments, FTP servers, and distributor portals. Each source is its own special case. That's why an adapter-based approach wins here: each distributor gets its own parser, isolated from the rest, easy to update when formats change.",[778,5042,5044],{"id":5043},"one-clean-dataset","One clean dataset",[749,5046,5047],{},"Here's what the pipeline looks like in practice:",[2815,5049,5051],{"className":4018,"code":5050,"language":4020,"meta":920,"style":920},"flowchart LR\n    subgraph sources[\"Raw Files\"]\n        A[\".xlsx\"]\n        B[\".xlsb\"]\n        C[\".xls\"]\n        D[\".csv\"]\n    end\n\n    subgraph adapters[\"Adapter Layer\"]\n        E[\"FUGA\"]\n        F[\"ADA\"]\n        G[\"Orchard\"]\n        H[\"Bandcamp\"]\n        I[\"+ 14 more\"]\n    end\n\n    subgraph output[\"Unified Output\"]\n        J[(\"Clean dataset\")]\n    end\n\n    A --> E\n    B --> F\n    C --> G\n    D --> H\n\n    E --> J\n    F --> J\n    G --> J\n    H --> J\n    I --> J\n",[1989,5052,5053,5057,5062,5067,5072,5077,5082,5086,5090,5095,5100,5105,5110,5115,5120,5124,5128,5133,5138,5142,5146,5151,5156,5160,5165,5169,5174,5179,5184,5189],{"__ignoreMap":920},[2824,5054,5055],{"class":2826,"line":2827},[2824,5056,4027],{"class":2834},[2824,5058,5059],{"class":2826,"line":921},[2824,5060,5061],{"class":2834},"    subgraph sources[\"Raw Files\"]\n",[2824,5063,5064],{"class":2826,"line":2843},[2824,5065,5066],{"class":2834},"        A[\".xlsx\"]\n",[2824,5068,5069],{"class":2826,"line":2850},[2824,5070,5071],{"class":2834},"        B[\".xlsb\"]\n",[2824,5073,5074],{"class":2826,"line":1894},[2824,5075,5076],{"class":2834},"        C[\".xls\"]\n",[2824,5078,5079],{"class":2826,"line":2894},[2824,5080,5081],{"class":2834},"        D[\".csv\"]\n",[2824,5083,5084],{"class":2826,"line":2900},[2824,5085,4067],{"class":2834},[2824,5087,5088],{"class":2826,"line":2919},[2824,5089,2840],{"emptyLinePlaceholder":935},[2824,5091,5092],{"class":2826,"line":2924},[2824,5093,5094],{"class":2834},"    subgraph adapters[\"Adapter Layer\"]\n",[2824,5096,5097],{"class":2826,"line":2967},[2824,5098,5099],{"class":2834},"        E[\"FUGA\"]\n",[2824,5101,5102],{"class":2826,"line":3000},[2824,5103,5104],{"class":2834},"        F[\"ADA\"]\n",[2824,5106,5107],{"class":2826,"line":3005},[2824,5108,5109],{"class":2834},"        G[\"Orchard\"]\n",[2824,5111,5112],{"class":2826,"line":3011},[2824,5113,5114],{"class":2834},"        H[\"Bandcamp\"]\n",[2824,5116,5117],{"class":2826,"line":3046},[2824,5118,5119],{"class":2834},"        I[\"+ 14 more\"]\n",[2824,5121,5122],{"class":2826,"line":3080},[2824,5123,4067],{"class":2834},[2824,5125,5126],{"class":2826,"line":3115},[2824,5127,2840],{"emptyLinePlaceholder":935},[2824,5129,5130],{"class":2826,"line":3149},[2824,5131,5132],{"class":2834},"    subgraph output[\"Unified Output\"]\n",[2824,5134,5135],{"class":2826,"line":3170},[2824,5136,5137],{"class":2834},"        J[(\"Clean dataset\")]\n",[2824,5139,5140],{"class":2826,"line":3203},[2824,5141,4067],{"class":2834},[2824,5143,5144],{"class":2826,"line":3209},[2824,5145,2840],{"emptyLinePlaceholder":935},[2824,5147,5148],{"class":2826,"line":3215},[2824,5149,5150],{"class":2834},"    A --> E\n",[2824,5152,5153],{"class":2826,"line":3232},[2824,5154,5155],{"class":2834},"    B --> F\n",[2824,5157,5158],{"class":2826,"line":3264},[2824,5159,4104],{"class":2834},[2824,5161,5162],{"class":2826,"line":3269},[2824,5163,5164],{"class":2834},"    D --> H\n",[2824,5166,5167],{"class":2826,"line":3275},[2824,5168,2840],{"emptyLinePlaceholder":935},[2824,5170,5171],{"class":2826,"line":3290},[2824,5172,5173],{"class":2834},"    E --> J\n",[2824,5175,5176],{"class":2826,"line":3304},[2824,5177,5178],{"class":2834},"    F --> J\n",[2824,5180,5181],{"class":2826,"line":3321},[2824,5182,5183],{"class":2834},"    G --> J\n",[2824,5185,5186],{"class":2826,"line":3329},[2824,5187,5188],{"class":2834},"    H --> J\n",[2824,5190,5191],{"class":2826,"line":3344},[2824,5192,5193],{"class":2834},"    I --> J\n",[749,5195,5196],{},"Every file goes through its format-specific adapter - handling encoding, column mapping, date parsing, and multi-sheet logic. What comes out the other side is one consistent dataset: same columns, same date format, same encoding. Ready for analysis, reporting, and artist payouts.",[749,5198,5199,5200,5203,5204,5207],{},"But consistent columns are only the beginning. The data inside those files is ",[763,5201,5202],{"href":81},"just as messy"," - 830 raw values that need mapping to 19 canonical names before you can run a single meaningful query. And once the data is truly clean, it opens the door to ",[763,5205,5206],{"href":85},"AI-powered analytics"," where business users ask questions in plain English and get charts back in seconds.",[749,5209,5210,5211,5214],{},"That's what we build at MusicTech Lab. Not another dashboard on top of messy data - but the ",[753,5212,5213],{},"data layer underneath"," that turns chaos into clarity.",[778,5216,5218],{"id":5217},"looks-familiar","Looks familiar?",[749,5220,5221],{},"If your monthly royalty workflow involves more spreadsheet wrangling than actual analysis, we should talk. We've built data pipelines for independent labels handling exactly this kind of complexity - and we can do the same for you.",[3812,5223,4515],{},{"title":920,"searchDepth":921,"depth":921,"links":5225},[5226,5227,5228,5229,5230,5231],{"id":4577,"depth":921,"text":4578},{"id":4872,"depth":921,"text":4873},{"id":4901,"depth":921,"text":4902},{"id":4933,"depth":921,"text":4934},{"id":5043,"depth":921,"text":5044},{"id":5217,"depth":921,"text":5218},"2026-02-27T00:00:00.000Z","Every month, independent labels receive royalty reports from over a dozen distributors. No two look the same. Here's what that actually looks like.",[5235,5238,5241],{"question":5236,"answer":5237},"Why do music distributors use different file formats?","There is no industry-wide standard for royalty report delivery. Each distributor built their own reporting system independently, resulting in different file formats, column names, date conventions, and encodings.",{"question":5239,"answer":5240},"What file formats are used in music royalty reporting?","Common formats include XLSX (modern Excel), XLSB (binary Excel), XLS (legacy Excel), and CSV with various encodings (UTF-8, UTF-16, ISO-8859-1). Some distributors send the same report in multiple formats.",{"question":5242,"answer":5243},"How can labels automate royalty data processing?","By building format-aware adapters that recognise each distributor's file structure and automatically normalise everything into a single, clean dataset -eliminating manual cleanup and reducing errors.",{"src":5245},"/images/blog/musictechlab_blog_13-distributors-5-file-formats-zero-standards.webp",{"enabled":935,"items":5247},[5248,5251,5254,5256],{"text":5249,"icon":5250},"18 adapters parse 500+ files per year from 13 distributors in 5 different formats.","i-lucide-blocks",{"text":5252,"icon":5253},"File sizes range from 6 KB (Bandcamp) to 700 MB (The Orchard) with zero naming standards.","i-lucide-file-text",{"text":5255,"icon":4548},"Adapter-based pipelines isolate each source, making format changes safe and side-effect-free.",{"text":5257,"icon":1887},"Manual spreadsheet processing delays royalty payments and introduces silent reporting errors.",{},{"title":5260,"description":5261},"Music Royalty Data Chaos: 13 Distributors, 5 Formats | MusicTech Lab","See the real complexity of music royalty reporting -different file formats, naming conventions, and schemas from every distributor. Learn how automation solves it.",[927,950,5263,4559,951],"royalties","RALDAG90DAM9IgwQPuVrQkFWVhTDlAAddo9XQWvnld4",1780305216762]