{"id":6725,"date":"2025-06-05T12:38:47","date_gmt":"2025-06-05T10:38:47","guid":{"rendered":"https:\/\/www.pschatzmann.ch\/home\/?p=6725"},"modified":"2025-06-09T09:47:39","modified_gmt":"2025-06-09T07:47:39","slug":"vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools","status":"publish","type":"post","link":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/","title":{"rendered":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools"},"content":{"rendered":"<p>Last week I was asked, if my <a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\">Arduino Audio Tools<\/a> project was <strong>supporting the playback of M4A files<\/strong>, which it didn&#8217;t: but I thought that would be quite a good opportunity to try out <strong>Vibe Coding<\/strong>,\u00a0 since this problem space is well documented and quite established it seemed to be quite a good fit. Needless to say that at that point of time I did not know anything about <strong>M4A<\/strong>. So I just asked Claude to generate me an audio file extractor class for AAC which follows my Container API.<\/p>\n<p>And it did <strong>generate quite a lot of detailed code<\/strong> that at first glace was looking very promising. But running some tests proved that it did not work and after looking at the code and the execution logic in the debugger I came to the concolusion that this is <strong>hopeless and impossible to fix<\/strong>!<\/p>\n<p>Then I had quite some detailed discussion with ChatGPT which was leading me to a better understanding what needs to be done:<\/p>\n<ol>\n<li><strong>Parse the MP4 container<\/strong> format and handle the relevant boxes only<\/li>\n<li>Build a <strong>sample table<\/strong> which was giving the record sizes to be played back<\/li>\n<li>For <strong>AAC<\/strong> get the profile, sample rate index and channel index and with this build and add an adts header before the samples<\/li>\n<li>For <strong>ALAC<\/strong> data extract the magic cookie and provide it to the decoder<\/li>\n<li>Return the audio data which is contained in the mdat box so that it can be sent to a decoder.<\/li>\n<\/ol>\n<h3>The M4A Audio Format<\/h3>\n<p data-start=\"85\" data-end=\"446\">The <strong>M4A audio format<\/strong> is based on the <strong>MP4 container<\/strong> structure, which organizes data into a hierarchy of <em data-start=\"188\" data-end=\"195\">boxes<\/em>. Each box begins with a 4-byte big-endian size field, followed by a 4-byte type identifier. Container boxes can nest other boxes and typically contain no data of their own, although exceptions exist. In contrast, non-container boxes hold actual data.<\/p>\n<p data-start=\"448\" data-end=\"933\">Audio samples are stored in the <code data-start=\"480\" data-end=\"486\">mdat<\/code> box, but to extract them correctly, information from the <code data-start=\"544\" data-end=\"550\">stsz<\/code> box is required. The <code data-start=\"572\" data-end=\"578\">stsz<\/code> box indicates the total number of samples and either a fixed sample size or, if the size is zero, a table of individual sample sizes. This data is essential to determine how many bytes to read from <code data-start=\"777\" data-end=\"783\">mdat<\/code> for each sample. Additionally, the child boxes within the <code data-start=\"842\" data-end=\"848\">stsd<\/code> box reveal the audio format\u2014such as <code data-start=\"885\" data-end=\"891\">alac<\/code> (Apple Lossless), <code data-start=\"910\" data-end=\"916\">mp4a<\/code> (AAC), or <code data-start=\"927\" data-end=\"932\">mp3<\/code>.<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: center;\"><strong><em>How to eat an elephant: cut him up into little pieces!<\/em><\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>So, I decided to split up the problem into different C++classes:<\/p>\n<h3>The MP4 Parser<\/h3>\n<p>I expected to be able to find an existing <strong>simple, lean and tested MP4 parser <\/strong>which would run on a Microcontroller that provides a simple callback API where I can just plug in some callbacks with the relevant logic, and to my big surprise <strong>I found nothing<\/strong>!<\/p>\n<p>So I was <strong>forced do this myself<\/strong> and I wrote and tested my <a href=\"https:\/\/pschatzmann.github.io\/arduino-audio-tools\/classaudio__tools_1_1_m_p4_parser.html\">MP4Parser<\/a> class which, to keep things simple, expects each box to fit into the actual RAM buffer. Here I had quite some surprises: In some rare cases it did not find a valid box at the expected location, so I added some fallback error handling that just scans for the next box and reports the skiped data under the last box type.<\/p>\n<p>As a next step, I was extending this with a MP4ParserIncremental class which removes this restriction and can provide the box content <strong>incrementally<\/strong> when the buffer is too small. After that functionality was tested, I integrated it back into the MP4Parser.<\/p>\n<p><em>This was quit simple to test: just execute the test sketch and check if you find the boxes at the indicated locations!<\/em><\/p>\n<h3>Extracting the Audio Data<\/h3>\n<p>Next I decided to have a separate <a href=\"https:\/\/pschatzmann.github.io\/arduino-audio-tools\/classaudio__tools_1_1_m4_a_audio_demuxer.html\">M4AAudioDemuxer<\/a> class which implements all the necessary <strong>parsing data callbacks<\/strong> and data extraction logic and provides the the result as <a href=\"https:\/\/pschatzmann.github.io\/arduino-audio-tools\/structaudio__tools_1_1_m4_a_audio_demuxer_1_1_frame.html\">frame<\/a> entries in a callback. This class basically<\/p>\n<ul>\n<li>forwards the written data to the parser<\/li>\n<li>implements the data M4A extraction logic<\/li>\n<li>and provides the result via a callback<\/li>\n<\/ul>\n<p>So this class is where the major work was done.\u00a0 With the parsing issues out of the way, I could concentrate on the logical issues. The two major ones were the following:<\/p>\n<ul>\n<li>The proposed logic from Claude for the extraction of the <strong>AAC profile, sample rate index and channel index<\/strong> did just lead to wrong data. I was trying quite some alternative AI models until I was proposed with a working solution.<\/li>\n<li>The proposed logic for the <strong>extraction of the alac magic cookie<\/strong> was also giving wrong values: until I figured out that there is an alac box in the alac box that contains the correct data.<\/li>\n<\/ul>\n<p>With these issues out of the way the decoding of audio stared to work&#8230;<\/p>\n<h3>The Container API<\/h3>\n<p>The final <a href=\"https:\/\/pschatzmann.github.io\/arduino-audio-tools\/classaudio__tools_1_1_container_m4_a.html\">ContainerM4A<\/a> which is a ContainerDecoder subclass was quite simple to implement:<\/p>\n<ul>\n<li>Get a <a href=\"https:\/\/pschatzmann.github.io\/arduino-audio-tools\/classaudio__tools_1_1_multi_decoder.html#acba365cc28eb702040c382646cfb0a7a\">MultiDecoder<\/a> via the constructor, so that we can support the relevant audio formats: AAC and ALAC<\/li>\n<li>Just subscribe to the data provided by the M4AAudioDemuxer callback<\/li>\n<li>When receiving a Frame from the callback, just select the right decoder and write the data to it.<\/li>\n<\/ul>\n<h3>Example Arduino Sketch<\/h3>\n<p>An <a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\/blob\/main\/examples\/examples-audiokit\/streams-sd_m4a-audiokit\/streams-sd_m4a-audiokit.ino\">example sketch can be found on Github<\/a>: I was using an <a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\/wiki\/Audio-Boards#esp32-a1s-based-audio-boards-audiokit-lyrat\">AudioKit<\/a> for testing, but you can easily adapt this logic to work with any other supported output type.<\/p>\n<p>And there is also an <a href=\"https:\/\/github.com\/pschatzmann\/arduino-audio-tools\/tree\/main\/examples\/examples-player\/player-sd_m4a-audiokit\">example using the AudioPlayer<\/a>:\u00a0 You can use a single MultiDecoder both for the AudioPlayer and the ContainerM4A or you can use the MultiDecoder only for the ContainerM4A and provide the container to the AudioPlayer or finally you can use two separate MultiDecoder for clearly specifying what audio types the AudioPlayer should support and what types the ContainerM4A should support.<\/p>\n<div>\n<h3>Caveats<\/h3>\n<ul>\n<li>The M4A file format <strong>needs quite a lot of RAM<\/strong> to store the sample table, so don&#8217;t even try this w\/o enough PSRAM!<\/li>\n<li>The M4A need to be stored in <strong>streaming format<\/strong> where the mdat box (with the audio data) is at the end. Some files do not follow this logic: thouse need to be processed twice!<\/li>\n<\/ul>\n<h3>Outlook<\/h3>\n<p>I am planning to provide an Implentation where the API works with an <strong>Arduino File<\/strong>: with this we do not need to store the sample table in memory, but we can read it directly from the file when needed. This is much more memory efficient&#8230;<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n<pre><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Last week I was asked, if my Arduino Audio Tools project was supporting the playback of M4A files, which it didn&#8217;t: but I thought that would be quite a good opportunity to try out Vibe Coding,\u00a0 since this problem space is well documented and quite established it seemed to be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6726,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[20,22],"tags":[59],"class_list":["post-6725","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-arduino","category-machine-sound","tag-m4a"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann\" \/>\n<meta property=\"og:description\" content=\"Last week I was asked, if my Arduino Audio Tools project was supporting the playback of M4A files, which it didn&#8217;t: but I thought that would be quite a good opportunity to try out Vibe Coding,\u00a0 since this problem space is well documented and quite established it seemed to be [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/\" \/>\n<meta property=\"og:site_name\" content=\"Phil Schatzmann\" \/>\n<meta property=\"article:published_time\" content=\"2025-06-05T10:38:47+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-09T07:47:39+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"196\" \/>\n\t<meta property=\"og:image:height\" content=\"257\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"pschatzmann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"pschatzmann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/\"},\"author\":{\"name\":\"pschatzmann\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"headline\":\"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools\",\"datePublished\":\"2025-06-05T10:38:47+00:00\",\"dateModified\":\"2025-06-09T07:47:39+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/\"},\"wordCount\":1072,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/m4a.jpeg\",\"keywords\":[\"M4A\"],\"articleSection\":[\"Arduino\",\"Machine Sound\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/\",\"name\":\"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/m4a.jpeg\",\"datePublished\":\"2025-06-05T10:38:47+00:00\",\"dateModified\":\"2025-06-09T07:47:39+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/m4a.jpeg\",\"contentUrl\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/m4a.jpeg\",\"width\":196,\"height\":257},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/2025\\\/06\\\/05\\\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#website\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/\",\"name\":\"Phil Schatzmann Consulting\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/home\\\/#\\\/schema\\\/person\\\/73a53638a4e34e8373405fd737dac9b1\",\"name\":\"pschatzmann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"url\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"contentUrl\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\",\"width\":305,\"height\":305,\"caption\":\"pschatzmann\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.pschatzmann.ch\\\/wp-content\\\/uploads\\\/2022\\\/08\\\/pschatzmann.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/","og_locale":"en_US","og_type":"article","og_title":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann","og_description":"Last week I was asked, if my Arduino Audio Tools project was supporting the playback of M4A files, which it didn&#8217;t: but I thought that would be quite a good opportunity to try out Vibe Coding,\u00a0 since this problem space is well documented and quite established it seemed to be [&hellip;]","og_url":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/","og_site_name":"Phil Schatzmann","article_published_time":"2025-06-05T10:38:47+00:00","article_modified_time":"2025-06-09T07:47:39+00:00","og_image":[{"width":196,"height":257,"url":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg","type":"image\/jpeg"}],"author":"pschatzmann","twitter_card":"summary_large_image","twitter_misc":{"Written by":"pschatzmann","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#article","isPartOf":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/"},"author":{"name":"pschatzmann","@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"headline":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools","datePublished":"2025-06-05T10:38:47+00:00","dateModified":"2025-06-09T07:47:39+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/"},"wordCount":1072,"commentCount":0,"publisher":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"image":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#primaryimage"},"thumbnailUrl":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg","keywords":["M4A"],"articleSection":["Arduino","Machine Sound"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/","url":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/","name":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools - Phil Schatzmann","isPartOf":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#primaryimage"},"image":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#primaryimage"},"thumbnailUrl":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg","datePublished":"2025-06-05T10:38:47+00:00","dateModified":"2025-06-09T07:47:39+00:00","breadcrumb":{"@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#primaryimage","url":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg","contentUrl":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2025\/06\/m4a.jpeg","width":196,"height":257},{"@type":"BreadcrumbList","@id":"https:\/\/www.pschatzmann.ch\/home\/2025\/06\/05\/vibe-coding-adding-m4a-audio-playback-support-to-the-audiotools\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pschatzmann.ch\/home\/"},{"@type":"ListItem","position":2,"name":"Vibe Coding: Adding M4A Audio Playback Support to the AudioTools"}]},{"@type":"WebSite","@id":"https:\/\/www.pschatzmann.ch\/home\/#website","url":"https:\/\/www.pschatzmann.ch\/home\/","name":"Phil Schatzmann Consulting","description":"","publisher":{"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pschatzmann.ch\/home\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.pschatzmann.ch\/home\/#\/schema\/person\/73a53638a4e34e8373405fd737dac9b1","name":"pschatzmann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","url":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","contentUrl":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png","width":305,"height":305,"caption":"pschatzmann"},"logo":{"@id":"https:\/\/www.pschatzmann.ch\/wp-content\/uploads\/2022\/08\/pschatzmann.png"}}]}},"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6725","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/comments?post=6725"}],"version-history":[{"count":16,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6725\/revisions"}],"predecessor-version":[{"id":6748,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/posts\/6725\/revisions\/6748"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/media\/6726"}],"wp:attachment":[{"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/media?parent=6725"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/categories?post=6725"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pschatzmann.ch\/home\/wp-json\/wp\/v2\/tags?post=6725"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}